wogiflow 1.0.0

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 (221) hide show
  1. package/.workflow/agents/reviewer.md +81 -0
  2. package/.workflow/agents/security.md +94 -0
  3. package/.workflow/agents/story-writer.md +58 -0
  4. package/.workflow/bridges/base-bridge.js +395 -0
  5. package/.workflow/bridges/claude-bridge.js +434 -0
  6. package/.workflow/bridges/index.js +130 -0
  7. package/.workflow/lib/assumption-detector.js +481 -0
  8. package/.workflow/lib/config-substitution.js +371 -0
  9. package/.workflow/lib/failure-categories.js +478 -0
  10. package/.workflow/state/app-map.md.template +15 -0
  11. package/.workflow/state/architecture.md.template +24 -0
  12. package/.workflow/state/component-index.json.template +5 -0
  13. package/.workflow/state/decisions.md.template +15 -0
  14. package/.workflow/state/feedback-patterns.md.template +9 -0
  15. package/.workflow/state/knowledge-sync.json.template +6 -0
  16. package/.workflow/state/progress.md.template +14 -0
  17. package/.workflow/state/ready.json.template +7 -0
  18. package/.workflow/state/request-log.md.template +14 -0
  19. package/.workflow/state/session-state.json.template +11 -0
  20. package/.workflow/state/stack.md.template +33 -0
  21. package/.workflow/state/testing.md.template +36 -0
  22. package/.workflow/templates/claude-md.hbs +257 -0
  23. package/.workflow/templates/correction-report.md +67 -0
  24. package/.workflow/templates/gemini-md.hbs +52 -0
  25. package/README.md +1802 -0
  26. package/bin/flow +205 -0
  27. package/lib/index.js +33 -0
  28. package/lib/installer.js +467 -0
  29. package/lib/release-channel.js +269 -0
  30. package/lib/skill-registry.js +526 -0
  31. package/lib/upgrader.js +401 -0
  32. package/lib/utils.js +305 -0
  33. package/package.json +64 -0
  34. package/scripts/flow +985 -0
  35. package/scripts/flow-adaptive-learning.js +1259 -0
  36. package/scripts/flow-aggregate.js +488 -0
  37. package/scripts/flow-archive +133 -0
  38. package/scripts/flow-auto-context.js +1015 -0
  39. package/scripts/flow-auto-learn.js +615 -0
  40. package/scripts/flow-bridge.js +223 -0
  41. package/scripts/flow-browser-suggest.js +316 -0
  42. package/scripts/flow-bug.js +247 -0
  43. package/scripts/flow-cascade.js +711 -0
  44. package/scripts/flow-changelog +85 -0
  45. package/scripts/flow-checkpoint.js +483 -0
  46. package/scripts/flow-cli.js +403 -0
  47. package/scripts/flow-code-intelligence.js +760 -0
  48. package/scripts/flow-complexity.js +502 -0
  49. package/scripts/flow-config-set.js +152 -0
  50. package/scripts/flow-constants.js +157 -0
  51. package/scripts/flow-context +152 -0
  52. package/scripts/flow-context-init.js +482 -0
  53. package/scripts/flow-context-monitor.js +384 -0
  54. package/scripts/flow-context-scoring.js +886 -0
  55. package/scripts/flow-correct.js +458 -0
  56. package/scripts/flow-damage-control.js +985 -0
  57. package/scripts/flow-deps +101 -0
  58. package/scripts/flow-diff.js +700 -0
  59. package/scripts/flow-done +151 -0
  60. package/scripts/flow-done.js +489 -0
  61. package/scripts/flow-durable-session.js +1541 -0
  62. package/scripts/flow-entropy-monitor.js +345 -0
  63. package/scripts/flow-export-profile +349 -0
  64. package/scripts/flow-export-scanner.js +1046 -0
  65. package/scripts/flow-figma-confirm.js +400 -0
  66. package/scripts/flow-figma-extract.js +496 -0
  67. package/scripts/flow-figma-generate.js +683 -0
  68. package/scripts/flow-figma-index.js +909 -0
  69. package/scripts/flow-figma-match.js +617 -0
  70. package/scripts/flow-figma-mcp-server.js +518 -0
  71. package/scripts/flow-figma-pipeline.js +414 -0
  72. package/scripts/flow-file-ops.js +301 -0
  73. package/scripts/flow-gate-confidence.js +825 -0
  74. package/scripts/flow-guided-edit.js +659 -0
  75. package/scripts/flow-health +185 -0
  76. package/scripts/flow-health.js +413 -0
  77. package/scripts/flow-hooks.js +556 -0
  78. package/scripts/flow-http-client.js +249 -0
  79. package/scripts/flow-hybrid-detect.js +167 -0
  80. package/scripts/flow-hybrid-interactive.js +591 -0
  81. package/scripts/flow-hybrid-test.js +152 -0
  82. package/scripts/flow-import-profile +439 -0
  83. package/scripts/flow-init +253 -0
  84. package/scripts/flow-instruction-richness.js +827 -0
  85. package/scripts/flow-jira-integration.js +579 -0
  86. package/scripts/flow-knowledge-router.js +522 -0
  87. package/scripts/flow-knowledge-sync.js +589 -0
  88. package/scripts/flow-linear-integration.js +631 -0
  89. package/scripts/flow-links.js +774 -0
  90. package/scripts/flow-log-manager.js +559 -0
  91. package/scripts/flow-loop-enforcer.js +1246 -0
  92. package/scripts/flow-loop-retry-learning.js +630 -0
  93. package/scripts/flow-lsp.js +923 -0
  94. package/scripts/flow-map-index +348 -0
  95. package/scripts/flow-map-sync +201 -0
  96. package/scripts/flow-memory-blocks.js +668 -0
  97. package/scripts/flow-memory-compactor.js +350 -0
  98. package/scripts/flow-memory-db.js +1110 -0
  99. package/scripts/flow-memory-sync.js +484 -0
  100. package/scripts/flow-metrics.js +353 -0
  101. package/scripts/flow-migrate-ids.js +370 -0
  102. package/scripts/flow-model-adapter.js +802 -0
  103. package/scripts/flow-model-router.js +884 -0
  104. package/scripts/flow-models.js +1231 -0
  105. package/scripts/flow-morning.js +517 -0
  106. package/scripts/flow-multi-approach.js +660 -0
  107. package/scripts/flow-new-feature +86 -0
  108. package/scripts/flow-onboard +1042 -0
  109. package/scripts/flow-orchestrate-llm.js +459 -0
  110. package/scripts/flow-orchestrate.js +3592 -0
  111. package/scripts/flow-output.js +123 -0
  112. package/scripts/flow-parallel-detector.js +399 -0
  113. package/scripts/flow-parallel-dispatch.js +987 -0
  114. package/scripts/flow-parallel.js +428 -0
  115. package/scripts/flow-pattern-enforcer.js +600 -0
  116. package/scripts/flow-prd-manager.js +282 -0
  117. package/scripts/flow-progress.js +323 -0
  118. package/scripts/flow-project-analyzer.js +975 -0
  119. package/scripts/flow-prompt-composer.js +487 -0
  120. package/scripts/flow-providers.js +1381 -0
  121. package/scripts/flow-queue.js +308 -0
  122. package/scripts/flow-ready +82 -0
  123. package/scripts/flow-ready.js +189 -0
  124. package/scripts/flow-regression.js +396 -0
  125. package/scripts/flow-response-parser.js +450 -0
  126. package/scripts/flow-resume.js +284 -0
  127. package/scripts/flow-rules-sync.js +439 -0
  128. package/scripts/flow-run-trace.js +718 -0
  129. package/scripts/flow-safety.js +587 -0
  130. package/scripts/flow-search +104 -0
  131. package/scripts/flow-security.js +481 -0
  132. package/scripts/flow-session-end +106 -0
  133. package/scripts/flow-session-end.js +437 -0
  134. package/scripts/flow-session-state.js +671 -0
  135. package/scripts/flow-setup-hooks +216 -0
  136. package/scripts/flow-setup-hooks.js +377 -0
  137. package/scripts/flow-skill-create.js +329 -0
  138. package/scripts/flow-skill-creator.js +572 -0
  139. package/scripts/flow-skill-generator.js +1046 -0
  140. package/scripts/flow-skill-learn.js +880 -0
  141. package/scripts/flow-skill-matcher.js +578 -0
  142. package/scripts/flow-spec-generator.js +820 -0
  143. package/scripts/flow-stack-wizard.js +895 -0
  144. package/scripts/flow-standup +162 -0
  145. package/scripts/flow-start +74 -0
  146. package/scripts/flow-start.js +235 -0
  147. package/scripts/flow-status +110 -0
  148. package/scripts/flow-status.js +301 -0
  149. package/scripts/flow-step-browser.js +83 -0
  150. package/scripts/flow-step-changelog.js +217 -0
  151. package/scripts/flow-step-comments.js +306 -0
  152. package/scripts/flow-step-complexity.js +234 -0
  153. package/scripts/flow-step-coverage.js +218 -0
  154. package/scripts/flow-step-knowledge.js +193 -0
  155. package/scripts/flow-step-pr-tests.js +364 -0
  156. package/scripts/flow-step-regression.js +89 -0
  157. package/scripts/flow-step-review.js +516 -0
  158. package/scripts/flow-step-security.js +162 -0
  159. package/scripts/flow-step-silent-failures.js +290 -0
  160. package/scripts/flow-step-simplifier.js +346 -0
  161. package/scripts/flow-story +105 -0
  162. package/scripts/flow-story.js +500 -0
  163. package/scripts/flow-suspend.js +252 -0
  164. package/scripts/flow-sync-daemon.js +654 -0
  165. package/scripts/flow-task-analyzer.js +606 -0
  166. package/scripts/flow-team-dashboard.js +748 -0
  167. package/scripts/flow-team-sync.js +752 -0
  168. package/scripts/flow-team.js +977 -0
  169. package/scripts/flow-tech-options.js +528 -0
  170. package/scripts/flow-templates.js +812 -0
  171. package/scripts/flow-tiered-learning.js +728 -0
  172. package/scripts/flow-trace +204 -0
  173. package/scripts/flow-transcript-chunking.js +1106 -0
  174. package/scripts/flow-transcript-digest.js +7918 -0
  175. package/scripts/flow-transcript-language.js +465 -0
  176. package/scripts/flow-transcript-parsing.js +1085 -0
  177. package/scripts/flow-transcript-stories.js +2194 -0
  178. package/scripts/flow-update-map +224 -0
  179. package/scripts/flow-utils.js +2242 -0
  180. package/scripts/flow-verification.js +644 -0
  181. package/scripts/flow-verify.js +1177 -0
  182. package/scripts/flow-voice-input.js +638 -0
  183. package/scripts/flow-watch +168 -0
  184. package/scripts/flow-workflow-steps.js +521 -0
  185. package/scripts/flow-workflow.js +1029 -0
  186. package/scripts/flow-worktree.js +489 -0
  187. package/scripts/hooks/adapters/base-adapter.js +102 -0
  188. package/scripts/hooks/adapters/claude-code.js +359 -0
  189. package/scripts/hooks/adapters/index.js +79 -0
  190. package/scripts/hooks/core/component-check.js +341 -0
  191. package/scripts/hooks/core/index.js +35 -0
  192. package/scripts/hooks/core/loop-check.js +241 -0
  193. package/scripts/hooks/core/session-context.js +294 -0
  194. package/scripts/hooks/core/task-gate.js +177 -0
  195. package/scripts/hooks/core/validation.js +230 -0
  196. package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
  197. package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
  198. package/scripts/hooks/entry/claude-code/session-end.js +87 -0
  199. package/scripts/hooks/entry/claude-code/session-start.js +46 -0
  200. package/scripts/hooks/entry/claude-code/stop.js +43 -0
  201. package/scripts/postinstall.js +139 -0
  202. package/templates/browser-test-flow.json +56 -0
  203. package/templates/bug-report.md +43 -0
  204. package/templates/component-detail.md +42 -0
  205. package/templates/component.stories.tsx +49 -0
  206. package/templates/context/constraints.md +83 -0
  207. package/templates/context/conventions.md +177 -0
  208. package/templates/context/stack.md +60 -0
  209. package/templates/correction-report.md +90 -0
  210. package/templates/feature-proposal.md +35 -0
  211. package/templates/hybrid/_base.md +254 -0
  212. package/templates/hybrid/_patterns.md +45 -0
  213. package/templates/hybrid/create-component.md +127 -0
  214. package/templates/hybrid/create-file.md +56 -0
  215. package/templates/hybrid/create-hook.md +145 -0
  216. package/templates/hybrid/create-service.md +70 -0
  217. package/templates/hybrid/fix-bug.md +33 -0
  218. package/templates/hybrid/modify-file.md +55 -0
  219. package/templates/story.md +68 -0
  220. package/templates/task.json +56 -0
  221. package/templates/trace.md +69 -0
@@ -0,0 +1,81 @@
1
+ # Code Review Agent
2
+
3
+ Expert agent for conducting thorough code reviews.
4
+
5
+ ## Role
6
+
7
+ Review code changes for quality, correctness, and maintainability.
8
+
9
+ ## Review Checklist
10
+
11
+ ### Code Quality
12
+ - [ ] Naming is clear and consistent
13
+ - [ ] Functions are small and focused
14
+ - [ ] No dead code or unused imports
15
+ - [ ] Comments explain "why", not "what"
16
+ - [ ] Consistent formatting
17
+
18
+ ### Logic & Correctness
19
+ - [ ] Algorithm is correct
20
+ - [ ] Edge cases handled
21
+ - [ ] Error states managed
22
+ - [ ] No off-by-one errors
23
+ - [ ] Null/undefined checks where needed
24
+
25
+ ### Performance
26
+ - [ ] No unnecessary loops/iterations
27
+ - [ ] Large data sets handled efficiently
28
+ - [ ] No memory leaks
29
+ - [ ] Async operations handled correctly
30
+
31
+ ### Testing
32
+ - [ ] Tests cover happy path
33
+ - [ ] Tests cover error cases
34
+ - [ ] Tests are readable
35
+ - [ ] No flaky tests
36
+
37
+ ### Architecture
38
+ - [ ] Follows existing patterns (check decisions.md)
39
+ - [ ] Uses existing components (check app-map.md)
40
+ - [ ] Separation of concerns
41
+ - [ ] Dependencies are appropriate
42
+
43
+ ## Issue Severity
44
+
45
+ | Severity | Description | Action |
46
+ |----------|-------------|--------|
47
+ | Critical | Bug that breaks functionality | Block merge |
48
+ | High | Security issue or major problem | Block merge |
49
+ | Medium | Could cause issues | Should fix |
50
+ | Low | Stylistic or minor | Nice to have |
51
+
52
+ ## Review Format
53
+
54
+ ```
55
+ ## File: [path]
56
+
57
+ ### Line [N]: [severity] [type]
58
+ Description of the issue.
59
+
60
+ **Current:**
61
+ \`\`\`
62
+ [current code]
63
+ \`\`\`
64
+
65
+ **Suggested:**
66
+ \`\`\`
67
+ [suggested fix]
68
+ \`\`\`
69
+ ```
70
+
71
+ ## When Approving
72
+
73
+ Provide a brief summary:
74
+ ```
75
+ ✓ Approved
76
+
77
+ Summary:
78
+ - [What the change does]
79
+ - [Key decisions made]
80
+ - [Any follow-up items]
81
+ ```
@@ -0,0 +1,94 @@
1
+ # Security Review Agent
2
+
3
+ Expert agent for reviewing code against OWASP Top 10 and security best practices.
4
+
5
+ ## Role
6
+
7
+ Identify security vulnerabilities in code changes and recommend fixes.
8
+
9
+ ## OWASP Top 10 Checklist
10
+
11
+ ### A01: Broken Access Control
12
+ - [ ] Authorization checks on every protected resource
13
+ - [ ] Deny by default for new functionality
14
+ - [ ] Rate limiting on APIs
15
+ - [ ] Invalidate sessions on logout
16
+
17
+ ### A02: Cryptographic Failures
18
+ - [ ] Data classified by sensitivity
19
+ - [ ] No sensitive data in URLs
20
+ - [ ] Strong encryption for data at rest
21
+ - [ ] TLS for data in transit
22
+
23
+ ### A03: Injection
24
+ - [ ] Parameterized queries for SQL
25
+ - [ ] Input validation on all user data
26
+ - [ ] Output encoding for HTML contexts
27
+ - [ ] Command injection prevention
28
+
29
+ ### A04: Insecure Design
30
+ - [ ] Threat modeling for new features
31
+ - [ ] Secure by default configurations
32
+ - [ ] Unit tests for security controls
33
+
34
+ ### A05: Security Misconfiguration
35
+ - [ ] No default credentials
36
+ - [ ] Error messages don't leak info
37
+ - [ ] Security headers configured
38
+ - [ ] Unnecessary features disabled
39
+
40
+ ### A06: Vulnerable Components
41
+ - [ ] Dependencies audited (`npm audit`)
42
+ - [ ] No known vulnerable versions
43
+ - [ ] Update process documented
44
+
45
+ ### A07: Authentication Failures
46
+ - [ ] Strong password requirements
47
+ - [ ] Multi-factor authentication option
48
+ - [ ] Account lockout after failures
49
+ - [ ] Secure session management
50
+
51
+ ### A08: Software and Data Integrity Failures
52
+ - [ ] CI/CD pipeline secured
53
+ - [ ] Signed commits/releases
54
+ - [ ] Dependency integrity verification
55
+
56
+ ### A09: Security Logging Failures
57
+ - [ ] Login/logout events logged
58
+ - [ ] Access control failures logged
59
+ - [ ] Logs protected from tampering
60
+ - [ ] No sensitive data in logs
61
+
62
+ ### A10: Server-Side Request Forgery (SSRF)
63
+ - [ ] URL validation for external calls
64
+ - [ ] Allowlist for external services
65
+ - [ ] Firewall rules for internal networks
66
+
67
+ ## Common Patterns to Flag
68
+
69
+ ```javascript
70
+ // BAD: Raw JSON parse
71
+ JSON.parse(userInput)
72
+
73
+ // GOOD: Safe JSON parse with try-catch
74
+ try {
75
+ const data = JSON.parse(userInput);
76
+ if (data.__proto__) throw new Error('Invalid');
77
+ } catch { return null; }
78
+ ```
79
+
80
+ ```javascript
81
+ // BAD: Path without validation
82
+ fs.readFileSync(path.join(base, userInput))
83
+
84
+ // GOOD: Validate path is within base
85
+ const resolved = path.resolve(base, userInput);
86
+ if (!resolved.startsWith(base)) throw new Error('Invalid path');
87
+ ```
88
+
89
+ ## Severity Ratings
90
+
91
+ - **Critical**: Immediate exploitation risk
92
+ - **High**: Significant security impact
93
+ - **Medium**: Requires specific conditions
94
+ - **Low**: Minimal security impact
@@ -0,0 +1,58 @@
1
+ # Story Writer Agent
2
+
3
+ Expert agent for creating well-structured user stories with clear acceptance criteria.
4
+
5
+ ## Role
6
+
7
+ Transform vague feature requests into actionable user stories with:
8
+ - Clear user personas
9
+ - Specific value propositions
10
+ - Testable acceptance criteria using Given/When/Then format
11
+
12
+ ## Story Template
13
+
14
+ ```markdown
15
+ # [wf-XXXXXXXX] [Title]
16
+
17
+ ## User Story
18
+ **As a** [user persona]
19
+ **I want** [feature/action]
20
+ **So that** [benefit/value]
21
+
22
+ ## Description
23
+ [2-4 sentences explaining context and scope]
24
+
25
+ ## Acceptance Criteria
26
+
27
+ ### Scenario 1: [Happy path]
28
+ **Given** [initial context]
29
+ **When** [action is taken]
30
+ **Then** [expected outcome]
31
+
32
+ ### Scenario 2: [Error handling]
33
+ **Given** [context]
34
+ **When** [invalid action]
35
+ **Then** [error response]
36
+
37
+ ## Technical Notes
38
+ - Components to create/modify
39
+ - API endpoints involved
40
+ - Dependencies
41
+
42
+ ## Test Strategy
43
+ - [ ] Unit tests for [component]
44
+ - [ ] Integration test for [flow]
45
+
46
+ ## Dependencies
47
+ - [Depends on wf-XXXXXXXX]
48
+
49
+ ## Complexity
50
+ Low | Medium | High
51
+ ```
52
+
53
+ ## Guidelines
54
+
55
+ 1. **Be specific** - Avoid vague acceptance criteria
56
+ 2. **Include error states** - What happens when things go wrong?
57
+ 3. **Reference existing components** - Check app-map.md first
58
+ 4. **Set realistic scope** - If it's too big, decompose into sub-tasks
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Base Bridge Class
3
+ *
4
+ * Abstract base class for CLI bridges. Each supported CLI (Claude Code, Gemini CLI, etc.)
5
+ * extends this class to generate its specific file structure from the universal .workflow/ config.
6
+ *
7
+ * Architecture:
8
+ *
9
+ * .workflow/ ← Universal source of truth
10
+ * ├── config.json ← Contains cli.type setting
11
+ * ├── models/ ← Model registry (CLI-agnostic)
12
+ * ├── skills/ ← Skills (CLI-agnostic)
13
+ * └── templates/ ← Templates for generating CLI files
14
+ * │
15
+ * ▼ (bridge generates CLI-specific files)
16
+ * .claude/ or .gemini/ etc. ← Generated by bridge
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+
22
+ // Import safeJsonParse from flow-utils to avoid duplicate implementation
23
+ let safeJsonParse;
24
+ try {
25
+ safeJsonParse = require('../../scripts/flow-utils').safeJsonParse;
26
+ } catch {
27
+ // Fallback if flow-utils not available
28
+ safeJsonParse = null;
29
+ }
30
+
31
+ class BaseBridge {
32
+ /**
33
+ * @param {string} cliType - The CLI type identifier (e.g., 'claude-code', 'gemini-cli')
34
+ * @param {Object} options - Configuration options
35
+ * @param {string} options.workflowDir - Path to .workflow directory
36
+ * @param {string} options.projectDir - Path to project root
37
+ */
38
+ constructor(cliType, options = {}) {
39
+ this.cliType = cliType;
40
+ this.workflowDir = options.workflowDir || '.workflow';
41
+ this.projectDir = options.projectDir || process.cwd();
42
+ this.verbose = options.verbose || false;
43
+
44
+ // Note: These properties are deprecated in favor of getter methods below.
45
+ // Kept for backwards compatibility with any subclasses that set them directly.
46
+ // New subclasses should override getCliFolder(), getRulesFileName(), etc.
47
+ this.cliFolder = null;
48
+ this.rulesFile = null;
49
+ this.skillsPath = null;
50
+ this.rulesPath = null;
51
+ }
52
+
53
+ /**
54
+ * Get the CLI-specific folder name
55
+ * @abstract
56
+ * @returns {string}
57
+ */
58
+ getCliFolder() {
59
+ throw new Error('Subclass must implement getCliFolder()');
60
+ }
61
+
62
+ /**
63
+ * Get the rules file name (e.g., CLAUDE.md)
64
+ * @abstract
65
+ * @returns {string}
66
+ */
67
+ getRulesFileName() {
68
+ throw new Error('Subclass must implement getRulesFileName()');
69
+ }
70
+
71
+ /**
72
+ * Get the path where skills should be synced
73
+ * @abstract
74
+ * @returns {string}
75
+ */
76
+ getSkillsPath() {
77
+ throw new Error('Subclass must implement getSkillsPath()');
78
+ }
79
+
80
+ /**
81
+ * Get the path where rules should be synced
82
+ * @abstract
83
+ * @returns {string}
84
+ */
85
+ getRulesPath() {
86
+ throw new Error('Subclass must implement getRulesPath()');
87
+ }
88
+
89
+ /**
90
+ * Generate the main rules/instructions file content
91
+ * @abstract
92
+ * @param {Object} config - The workflow config
93
+ * @returns {string}
94
+ */
95
+ generateRulesContent(config) {
96
+ throw new Error('Subclass must implement generateRulesContent()');
97
+ }
98
+
99
+ /**
100
+ * Perform any CLI-specific setup
101
+ * @abstract
102
+ * @param {Object} config - The workflow config
103
+ */
104
+ async setupCliSpecific(config) {
105
+ // Default: no-op. Override in subclasses if needed.
106
+ }
107
+
108
+ // ==================== Common Methods ====================
109
+
110
+ /**
111
+ * Safe JSON parse that checks for prototype pollution (fallback when flow-utils unavailable)
112
+ * @param {string} content - JSON string to parse
113
+ * @returns {Object|null} Parsed object or null if invalid
114
+ */
115
+ 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
+ return null;
123
+ }
124
+
125
+ try {
126
+ const parsed = JSON.parse(content);
127
+ if (parsed === null || typeof parsed !== 'object') {
128
+ return null;
129
+ }
130
+ return parsed;
131
+ } catch {
132
+ return null;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Read the workflow config
138
+ * @returns {Object}
139
+ */
140
+ readConfig() {
141
+ const configPath = path.join(this.projectDir, this.workflowDir, 'config.json');
142
+ if (!fs.existsSync(configPath)) {
143
+ throw new Error(`Config not found: ${configPath}`);
144
+ }
145
+
146
+ // Use flow-utils safeJsonParse if available, otherwise fall back to class method
147
+ let config;
148
+ if (safeJsonParse) {
149
+ config = safeJsonParse(configPath, null);
150
+ } else {
151
+ const content = fs.readFileSync(configPath, 'utf-8');
152
+ config = this.safeJsonParseContent(content);
153
+ }
154
+
155
+ if (!config) {
156
+ throw new Error(`Invalid config format: ${configPath}`);
157
+ }
158
+ return config;
159
+ }
160
+
161
+ /**
162
+ * Ensure the CLI folder exists
163
+ */
164
+ ensureCliFolder() {
165
+ const cliFolder = path.join(this.projectDir, this.getCliFolder());
166
+ if (!fs.existsSync(cliFolder)) {
167
+ fs.mkdirSync(cliFolder, { recursive: true });
168
+ this.log(`Created ${this.getCliFolder()}/`);
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Sync skills from .workflow/skills/ to CLI-specific location
174
+ */
175
+ syncSkills() {
176
+ const sourceSkillsDir = path.join(this.projectDir, this.workflowDir, 'skills');
177
+ const targetSkillsDir = path.join(this.projectDir, this.getSkillsPath());
178
+
179
+ if (!fs.existsSync(sourceSkillsDir)) {
180
+ this.log('No skills to sync (no .workflow/skills/ directory)');
181
+ return;
182
+ }
183
+
184
+ // Ensure target directory exists
185
+ if (!fs.existsSync(targetSkillsDir)) {
186
+ fs.mkdirSync(targetSkillsDir, { recursive: true });
187
+ }
188
+
189
+ // Copy skills
190
+ const skills = fs.readdirSync(sourceSkillsDir).filter(item => {
191
+ const itemPath = path.join(sourceSkillsDir, item);
192
+ return fs.statSync(itemPath).isDirectory();
193
+ });
194
+
195
+ for (const skill of skills) {
196
+ const sourcePath = path.join(sourceSkillsDir, skill);
197
+ const targetPath = path.join(targetSkillsDir, skill);
198
+
199
+ this.copyDirRecursive(sourcePath, targetPath);
200
+ this.log(`Synced skill: ${skill}`);
201
+ }
202
+
203
+ // Also copy skills-index.json if it exists
204
+ const indexPath = path.join(sourceSkillsDir, 'skills-index.json');
205
+ if (fs.existsSync(indexPath)) {
206
+ fs.copyFileSync(indexPath, path.join(targetSkillsDir, 'skills-index.json'));
207
+ this.log('Synced skills-index.json');
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Sync rules from .workflow/state/decisions.md to CLI-specific rules folder
213
+ */
214
+ syncRules() {
215
+ const rulesDir = path.join(this.projectDir, this.getRulesPath());
216
+
217
+ // Ensure rules directory exists
218
+ if (!fs.existsSync(rulesDir)) {
219
+ fs.mkdirSync(rulesDir, { recursive: true });
220
+ }
221
+
222
+ // Copy any existing rules from .workflow/rules/ if present
223
+ const sourceRulesDir = path.join(this.projectDir, this.workflowDir, 'rules');
224
+ if (fs.existsSync(sourceRulesDir)) {
225
+ const rules = fs.readdirSync(sourceRulesDir).filter(f => f.endsWith('.md'));
226
+ for (const rule of rules) {
227
+ fs.copyFileSync(
228
+ path.join(sourceRulesDir, rule),
229
+ path.join(rulesDir, rule)
230
+ );
231
+ this.log(`Synced rule: ${rule}`);
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Sync knowledge files from .workflow/state/ to CLI-specific docs folder
238
+ * Also updates the knowledge-sync.json state
239
+ */
240
+ syncKnowledgeFiles() {
241
+ const stateDir = path.join(this.projectDir, this.workflowDir, 'state');
242
+ const cliDocsDir = path.join(this.projectDir, this.getCliFolder(), 'docs');
243
+
244
+ // Knowledge files to sync
245
+ const knowledgeFiles = ['stack.md', 'architecture.md', 'testing.md'];
246
+
247
+ // Ensure CLI docs directory exists
248
+ if (!fs.existsSync(cliDocsDir)) {
249
+ fs.mkdirSync(cliDocsDir, { recursive: true });
250
+ }
251
+
252
+ let syncedCount = 0;
253
+ for (const file of knowledgeFiles) {
254
+ const sourcePath = path.join(stateDir, file);
255
+ const targetPath = path.join(cliDocsDir, file);
256
+
257
+ if (fs.existsSync(sourcePath)) {
258
+ fs.copyFileSync(sourcePath, targetPath);
259
+ this.log(`Synced knowledge file: ${file}`);
260
+ syncedCount++;
261
+ }
262
+ }
263
+
264
+ // Update knowledge-sync.json after bridge sync
265
+ if (syncedCount > 0) {
266
+ try {
267
+ const knowledgeSync = require('../../scripts/flow-knowledge-sync');
268
+ knowledgeSync.markAsSynced();
269
+ this.log('Updated knowledge-sync.json');
270
+ } catch (err) {
271
+ // flow-knowledge-sync not available
272
+ this.log(`Could not update knowledge-sync state: ${err.message}`);
273
+ }
274
+ }
275
+
276
+ return syncedCount;
277
+ }
278
+
279
+ /**
280
+ * Generate and write the main rules file (e.g., CLAUDE.md)
281
+ */
282
+ generateRulesFile() {
283
+ const config = this.readConfig();
284
+ const content = this.generateRulesContent(config);
285
+ const rulesFilePath = path.join(this.projectDir, this.getRulesFileName());
286
+
287
+ fs.writeFileSync(rulesFilePath, content, 'utf-8');
288
+ this.log(`Generated ${this.getRulesFileName()}`);
289
+ }
290
+
291
+ /**
292
+ * Run full sync: skills, rules, and CLI-specific setup
293
+ * @returns {Object} Sync result summary
294
+ */
295
+ async sync() {
296
+ const startTime = Date.now();
297
+ const results = {
298
+ cliType: this.cliType,
299
+ cliFolder: this.getCliFolder(),
300
+ synced: [],
301
+ errors: []
302
+ };
303
+
304
+ try {
305
+ // 1. Ensure CLI folder exists
306
+ this.ensureCliFolder();
307
+ results.synced.push('cli-folder');
308
+
309
+ // 2. Sync skills
310
+ try {
311
+ this.syncSkills();
312
+ results.synced.push('skills');
313
+ } catch (err) {
314
+ results.errors.push({ step: 'skills', error: err.message });
315
+ }
316
+
317
+ // 3. Sync rules
318
+ try {
319
+ this.syncRules();
320
+ results.synced.push('rules');
321
+ } catch (err) {
322
+ results.errors.push({ step: 'rules', error: err.message });
323
+ }
324
+
325
+ // 4. Sync knowledge files (stack.md, architecture.md, testing.md)
326
+ try {
327
+ const syncedCount = this.syncKnowledgeFiles();
328
+ if (syncedCount > 0) {
329
+ results.synced.push('knowledge-files');
330
+ }
331
+ } catch (err) {
332
+ results.errors.push({ step: 'knowledge-files', error: err.message });
333
+ }
334
+
335
+ // 5. Generate rules file
336
+ try {
337
+ this.generateRulesFile();
338
+ results.synced.push('rules-file');
339
+ } catch (err) {
340
+ results.errors.push({ step: 'rules-file', error: err.message });
341
+ }
342
+
343
+ // 6. CLI-specific setup
344
+ try {
345
+ const config = this.readConfig();
346
+ await this.setupCliSpecific(config);
347
+ results.synced.push('cli-specific');
348
+ } catch (err) {
349
+ results.errors.push({ step: 'cli-specific', error: err.message });
350
+ }
351
+
352
+ } catch (err) {
353
+ results.errors.push({ step: 'general', error: err.message });
354
+ }
355
+
356
+ results.duration = Date.now() - startTime;
357
+ results.success = results.errors.length === 0;
358
+
359
+ return results;
360
+ }
361
+
362
+ // ==================== Utility Methods ====================
363
+
364
+ /**
365
+ * Copy a directory recursively
366
+ */
367
+ copyDirRecursive(source, target) {
368
+ if (!fs.existsSync(target)) {
369
+ fs.mkdirSync(target, { recursive: true });
370
+ }
371
+
372
+ const items = fs.readdirSync(source);
373
+ for (const item of items) {
374
+ const sourcePath = path.join(source, item);
375
+ const targetPath = path.join(target, item);
376
+
377
+ if (fs.statSync(sourcePath).isDirectory()) {
378
+ this.copyDirRecursive(sourcePath, targetPath);
379
+ } else {
380
+ fs.copyFileSync(sourcePath, targetPath);
381
+ }
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Log a message (if verbose mode is on)
387
+ */
388
+ log(message) {
389
+ if (this.verbose) {
390
+ console.log(`[${this.cliType}] ${message}`);
391
+ }
392
+ }
393
+ }
394
+
395
+ module.exports = BaseBridge;