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,216 @@
1
+ #!/bin/bash
2
+
3
+ # Wogi Flow - Setup Git Hooks
4
+ # Installs optional pre-commit hooks to enforce workflow rules
5
+
6
+ set -e
7
+
8
+ WORKFLOW_DIR=".workflow"
9
+
10
+ # Colors
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ RED='\033[0;31m'
14
+ CYAN='\033[0;36m'
15
+ NC='\033[0m'
16
+
17
+ show_help() {
18
+ echo "Setup Git Hooks"
19
+ echo ""
20
+ echo "Usage: flow setup-hooks [options]"
21
+ echo ""
22
+ echo "Options:"
23
+ echo " install Install pre-commit hooks"
24
+ echo " uninstall Remove pre-commit hooks"
25
+ echo " status Check if hooks are installed"
26
+ echo ""
27
+ echo "Hooks enforce:"
28
+ echo " • request-log.md has been updated"
29
+ echo " • app-map.md updated if new components"
30
+ echo " • No console.log in production code"
31
+ echo " • Tests pass (if configured in config.json)"
32
+ echo " • Skill learning extraction (if skillLearning.enabled)"
33
+ }
34
+
35
+ install_hooks() {
36
+ if [ ! -d ".git" ]; then
37
+ echo -e "${RED}Error: Not a git repository${NC}"
38
+ exit 1
39
+ fi
40
+
41
+ mkdir -p .git/hooks
42
+
43
+ # Create pre-commit hook
44
+ cat > .git/hooks/pre-commit << 'HOOK'
45
+ #!/bin/bash
46
+
47
+ # Wogi Flow Pre-commit Hook
48
+ # Enforces workflow rules before commits
49
+
50
+ WORKFLOW_DIR=".workflow"
51
+ RED='\033[0;31m'
52
+ GREEN='\033[0;32m'
53
+ YELLOW='\033[1;33m'
54
+ NC='\033[0m'
55
+
56
+ echo "Running Wogi Flow pre-commit checks..."
57
+
58
+ failed=0
59
+
60
+ # Check 1: request-log.md was modified (if other files changed)
61
+ staged_files=$(git diff --cached --name-only)
62
+ non_workflow_files=$(echo "$staged_files" | grep -v "^\.workflow/" | grep -v "^CLAUDE.md" || true)
63
+
64
+ if [ -n "$non_workflow_files" ]; then
65
+ if ! echo "$staged_files" | grep -q "request-log.md"; then
66
+ echo -e "${YELLOW}⚠ Warning: Code changed but request-log.md not updated${NC}"
67
+ echo " Consider adding a log entry for this change."
68
+ # Warning only, don't fail
69
+ else
70
+ echo -e "${GREEN}✓${NC} request-log.md updated"
71
+ fi
72
+ fi
73
+
74
+ # Check 2: No console.log in staged JS/TS files (warning only)
75
+ js_files=$(echo "$staged_files" | grep -E '\.(js|ts|jsx|tsx)$' || true)
76
+ if [ -n "$js_files" ]; then
77
+ console_logs=$(git diff --cached -- $js_files | grep -E '^\+.*console\.(log|debug)' || true)
78
+ if [ -n "$console_logs" ]; then
79
+ echo -e "${YELLOW}⚠ Warning: console.log found in staged files${NC}"
80
+ echo "$console_logs" | head -5
81
+ # Warning only
82
+ fi
83
+ fi
84
+
85
+ # Check 3: Run tests if configured
86
+ if [ -f "$WORKFLOW_DIR/config.json" ]; then
87
+ run_tests=$(CONFIG_FILE="$WORKFLOW_DIR/config.json" python3 -c "
88
+ import json, os
89
+ with open(os.environ['CONFIG_FILE']) as f:
90
+ config = json.load(f)
91
+ print(config.get('testing', {}).get('runBeforeCommit', False))
92
+ " 2>/dev/null || echo "False")
93
+
94
+ if [ "$run_tests" = "True" ]; then
95
+ echo "Running tests..."
96
+ if npm test --silent 2>/dev/null; then
97
+ echo -e "${GREEN}✓${NC} Tests passed"
98
+ else
99
+ echo -e "${RED}✗ Tests failed${NC}"
100
+ failed=1
101
+ fi
102
+ fi
103
+ fi
104
+
105
+ # Check 4: Lint if configured
106
+ if [ -f "package.json" ] && grep -q '"lint"' package.json 2>/dev/null; then
107
+ staged_code=$(echo "$staged_files" | grep -E '\.(js|ts|jsx|tsx|vue)$' || true)
108
+ if [ -n "$staged_code" ]; then
109
+ # Only lint staged files
110
+ if command -v npx &> /dev/null && [ -f ".eslintrc.js" ] || [ -f ".eslintrc.json" ] || [ -f ".eslintrc" ]; then
111
+ echo "Linting staged files..."
112
+ if echo "$staged_code" | xargs npx eslint --quiet 2>/dev/null; then
113
+ echo -e "${GREEN}✓${NC} Lint passed"
114
+ else
115
+ echo -e "${YELLOW}⚠${NC} Lint warnings (not blocking)"
116
+ fi
117
+ fi
118
+ fi
119
+ fi
120
+
121
+ # Check 5: Skill Learning (extract learnings before commit)
122
+ if [ -f "$WORKFLOW_DIR/config.json" ]; then
123
+ skill_learning=$(CONFIG_FILE="$WORKFLOW_DIR/config.json" python3 -c "
124
+ import json, os
125
+ with open(os.environ['CONFIG_FILE']) as f:
126
+ config = json.load(f)
127
+ sl = config.get('skillLearning', {})
128
+ enabled = sl.get('enabled', False) and sl.get('autoExtract', False)
129
+ trigger = sl.get('triggers', {}).get('onCommit', True)
130
+ print('True' if enabled and trigger else 'False')
131
+ " 2>/dev/null || echo "False")
132
+
133
+ if [ "$skill_learning" = "True" ]; then
134
+ echo "📚 Extracting skill learnings..."
135
+ if command -v node &> /dev/null && [ -f "scripts/flow-skill-learn.js" ]; then
136
+ node scripts/flow-skill-learn.js --trigger=commit 2>/dev/null || true
137
+ fi
138
+ fi
139
+ fi
140
+
141
+ if [ $failed -eq 1 ]; then
142
+ echo ""
143
+ echo -e "${RED}Pre-commit checks failed. Fix issues or use --no-verify to bypass.${NC}"
144
+ exit 1
145
+ fi
146
+
147
+ echo -e "${GREEN}✓ Pre-commit checks passed${NC}"
148
+ exit 0
149
+ HOOK
150
+
151
+ chmod +x .git/hooks/pre-commit
152
+
153
+ echo -e "${GREEN}✓ Pre-commit hook installed${NC}"
154
+ echo ""
155
+ echo "The hook will check:"
156
+ echo " • request-log.md updates (warning)"
157
+ echo " • console.log statements (warning)"
158
+ echo " • Tests (if runBeforeCommit: true in config.json)"
159
+ echo " • Lint (if eslint configured)"
160
+ echo ""
161
+ echo "To bypass: git commit --no-verify"
162
+ echo "To remove: ./scripts/flow setup-hooks uninstall"
163
+ }
164
+
165
+ uninstall_hooks() {
166
+ if [ -f ".git/hooks/pre-commit" ]; then
167
+ # Check if it's our hook
168
+ if grep -q "Wogi Flow" .git/hooks/pre-commit 2>/dev/null; then
169
+ rm .git/hooks/pre-commit
170
+ echo -e "${GREEN}✓ Pre-commit hook removed${NC}"
171
+ else
172
+ echo -e "${YELLOW}Pre-commit hook exists but wasn't installed by Wogi Flow${NC}"
173
+ echo "Remove manually if desired: rm .git/hooks/pre-commit"
174
+ fi
175
+ else
176
+ echo "No pre-commit hook installed"
177
+ fi
178
+ }
179
+
180
+ check_status() {
181
+ echo -e "${CYAN}Hook Status${NC}"
182
+ echo ""
183
+
184
+ if [ ! -d ".git" ]; then
185
+ echo -e "${YELLOW}Not a git repository${NC}"
186
+ exit 0
187
+ fi
188
+
189
+ if [ -f ".git/hooks/pre-commit" ]; then
190
+ if grep -q "Wogi Flow" .git/hooks/pre-commit 2>/dev/null; then
191
+ echo -e "${GREEN}✓${NC} Wogi Flow pre-commit hook installed"
192
+ else
193
+ echo -e "${YELLOW}○${NC} Pre-commit hook exists (not Wogi Flow)"
194
+ fi
195
+ else
196
+ echo -e "${YELLOW}○${NC} No pre-commit hook installed"
197
+ fi
198
+ }
199
+
200
+ case "${1:-}" in
201
+ install)
202
+ install_hooks
203
+ ;;
204
+ uninstall)
205
+ uninstall_hooks
206
+ ;;
207
+ status)
208
+ check_status
209
+ ;;
210
+ help|--help|-h)
211
+ show_help
212
+ ;;
213
+ *)
214
+ show_help
215
+ ;;
216
+ esac
@@ -0,0 +1,377 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Git Hooks Setup
5
+ *
6
+ * Installs git hooks for automatic workflow integration:
7
+ * - pre-commit: Optionally runs component index scan
8
+ * - post-commit: Optionally syncs rules from decisions.md
9
+ *
10
+ * Usage:
11
+ * node scripts/flow-setup-hooks.js # Install hooks
12
+ * node scripts/flow-setup-hooks.js --remove # Remove hooks
13
+ * node scripts/flow-setup-hooks.js --status # Check hook status
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const {
19
+ getProjectRoot,
20
+ getConfig,
21
+ color,
22
+ success,
23
+ warn,
24
+ error
25
+ } = require('./flow-utils');
26
+
27
+ const PROJECT_ROOT = getProjectRoot();
28
+ const GIT_DIR = path.join(PROJECT_ROOT, '.git');
29
+ const HOOKS_DIR = path.join(GIT_DIR, 'hooks');
30
+
31
+ // Hook marker to identify our managed hooks
32
+ const HOOK_MARKER = '# WOGI_FLOW_MANAGED_HOOK';
33
+
34
+ // ============================================================
35
+ // Hook Templates
36
+ // ============================================================
37
+
38
+ const PRE_COMMIT_HOOK = `#!/bin/sh
39
+ ${HOOK_MARKER}
40
+ # Wogi Flow Pre-commit Hook
41
+ # Auto-generated - do not edit manually
42
+
43
+ # Check config for what to run
44
+ CONFIG_FILE=".workflow/config.json"
45
+
46
+ # Function to check if a feature is enabled in config
47
+ check_config() {
48
+ local key="$1"
49
+ local default="$2"
50
+ if [ -f "$CONFIG_FILE" ]; then
51
+ python3 -c "
52
+ import json
53
+ try:
54
+ with open('$CONFIG_FILE', 'r') as f:
55
+ config = json.load(f)
56
+ keys = '$key'.split('.')
57
+ val = config
58
+ for k in keys:
59
+ val = val.get(k, {}) if isinstance(val, dict) else {}
60
+ result = val if val != {} else '$default'
61
+ print('true' if result == True or result == 'true' else 'false' if result == False or result == 'false' else result)
62
+ except Exception as e:
63
+ print('$default')
64
+ " 2>/dev/null
65
+ else
66
+ echo "$default"
67
+ fi
68
+ }
69
+
70
+ # Run component index scan if configured
71
+ SCAN_ON_COMMIT=$(check_config "componentIndex.scanOn" "[]" | grep -q "preCommit" && echo "true" || echo "false")
72
+ if [ "$SCAN_ON_COMMIT" = "true" ]; then
73
+ echo "🔄 Updating component index..."
74
+ bash scripts/flow-map-index scan --quiet 2>/dev/null || true
75
+ fi
76
+
77
+ # Sync rules if decisions.md was modified
78
+ if git diff --cached --name-only | grep -q "decisions.md"; then
79
+ echo "📋 Syncing rules from decisions.md..."
80
+ node scripts/flow-rules-sync.js 2>/dev/null || true
81
+ git add .claude/rules/*.md 2>/dev/null || true
82
+ fi
83
+
84
+ # Continue with commit
85
+ exit 0
86
+ `;
87
+
88
+ const POST_COMMIT_HOOK = `#!/bin/sh
89
+ ${HOOK_MARKER}
90
+ # Wogi Flow Post-commit Hook
91
+ # Auto-generated - do not edit manually
92
+
93
+ # Optional: Log commit to request log
94
+ # This is disabled by default as it can be noisy
95
+
96
+ exit 0
97
+ `;
98
+
99
+ // ============================================================
100
+ // Hook Management
101
+ // ============================================================
102
+
103
+ /**
104
+ * Check if .git directory exists
105
+ */
106
+ function isGitRepo() {
107
+ return fs.existsSync(GIT_DIR);
108
+ }
109
+
110
+ /**
111
+ * Check if a hook is managed by Wogi Flow
112
+ */
113
+ function isOurHook(hookPath) {
114
+ if (!fs.existsSync(hookPath)) return false;
115
+ const content = fs.readFileSync(hookPath, 'utf-8');
116
+ return content.includes(HOOK_MARKER);
117
+ }
118
+
119
+ /**
120
+ * Install a hook
121
+ */
122
+ function installHook(name, content) {
123
+ const hookPath = path.join(HOOKS_DIR, name);
124
+
125
+ // Create hooks directory if it doesn't exist
126
+ if (!fs.existsSync(HOOKS_DIR)) {
127
+ fs.mkdirSync(HOOKS_DIR, { recursive: true });
128
+ }
129
+
130
+ // Check if there's an existing hook
131
+ if (fs.existsSync(hookPath) && !isOurHook(hookPath)) {
132
+ const existingContent = fs.readFileSync(hookPath, 'utf-8');
133
+ // Backup existing hook
134
+ const backupPath = `${hookPath}.backup`;
135
+ fs.writeFileSync(backupPath, existingContent);
136
+ warn(`Backed up existing ${name} hook to ${name}.backup`);
137
+ }
138
+
139
+ // Write new hook
140
+ fs.writeFileSync(hookPath, content);
141
+ fs.chmodSync(hookPath, '755');
142
+
143
+ return true;
144
+ }
145
+
146
+ /**
147
+ * Remove a hook
148
+ */
149
+ function removeHook(name) {
150
+ const hookPath = path.join(HOOKS_DIR, name);
151
+
152
+ if (!fs.existsSync(hookPath)) {
153
+ return { existed: false };
154
+ }
155
+
156
+ if (!isOurHook(hookPath)) {
157
+ return { existed: true, skipped: true, reason: 'Not a Wogi Flow hook' };
158
+ }
159
+
160
+ fs.unlinkSync(hookPath);
161
+
162
+ // Restore backup if exists
163
+ const backupPath = `${hookPath}.backup`;
164
+ if (fs.existsSync(backupPath)) {
165
+ fs.renameSync(backupPath, hookPath);
166
+ return { existed: true, restored: true };
167
+ }
168
+
169
+ return { existed: true, removed: true };
170
+ }
171
+
172
+ /**
173
+ * Get hook status
174
+ */
175
+ function getHookStatus(name) {
176
+ const hookPath = path.join(HOOKS_DIR, name);
177
+
178
+ if (!fs.existsSync(hookPath)) {
179
+ return { installed: false };
180
+ }
181
+
182
+ const isManaged = isOurHook(hookPath);
183
+ const stats = fs.statSync(hookPath);
184
+ const isExecutable = (stats.mode & 0o111) !== 0;
185
+
186
+ return {
187
+ installed: true,
188
+ managed: isManaged,
189
+ executable: isExecutable,
190
+ path: hookPath
191
+ };
192
+ }
193
+
194
+ // ============================================================
195
+ // Main Commands
196
+ // ============================================================
197
+
198
+ function installHooks() {
199
+ if (!isGitRepo()) {
200
+ error('Not a git repository. Run this from the project root.');
201
+ process.exit(1);
202
+ }
203
+
204
+ console.log(color('cyan', '🪝 Installing Git Hooks'));
205
+ console.log('');
206
+
207
+ const results = [];
208
+
209
+ // Install pre-commit hook
210
+ try {
211
+ installHook('pre-commit', PRE_COMMIT_HOOK);
212
+ results.push({ name: 'pre-commit', success: true });
213
+ console.log(` ${color('green', '✓')} pre-commit hook installed`);
214
+ } catch (err) {
215
+ results.push({ name: 'pre-commit', success: false, error: err.message });
216
+ console.log(` ${color('red', '✗')} pre-commit: ${err.message}`);
217
+ }
218
+
219
+ // Install post-commit hook
220
+ try {
221
+ installHook('post-commit', POST_COMMIT_HOOK);
222
+ results.push({ name: 'post-commit', success: true });
223
+ console.log(` ${color('green', '✓')} post-commit hook installed`);
224
+ } catch (err) {
225
+ results.push({ name: 'post-commit', success: false, error: err.message });
226
+ console.log(` ${color('red', '✗')} post-commit: ${err.message}`);
227
+ }
228
+
229
+ console.log('');
230
+
231
+ const allSuccess = results.every(r => r.success);
232
+ if (allSuccess) {
233
+ success('Git hooks installed successfully');
234
+ console.log('');
235
+ console.log(color('dim', 'Configure in .workflow/config.json:'));
236
+ console.log(color('dim', ' componentIndex.scanOn: ["preCommit", "afterTask", "sessionStart"]'));
237
+ } else {
238
+ warn('Some hooks failed to install');
239
+ }
240
+
241
+ return results;
242
+ }
243
+
244
+ function removeHooks() {
245
+ if (!isGitRepo()) {
246
+ error('Not a git repository');
247
+ process.exit(1);
248
+ }
249
+
250
+ console.log(color('cyan', '🪝 Removing Git Hooks'));
251
+ console.log('');
252
+
253
+ const hooks = ['pre-commit', 'post-commit'];
254
+
255
+ for (const hook of hooks) {
256
+ const result = removeHook(hook);
257
+ if (result.skipped) {
258
+ console.log(` ${color('yellow', '○')} ${hook}: ${result.reason}`);
259
+ } else if (result.restored) {
260
+ console.log(` ${color('green', '✓')} ${hook} removed (backup restored)`);
261
+ } else if (result.removed) {
262
+ console.log(` ${color('green', '✓')} ${hook} removed`);
263
+ } else {
264
+ console.log(` ${color('dim', '-')} ${hook}: not installed`);
265
+ }
266
+ }
267
+
268
+ console.log('');
269
+ success('Git hooks removed');
270
+ }
271
+
272
+ function showStatus() {
273
+ if (!isGitRepo()) {
274
+ error('Not a git repository');
275
+ process.exit(1);
276
+ }
277
+
278
+ console.log(color('cyan', '🪝 Git Hook Status'));
279
+ console.log('');
280
+
281
+ const hooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
282
+
283
+ for (const hook of hooks) {
284
+ const status = getHookStatus(hook);
285
+
286
+ if (!status.installed) {
287
+ console.log(` ${color('dim', '-')} ${hook}: not installed`);
288
+ } else if (status.managed) {
289
+ console.log(` ${color('green', '✓')} ${hook}: installed (Wogi Flow managed)`);
290
+ } else {
291
+ console.log(` ${color('yellow', '○')} ${hook}: installed (external)`);
292
+ }
293
+ }
294
+
295
+ console.log('');
296
+
297
+ // Show config
298
+ try {
299
+ const config = getConfig();
300
+ const scanOn = config.componentIndex?.scanOn || [];
301
+ console.log(color('dim', 'Config: componentIndex.scanOn = ' + JSON.stringify(scanOn)));
302
+ } catch {
303
+ console.log(color('dim', 'Config: Unable to read'));
304
+ }
305
+ }
306
+
307
+ function showHelp() {
308
+ console.log(`
309
+ Wogi Flow - Git Hooks Setup
310
+
311
+ Install git hooks for automatic workflow integration.
312
+
313
+ Usage:
314
+ node scripts/flow-setup-hooks.js # Install hooks
315
+ node scripts/flow-setup-hooks.js --remove # Remove hooks
316
+ node scripts/flow-setup-hooks.js --status # Check status
317
+ node scripts/flow-setup-hooks.js --help # Show this help
318
+
319
+ Hooks installed:
320
+ pre-commit - Sync rules, optionally scan component index
321
+ post-commit - (Reserved for future use)
322
+
323
+ Configuration:
324
+ In .workflow/config.json, set componentIndex.scanOn to include "preCommit":
325
+
326
+ {
327
+ "componentIndex": {
328
+ "scanOn": ["sessionStart", "afterTask", "preCommit"]
329
+ }
330
+ }
331
+ `);
332
+ }
333
+
334
+ // ============================================================
335
+ // CLI
336
+ // ============================================================
337
+
338
+ function main() {
339
+ const args = process.argv.slice(2);
340
+
341
+ if (args.includes('--help') || args.includes('-h')) {
342
+ showHelp();
343
+ process.exit(0);
344
+ }
345
+
346
+ if (args.includes('--remove') || args.includes('--uninstall')) {
347
+ removeHooks();
348
+ process.exit(0);
349
+ }
350
+
351
+ if (args.includes('--status')) {
352
+ showStatus();
353
+ process.exit(0);
354
+ }
355
+
356
+ // Default: install hooks
357
+ installHooks();
358
+ }
359
+
360
+ // ============================================================
361
+ // Exports
362
+ // ============================================================
363
+
364
+ module.exports = {
365
+ installHook,
366
+ removeHook,
367
+ getHookStatus,
368
+ isOurHook,
369
+ installHooks,
370
+ removeHooks,
371
+ showStatus,
372
+ HOOK_MARKER
373
+ };
374
+
375
+ if (require.main === module) {
376
+ main();
377
+ }