wogiflow 1.0.47 → 1.0.48

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.
@@ -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
@@ -0,0 +1,441 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Codex CLI Bridge
5
+ *
6
+ * Generates AGENTS.md and .codex/config.toml from WogiFlow configuration.
7
+ * Provides soft parity with Claude Code/Gemini CLI - same rules, same memory,
8
+ * but enforcement is advisory (Codex lacks pre-operation hooks).
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const BaseBridge = require('./base-bridge');
14
+
15
+ // Try to load Handlebars, fall back to inline templates if not available
16
+ let Handlebars;
17
+ try {
18
+ Handlebars = require('handlebars');
19
+ } catch {
20
+ Handlebars = null;
21
+ }
22
+
23
+ // ============================================================
24
+ // Codex Bridge Class
25
+ // ============================================================
26
+
27
+ class CodexBridge extends BaseBridge {
28
+ constructor(options = {}) {
29
+ super('codex', options);
30
+ }
31
+
32
+ // ==================== Abstract Method Implementations ====================
33
+
34
+ getCliFolder() {
35
+ return '.codex';
36
+ }
37
+
38
+ getRulesFileName() {
39
+ return 'AGENTS.md';
40
+ }
41
+
42
+ getSkillsPath() {
43
+ return path.join('.codex', 'skills');
44
+ }
45
+
46
+ getRulesPath() {
47
+ return path.join('.codex', 'rules');
48
+ }
49
+
50
+ /**
51
+ * Generate AGENTS.md content
52
+ */
53
+ generateRulesContent(config) {
54
+ const context = this.buildContext(config);
55
+
56
+ // Try to use Handlebars template with proper error handling
57
+ if (Handlebars) {
58
+ try {
59
+ const templatePath = path.join(this.projectDir, this.workflowDir, 'templates', 'agents-md.hbs');
60
+ if (fs.existsSync(templatePath)) {
61
+ const templateSource = fs.readFileSync(templatePath, 'utf-8');
62
+ const template = Handlebars.compile(templateSource);
63
+ return template(context);
64
+ }
65
+ } catch (err) {
66
+ // Template failed - fall through to inline generation
67
+ this.log(`Template generation failed, using fallback: ${err.message}`);
68
+ }
69
+ }
70
+
71
+ // Fallback to inline generation
72
+ return this.generateAgentsMdFallback(context);
73
+ }
74
+
75
+ /**
76
+ * Codex-specific setup: generate config.toml
77
+ */
78
+ async setupCliSpecific(config) {
79
+ // Generate config.toml
80
+ const configTomlPath = path.join(this.projectDir, this.getCliFolder(), 'config.toml');
81
+ const configTomlContent = this.generateConfigToml(config);
82
+ fs.writeFileSync(configTomlPath, configTomlContent);
83
+ this.log('Generated .codex/config.toml');
84
+
85
+ // Convert Claude skills to Codex format
86
+ this.convertAndSyncSkills();
87
+ }
88
+
89
+ // ==================== Codex-Specific Methods ====================
90
+
91
+ /**
92
+ * Build template context
93
+ */
94
+ buildContext(config) {
95
+ // Load decisions.md for coding rules
96
+ const decisionsPath = path.join(this.projectDir, this.workflowDir, 'state', 'decisions.md');
97
+ let decisions = '';
98
+ try {
99
+ decisions = fs.readFileSync(decisionsPath, 'utf-8');
100
+ } catch (err) {
101
+ // File may not exist or be unreadable - continue with empty decisions
102
+ if (err.code !== 'ENOENT') {
103
+ this.log(`Failed to read decisions.md: ${err.message}`);
104
+ }
105
+ }
106
+
107
+ // Get installed skills
108
+ const skills = config.skills?.installed || [];
109
+
110
+ return {
111
+ projectName: path.basename(this.projectDir),
112
+ projectRoot: this.projectDir,
113
+ timestamp: new Date().toISOString(),
114
+ config,
115
+ decisions,
116
+ skills,
117
+ enforcement: config.enforcement || {},
118
+ research: config.research || {},
119
+ qualityGates: config.qualityGates || {},
120
+ commits: config.commits || {}
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Fallback AGENTS.md generation (no Handlebars)
126
+ */
127
+ generateAgentsMdFallback(context) {
128
+ const lines = [];
129
+
130
+ lines.push('# WogiFlow Project Instructions');
131
+ lines.push('');
132
+ lines.push(`> Generated by WogiFlow Codex Bridge - ${context.timestamp}`);
133
+ lines.push('');
134
+ lines.push('## Core Principles');
135
+ lines.push('');
136
+ lines.push('1. **State files are memory** - Read `.workflow/state/` first');
137
+ lines.push('2. **Config drives behavior** - Follow `.workflow/config.json` rules');
138
+ lines.push('3. **Log every change** - Append to `request-log.md`');
139
+ lines.push('4. **Reuse components** - Check `app-map.md` before creating');
140
+ lines.push('5. **Learn from feedback** - Update instructions when corrected');
141
+ lines.push('');
142
+
143
+ // Task Gating
144
+ if (context.enforcement?.strictMode) {
145
+ lines.push('## Task Gating (MANDATORY)');
146
+ lines.push('');
147
+ lines.push('**STOP. Before ANY implementation:**');
148
+ lines.push('1. Check `.workflow/state/ready.json` for existing tasks');
149
+ lines.push('2. If no task exists, create one with `/wogi-story`');
150
+ lines.push('3. Start with `/wogi-start TASK-XXX`');
151
+ lines.push('');
152
+ }
153
+
154
+ // Research Protocol
155
+ if (context.research?.enabled) {
156
+ lines.push('## Research Protocol');
157
+ lines.push('');
158
+ lines.push('For capability/feasibility/existence questions:');
159
+ lines.push('1. Search local files thoroughly (Glob, Grep)');
160
+ lines.push('2. Web search for current documentation');
161
+ lines.push('3. List assumptions and verify each');
162
+ lines.push('4. Cite sources for all claims');
163
+ lines.push('5. State confidence level (HIGH/MEDIUM/LOW)');
164
+ lines.push('');
165
+ lines.push('**FORBIDDEN:** Claiming "X doesn\'t exist" without exhaustive search.');
166
+ lines.push('');
167
+ }
168
+
169
+ // Essential Commands
170
+ lines.push('## Essential Commands');
171
+ lines.push('');
172
+ lines.push('| Command | Purpose |');
173
+ lines.push('|---------|---------|');
174
+ lines.push('| `/wogi-ready` | Show available tasks |');
175
+ lines.push('| `/wogi-start TASK-X` | Start task with context |');
176
+ lines.push('| `/wogi-story "title"` | Create story with AC |');
177
+ lines.push('| `/wogi-status` | Project overview |');
178
+ lines.push('| `/wogi-research "q"` | Research before answering |');
179
+ lines.push('');
180
+
181
+ // Request Logging
182
+ lines.push('## Request Logging');
183
+ lines.push('');
184
+ lines.push('After EVERY request that changes files:');
185
+ lines.push('```markdown');
186
+ lines.push('### R-[XXX] | [YYYY-MM-DD HH:MM]');
187
+ lines.push('**Type**: new | fix | change | refactor');
188
+ lines.push('**Tags**: #screen:[name] #component:[name]');
189
+ lines.push('**Request**: "[what user asked]"');
190
+ lines.push('**Result**: [what was done]');
191
+ lines.push('**Files**: [files changed]');
192
+ lines.push('```');
193
+ lines.push('');
194
+
195
+ // Component Reuse
196
+ lines.push('## Component Reuse');
197
+ lines.push('');
198
+ lines.push('**Before creating ANY component:**');
199
+ lines.push('1. Check `app-map.md`');
200
+ lines.push('2. Search codebase for existing');
201
+ lines.push('3. Priority: Use existing → Add variant → Extend → Create new');
202
+ lines.push('');
203
+
204
+ // File Locations
205
+ lines.push('## File Locations');
206
+ lines.push('');
207
+ lines.push('| What | Where |');
208
+ lines.push('|------|-------|');
209
+ lines.push('| Config | `.workflow/config.json` |');
210
+ lines.push('| Tasks | `.workflow/state/ready.json` |');
211
+ lines.push('| Logs | `.workflow/state/request-log.md` |');
212
+ lines.push('| Components | `.workflow/state/app-map.md` |');
213
+ lines.push('| Rules | `.workflow/state/decisions.md` |');
214
+ lines.push('');
215
+
216
+ lines.push('---');
217
+ lines.push('');
218
+ lines.push('*Note: Enforcement is advisory. Codex lacks pre-operation hooks.*');
219
+
220
+ return lines.join('\n');
221
+ }
222
+
223
+ /**
224
+ * Generate .codex/config.toml content
225
+ */
226
+ generateConfigToml(config) {
227
+ const context = this.buildContext(config);
228
+
229
+ // Try to use Handlebars template with proper error handling
230
+ if (Handlebars) {
231
+ try {
232
+ const templatePath = path.join(this.projectDir, this.workflowDir, 'templates', 'codex-config.hbs');
233
+ if (fs.existsSync(templatePath)) {
234
+ const templateSource = fs.readFileSync(templatePath, 'utf-8');
235
+ const template = Handlebars.compile(templateSource);
236
+ return template(context);
237
+ }
238
+ } catch (err) {
239
+ // Template failed - fall through to inline generation
240
+ this.log(`Config template failed, using fallback: ${err.message}`);
241
+ }
242
+ }
243
+
244
+ // Fallback to inline generation
245
+ return this.generateConfigTomlFallback(context);
246
+ }
247
+
248
+ /**
249
+ * Fallback config.toml generation
250
+ */
251
+ generateConfigTomlFallback(context) {
252
+ const lines = [];
253
+
254
+ lines.push('# WogiFlow Codex Configuration');
255
+ lines.push(`# Generated: ${context.timestamp}`);
256
+ lines.push('');
257
+
258
+ // Approvals - safer default
259
+ lines.push('[approvals]');
260
+ lines.push('mode = "on-request"');
261
+ lines.push('');
262
+
263
+ // MCP Servers
264
+ lines.push('[mcp_servers.wogiflow_memory]');
265
+ lines.push('command = "node"');
266
+ lines.push(`args = ["mcp-memory-server/index.js"]`);
267
+ lines.push(`cwd = "${context.projectRoot}"`);
268
+ lines.push('');
269
+
270
+ // Features
271
+ lines.push('[features]');
272
+ lines.push('child_agents_md = true');
273
+ lines.push('');
274
+
275
+ // Fallback filenames
276
+ lines.push('project_doc_fallback_filenames = ["CLAUDE.md", "GEMINI.md"]');
277
+ lines.push('');
278
+
279
+ return lines.join('\n');
280
+ }
281
+
282
+ /**
283
+ * Convert Claude skills to Codex SKILL.md format
284
+ */
285
+ convertAndSyncSkills() {
286
+ const claudeSkillsDir = path.join(this.projectDir, '.claude', 'skills');
287
+ const codexSkillsDir = path.join(this.projectDir, this.getSkillsPath());
288
+
289
+ if (!fs.existsSync(claudeSkillsDir)) {
290
+ this.log('No Claude skills to convert');
291
+ return;
292
+ }
293
+
294
+ // Ensure Codex skills directory exists with explicit permissions
295
+ if (!fs.existsSync(codexSkillsDir)) {
296
+ fs.mkdirSync(codexSkillsDir, { recursive: true, mode: 0o755 });
297
+ }
298
+
299
+ let skillDirs;
300
+ try {
301
+ skillDirs = fs.readdirSync(claudeSkillsDir, { withFileTypes: true })
302
+ .filter(d => d.isDirectory())
303
+ .map(d => d.name);
304
+ } catch (err) {
305
+ this.log(`Failed to read skills directory: ${err.message}`);
306
+ return;
307
+ }
308
+
309
+ let converted = 0;
310
+ let skipped = 0;
311
+
312
+ for (const skillName of skillDirs) {
313
+ try {
314
+ // SECURITY: Validate skillName to prevent path traversal
315
+ // path.basename() removes any directory components (../, etc.)
316
+ const safeSkillName = path.basename(skillName);
317
+ if (safeSkillName !== skillName) {
318
+ this.log(`Skipping suspicious skill name: ${skillName}`);
319
+ skipped++;
320
+ continue;
321
+ }
322
+
323
+ // Additional validation: only alphanumeric, dash, underscore
324
+ if (!/^[a-zA-Z0-9_-]+$/.test(safeSkillName)) {
325
+ this.log(`Skipping skill with invalid characters: ${skillName}`);
326
+ skipped++;
327
+ continue;
328
+ }
329
+
330
+ const claudeSkillMd = path.join(claudeSkillsDir, safeSkillName, 'skill.md');
331
+
332
+ if (fs.existsSync(claudeSkillMd)) {
333
+ const content = fs.readFileSync(claudeSkillMd, 'utf-8');
334
+ const codexContent = this.convertSkillToCodex(safeSkillName, content);
335
+
336
+ // Create Codex skill directory with explicit permissions
337
+ const codexSkillDir = path.join(codexSkillsDir, safeSkillName);
338
+ if (!fs.existsSync(codexSkillDir)) {
339
+ fs.mkdirSync(codexSkillDir, { recursive: true, mode: 0o755 });
340
+ }
341
+
342
+ // Write SKILL.md (Codex format)
343
+ fs.writeFileSync(path.join(codexSkillDir, 'SKILL.md'), codexContent);
344
+ this.log(`Converted skill: ${safeSkillName}`);
345
+ converted++;
346
+ }
347
+ } catch (err) {
348
+ // Log error but continue with other skills
349
+ this.log(`Failed to convert skill ${skillName}: ${err.message}`);
350
+ skipped++;
351
+ }
352
+ }
353
+
354
+ if (converted > 0 || skipped > 0) {
355
+ this.log(`Skill sync complete: ${converted} converted, ${skipped} skipped`);
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Convert a Claude skill.md to Codex SKILL.md format
361
+ */
362
+ convertSkillToCodex(skillName, claudeContent) {
363
+ const lines = [];
364
+
365
+ // Parse Claude frontmatter if present
366
+ let description = `WogiFlow ${skillName} skill`;
367
+ let body = claudeContent;
368
+
369
+ const frontmatterMatch = claudeContent.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
370
+ if (frontmatterMatch) {
371
+ const frontmatter = frontmatterMatch[1];
372
+ body = frontmatterMatch[2].trim();
373
+
374
+ const descMatch = frontmatter.match(/description:\s*["']?([^"'\n]+)["']?/);
375
+ if (descMatch) {
376
+ description = descMatch[1];
377
+ }
378
+ }
379
+
380
+ // Generate Codex SKILL.md format
381
+ lines.push('---');
382
+ lines.push(`name: ${skillName}`);
383
+ lines.push(`description: ${description}`);
384
+ lines.push('metadata:');
385
+ lines.push(` short-description: ${description.slice(0, 50)}`);
386
+ lines.push(` source: wogi-flow`);
387
+ lines.push('---');
388
+ lines.push('');
389
+ lines.push(body);
390
+
391
+ return lines.join('\n');
392
+ }
393
+ }
394
+
395
+ // ============================================================
396
+ // Module Exports
397
+ // ============================================================
398
+
399
+ module.exports = CodexBridge;
400
+
401
+ // CLI interface if run directly
402
+ if (require.main === module) {
403
+ const args = process.argv.slice(2);
404
+ const command = args[0];
405
+
406
+ const bridge = new CodexBridge({ verbose: true });
407
+
408
+ switch (command) {
409
+ case 'sync':
410
+ bridge.sync().then(results => {
411
+ console.log('');
412
+ console.log('Codex Bridge Sync Results:');
413
+ console.log(` Success: ${results.success}`);
414
+ console.log(` Duration: ${results.duration}ms`);
415
+ console.log(` Synced: ${results.synced.join(', ')}`);
416
+ if (results.errors.length > 0) {
417
+ console.log(` Errors: ${results.errors.map(e => e.error).join(', ')}`);
418
+ }
419
+ });
420
+ break;
421
+
422
+ case 'status':
423
+ const agentsMdExists = fs.existsSync(path.join(process.cwd(), 'AGENTS.md'));
424
+ const configTomlExists = fs.existsSync(path.join(process.cwd(), '.codex', 'config.toml'));
425
+
426
+ console.log('Codex Bridge Status:');
427
+ console.log(` AGENTS.md: ${agentsMdExists ? '✓ exists' : '✗ missing'}`);
428
+ console.log(` .codex/config.toml: ${configTomlExists ? '✓ exists' : '✗ missing'}`);
429
+ break;
430
+
431
+ default:
432
+ console.log('WogiFlow Codex Bridge');
433
+ console.log('');
434
+ console.log('Commands:');
435
+ console.log(' sync Sync WogiFlow config to Codex format');
436
+ console.log(' status Check current Codex configuration');
437
+ console.log('');
438
+ console.log('Usage:');
439
+ console.log(' node .workflow/bridges/codex-bridge.js sync');
440
+ }
441
+ }