@pjmendonca/devflow 1.13.2 → 1.19.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 (236) hide show
  1. package/.claude/commands/agent.md +1 -1
  2. package/.claude/commands/brainstorm.md +28 -0
  3. package/.claude/commands/bugfix.md +21 -0
  4. package/.claude/commands/checkpoint.md +0 -1
  5. package/.claude/commands/collab.md +0 -1
  6. package/.claude/commands/costs.md +88 -18
  7. package/.claude/commands/devflow.md +26 -0
  8. package/.claude/commands/handoff.md +0 -1
  9. package/.claude/commands/init.md +383 -0
  10. package/.claude/commands/memory.md +0 -1
  11. package/.claude/commands/pair.md +0 -1
  12. package/.claude/commands/review.md +27 -0
  13. package/.claude/commands/route.md +0 -1
  14. package/.claude/commands/swarm.md +0 -1
  15. package/.claude/commands/validate.md +55 -0
  16. package/.claude/hooks/session-notification.sh +44 -0
  17. package/.claude/hooks/session-startup.sh +427 -0
  18. package/.claude/hooks/session-stop.sh +38 -0
  19. package/.claude/hooks/session_tracker.py +272 -0
  20. package/.claude/settings.json +38 -0
  21. package/.claude/skills/brainstorm/SKILL.md +531 -0
  22. package/.claude/skills/costs/SKILL.md +156 -0
  23. package/.claude/skills/validate/SKILL.md +101 -0
  24. package/CHANGELOG.md +284 -0
  25. package/README.md +207 -10
  26. package/bin/devflow-install.js +2 -1
  27. package/bin/devflow.js +4 -0
  28. package/lib/constants.js +0 -1
  29. package/lib/exec-python.js +1 -1
  30. package/package.json +1 -1
  31. package/tooling/.automation/.checkpoint_lock +1 -0
  32. package/tooling/.automation/agents/architect.md +19 -0
  33. package/tooling/.automation/agents/ba.md +19 -0
  34. package/tooling/.automation/agents/maintainer.md +19 -0
  35. package/tooling/.automation/agents/pm.md +19 -0
  36. package/tooling/.automation/agents/reviewer.md +1 -1
  37. package/tooling/.automation/agents/writer.md +19 -0
  38. package/tooling/.automation/benchmarks/benchmark_20251230_100119.json +314 -0
  39. package/tooling/.automation/benchmarks/benchmark_20251230_100216.json +314 -0
  40. package/tooling/.automation/costs/config.json +31 -0
  41. package/tooling/.automation/costs/sessions/2025-12-29_20251229_164128.json +22 -0
  42. package/tooling/.automation/memory/knowledge/kg_integration-test.json +738 -1
  43. package/tooling/.automation/memory/knowledge/kg_test-story.json +3381 -2
  44. package/tooling/.automation/memory/shared/shared_integration-test.json +193 -1
  45. package/tooling/.automation/memory/shared/shared_test-story.json +757 -1
  46. package/tooling/.automation/memory/shared/shared_test.json +1332 -0
  47. package/tooling/.automation/memory/shared/shared_validation-check.json +240 -0
  48. package/tooling/.automation/overrides/templates/architect/cloud-native.yaml +5 -5
  49. package/tooling/.automation/overrides/templates/architect/enterprise-architect.yaml +23 -5
  50. package/tooling/.automation/overrides/templates/architect/pragmatic-minimalist.yaml +24 -6
  51. package/tooling/.automation/overrides/templates/ba/agile-storyteller.yaml +4 -4
  52. package/tooling/.automation/overrides/templates/ba/domain-expert.yaml +4 -4
  53. package/tooling/.automation/overrides/templates/ba/requirements-engineer.yaml +4 -4
  54. package/tooling/.automation/overrides/templates/dev/performance-engineer.yaml +18 -0
  55. package/tooling/.automation/overrides/templates/dev/rapid-prototyper.yaml +19 -1
  56. package/tooling/.automation/overrides/templates/dev/security-focused.yaml +18 -0
  57. package/tooling/.automation/overrides/templates/dev/user-advocate.yaml +54 -0
  58. package/tooling/.automation/overrides/templates/maintainer/devops-maintainer.yaml +4 -4
  59. package/tooling/.automation/overrides/templates/maintainer/legacy-steward.yaml +4 -4
  60. package/tooling/.automation/overrides/templates/maintainer/oss-maintainer.yaml +4 -4
  61. package/tooling/.automation/overrides/templates/maintainer/reliability-engineer.yaml +55 -0
  62. package/tooling/.automation/overrides/templates/pm/agile-pm.yaml +4 -4
  63. package/tooling/.automation/overrides/templates/pm/hybrid-delivery.yaml +3 -3
  64. package/tooling/.automation/overrides/templates/pm/traditional-pm.yaml +4 -4
  65. package/tooling/.automation/overrides/templates/reviewer/quick-sanity.yaml +18 -0
  66. package/tooling/.automation/overrides/templates/reviewer/thorough-critic.yaml +18 -0
  67. package/tooling/.automation/overrides/templates/sm/agile-coach.yaml +2 -2
  68. package/tooling/.automation/overrides/templates/sm/startup-pm.yaml +3 -3
  69. package/tooling/.automation/overrides/templates/writer/api-documentarian.yaml +5 -5
  70. package/tooling/.automation/overrides/templates/writer/docs-as-code.yaml +4 -4
  71. package/tooling/.automation/overrides/templates/writer/user-guide-author.yaml +5 -5
  72. package/tooling/.automation/validation/history/2025-12-29_val_002a28c1.json +32 -0
  73. package/tooling/.automation/validation/history/2025-12-29_val_01273bb1.json +32 -0
  74. package/tooling/.automation/validation/history/2025-12-29_val_03369914.json +41 -0
  75. package/tooling/.automation/validation/history/2025-12-29_val_07a449ba.json +32 -0
  76. package/tooling/.automation/validation/history/2025-12-29_val_0df1f0a2.json +41 -0
  77. package/tooling/.automation/validation/history/2025-12-29_val_10ff3d34.json +41 -0
  78. package/tooling/.automation/validation/history/2025-12-29_val_110771d7.json +32 -0
  79. package/tooling/.automation/validation/history/2025-12-29_val_13f3a7f9.json +32 -0
  80. package/tooling/.automation/validation/history/2025-12-29_val_17ba9d21.json +41 -0
  81. package/tooling/.automation/validation/history/2025-12-29_val_22247089.json +32 -0
  82. package/tooling/.automation/validation/history/2025-12-29_val_227ea6a4.json +32 -0
  83. package/tooling/.automation/validation/history/2025-12-29_val_2335d5ae.json +32 -0
  84. package/tooling/.automation/validation/history/2025-12-29_val_246824bb.json +41 -0
  85. package/tooling/.automation/validation/history/2025-12-29_val_28b4b9cd.json +32 -0
  86. package/tooling/.automation/validation/history/2025-12-29_val_2abd12cc.json +32 -0
  87. package/tooling/.automation/validation/history/2025-12-29_val_2c801b2f.json +59 -0
  88. package/tooling/.automation/validation/history/2025-12-29_val_2c8cfa8e.json +32 -0
  89. package/tooling/.automation/validation/history/2025-12-29_val_2ce76eb0.json +32 -0
  90. package/tooling/.automation/validation/history/2025-12-29_val_30351948.json +41 -0
  91. package/tooling/.automation/validation/history/2025-12-29_val_30eb7229.json +41 -0
  92. package/tooling/.automation/validation/history/2025-12-29_val_34df0e77.json +41 -0
  93. package/tooling/.automation/validation/history/2025-12-29_val_376e4d6a.json +32 -0
  94. package/tooling/.automation/validation/history/2025-12-29_val_3a4e8a1a.json +59 -0
  95. package/tooling/.automation/validation/history/2025-12-29_val_3b77a628.json +32 -0
  96. package/tooling/.automation/validation/history/2025-12-29_val_3ea4e1cf.json +59 -0
  97. package/tooling/.automation/validation/history/2025-12-29_val_44aacdb4.json +59 -0
  98. package/tooling/.automation/validation/history/2025-12-29_val_457ddfa8.json +32 -0
  99. package/tooling/.automation/validation/history/2025-12-29_val_45af6238.json +41 -0
  100. package/tooling/.automation/validation/history/2025-12-29_val_4735dba1.json +41 -0
  101. package/tooling/.automation/validation/history/2025-12-29_val_486b203c.json +41 -0
  102. package/tooling/.automation/validation/history/2025-12-29_val_49dc56cd.json +59 -0
  103. package/tooling/.automation/validation/history/2025-12-29_val_4d863d6d.json +32 -0
  104. package/tooling/.automation/validation/history/2025-12-29_val_5149a808.json +59 -0
  105. package/tooling/.automation/validation/history/2025-12-29_val_52e0bb43.json +32 -0
  106. package/tooling/.automation/validation/history/2025-12-29_val_585d6319.json +59 -0
  107. package/tooling/.automation/validation/history/2025-12-29_val_5b2d859a.json +32 -0
  108. package/tooling/.automation/validation/history/2025-12-29_val_635a7081.json +41 -0
  109. package/tooling/.automation/validation/history/2025-12-29_val_64df4905.json +32 -0
  110. package/tooling/.automation/validation/history/2025-12-29_val_70634cee.json +41 -0
  111. package/tooling/.automation/validation/history/2025-12-29_val_714553f9.json +32 -0
  112. package/tooling/.automation/validation/history/2025-12-29_val_7f7bfdbf.json +41 -0
  113. package/tooling/.automation/validation/history/2025-12-29_val_7faad91d.json +32 -0
  114. package/tooling/.automation/validation/history/2025-12-29_val_81821f8f.json +41 -0
  115. package/tooling/.automation/validation/history/2025-12-29_val_8249f3c9.json +32 -0
  116. package/tooling/.automation/validation/history/2025-12-29_val_8422b50f.json +41 -0
  117. package/tooling/.automation/validation/history/2025-12-29_val_8446c134.json +32 -0
  118. package/tooling/.automation/validation/history/2025-12-29_val_879f4e26.json +59 -0
  119. package/tooling/.automation/validation/history/2025-12-29_val_8b6d5bd7.json +32 -0
  120. package/tooling/.automation/validation/history/2025-12-29_val_8c5cd787.json +32 -0
  121. package/tooling/.automation/validation/history/2025-12-29_val_91d20bc7.json +32 -0
  122. package/tooling/.automation/validation/history/2025-12-29_val_958a12b7.json +41 -0
  123. package/tooling/.automation/validation/history/2025-12-29_val_95d91108.json +41 -0
  124. package/tooling/.automation/validation/history/2025-12-29_val_980dbb74.json +32 -0
  125. package/tooling/.automation/validation/history/2025-12-29_val_9e40c79b.json +32 -0
  126. package/tooling/.automation/validation/history/2025-12-29_val_9f499b7c.json +32 -0
  127. package/tooling/.automation/validation/history/2025-12-29_val_9f7c3b57.json +32 -0
  128. package/tooling/.automation/validation/history/2025-12-29_val_a30d5bd4.json +32 -0
  129. package/tooling/.automation/validation/history/2025-12-29_val_a6eb09c7.json +32 -0
  130. package/tooling/.automation/validation/history/2025-12-29_val_a86f7b83.json +41 -0
  131. package/tooling/.automation/validation/history/2025-12-29_val_ad5347e1.json +41 -0
  132. package/tooling/.automation/validation/history/2025-12-29_val_b0a5a993.json +32 -0
  133. package/tooling/.automation/validation/history/2025-12-29_val_bcb0192e.json +32 -0
  134. package/tooling/.automation/validation/history/2025-12-29_val_bf3c9aaa.json +32 -0
  135. package/tooling/.automation/validation/history/2025-12-29_val_c461ff88.json +32 -0
  136. package/tooling/.automation/validation/history/2025-12-29_val_c4f4e258.json +41 -0
  137. package/tooling/.automation/validation/history/2025-12-29_val_c7f0fa6d.json +41 -0
  138. package/tooling/.automation/validation/history/2025-12-29_val_c911b0e6.json +32 -0
  139. package/tooling/.automation/validation/history/2025-12-29_val_cc581964.json +32 -0
  140. package/tooling/.automation/validation/history/2025-12-29_val_cdd5a33b.json +32 -0
  141. package/tooling/.automation/validation/history/2025-12-29_val_cfd42495.json +32 -0
  142. package/tooling/.automation/validation/history/2025-12-29_val_d1c7a4ee.json +41 -0
  143. package/tooling/.automation/validation/history/2025-12-29_val_d2280d0e.json +32 -0
  144. package/tooling/.automation/validation/history/2025-12-29_val_d2a6ff69.json +32 -0
  145. package/tooling/.automation/validation/history/2025-12-29_val_d8c53ab2.json +59 -0
  146. package/tooling/.automation/validation/history/2025-12-29_val_d9c1247a.json +41 -0
  147. package/tooling/.automation/validation/history/2025-12-29_val_d9d58569.json +32 -0
  148. package/tooling/.automation/validation/history/2025-12-29_val_dabb4fd9.json +32 -0
  149. package/tooling/.automation/validation/history/2025-12-29_val_dd8fe359.json +32 -0
  150. package/tooling/.automation/validation/history/2025-12-29_val_decdffc9.json +32 -0
  151. package/tooling/.automation/validation/history/2025-12-29_val_e3a95476.json +59 -0
  152. package/tooling/.automation/validation/history/2025-12-29_val_e776dfca.json +32 -0
  153. package/tooling/.automation/validation/history/2025-12-29_val_ea70969f.json +59 -0
  154. package/tooling/.automation/validation/history/2025-12-29_val_ef41ea95.json +32 -0
  155. package/tooling/.automation/validation/history/2025-12-29_val_f384f9b1.json +32 -0
  156. package/tooling/.automation/validation/history/2025-12-29_val_f8adc38c.json +41 -0
  157. package/tooling/.automation/validation/history/2025-12-29_val_fa40b69e.json +32 -0
  158. package/tooling/.automation/validation/history/2025-12-29_val_fc538d54.json +41 -0
  159. package/tooling/.automation/validation/history/2025-12-29_val_fe814665.json +32 -0
  160. package/tooling/.automation/validation/history/2025-12-29_val_ffea4b12.json +32 -0
  161. package/tooling/.automation/validation/history/2025-12-30_val_02d001e5.json +59 -0
  162. package/tooling/.automation/validation/history/2025-12-30_val_0b8966dc.json +32 -0
  163. package/tooling/.automation/validation/history/2025-12-30_val_15455fbf.json +59 -0
  164. package/tooling/.automation/validation/history/2025-12-30_val_157e34b9.json +32 -0
  165. package/tooling/.automation/validation/history/2025-12-30_val_28d1d933.json +32 -0
  166. package/tooling/.automation/validation/history/2025-12-30_val_3442a52c.json +32 -0
  167. package/tooling/.automation/validation/history/2025-12-30_val_37f1ce1e.json +32 -0
  168. package/tooling/.automation/validation/history/2025-12-30_val_4f1d8a93.json +32 -0
  169. package/tooling/.automation/validation/history/2025-12-30_val_56ff1de3.json +32 -0
  170. package/tooling/.automation/validation/history/2025-12-30_val_664fd4e2.json +41 -0
  171. package/tooling/.automation/validation/history/2025-12-30_val_66afb0a7.json +32 -0
  172. package/tooling/.automation/validation/history/2025-12-30_val_7634663c.json +41 -0
  173. package/tooling/.automation/validation/history/2025-12-30_val_8ea830c3.json +41 -0
  174. package/tooling/.automation/validation/history/2025-12-30_val_998957c2.json +32 -0
  175. package/tooling/.automation/validation/history/2025-12-30_val_a52177db.json +32 -0
  176. package/tooling/.automation/validation/history/2025-12-30_val_a5b65a63.json +32 -0
  177. package/tooling/.automation/validation/history/2025-12-30_val_ae391d0e.json +32 -0
  178. package/tooling/.automation/validation/history/2025-12-30_val_c7895339.json +41 -0
  179. package/tooling/.automation/validation/history/2025-12-30_val_ca416593.json +41 -0
  180. package/tooling/.automation/validation/history/2025-12-30_val_cee19422.json +32 -0
  181. package/tooling/.automation/validation/history/2025-12-30_val_ddd4f4e6.json +32 -0
  182. package/tooling/.automation/validation/history/2025-12-30_val_f2e1394b.json +32 -0
  183. package/tooling/.automation/validation/history/2025-12-30_val_f4a7fa06.json +41 -0
  184. package/tooling/.automation/validation/history/2025-12-30_val_ffea3369.json +32 -0
  185. package/tooling/.automation/validation/history/2026-01-03_val_1287a74c.json +41 -0
  186. package/tooling/.automation/validation/history/2026-01-03_val_3b24071f.json +32 -0
  187. package/tooling/.automation/validation/history/2026-01-03_val_44d77573.json +32 -0
  188. package/tooling/.automation/validation/history/2026-01-03_val_5b31dc51.json +32 -0
  189. package/tooling/.automation/validation/history/2026-01-03_val_74267244.json +32 -0
  190. package/tooling/.automation/validation/history/2026-01-03_val_8b2d95c7.json +59 -0
  191. package/tooling/.automation/validation/history/2026-01-03_val_d875b297.json +41 -0
  192. package/tooling/.automation/validation-config.yaml +103 -0
  193. package/tooling/completions/DevflowCompletion.ps1 +21 -21
  194. package/tooling/completions/_run-story +3 -3
  195. package/tooling/completions/run-story-completion.bash +8 -8
  196. package/tooling/docs/DOC-STANDARD.md +14 -14
  197. package/tooling/docs/stories/.gitkeep +0 -0
  198. package/tooling/docs/templates/brainstorm-guide.md +314 -0
  199. package/tooling/docs/templates/migration-spec.md +4 -4
  200. package/tooling/docs/templates/story.md +66 -0
  201. package/tooling/scripts/context_checkpoint.py +5 -15
  202. package/tooling/scripts/cost_dashboard.py +610 -13
  203. package/tooling/scripts/create-persona.py +1 -12
  204. package/tooling/scripts/create-persona.sh +44 -44
  205. package/tooling/scripts/lib/__init__.py +12 -1
  206. package/tooling/scripts/lib/agent_handoff.py +11 -2
  207. package/tooling/scripts/lib/agent_router.py +31 -10
  208. package/tooling/scripts/lib/colors.py +106 -0
  209. package/tooling/scripts/lib/context_monitor.py +766 -0
  210. package/tooling/scripts/lib/cost_config.py +229 -10
  211. package/tooling/scripts/lib/cost_display.py +20 -45
  212. package/tooling/scripts/lib/cost_tracker.py +462 -15
  213. package/tooling/scripts/lib/currency_converter.py +28 -5
  214. package/tooling/scripts/lib/pair_programming.py +102 -3
  215. package/tooling/scripts/lib/personality_system.py +949 -0
  216. package/tooling/scripts/lib/platform.py +55 -0
  217. package/tooling/scripts/lib/shared_memory.py +9 -3
  218. package/tooling/scripts/lib/swarm_orchestrator.py +514 -75
  219. package/tooling/scripts/lib/validation_loop.py +1014 -0
  220. package/tooling/scripts/memory_summarize.py +9 -2
  221. package/tooling/scripts/new-doc.py +2 -9
  222. package/tooling/scripts/personalize_agent.py +1 -12
  223. package/tooling/scripts/rollback-migration.sh +60 -60
  224. package/tooling/scripts/run-collab.ps1 +16 -16
  225. package/tooling/scripts/run-collab.py +88 -53
  226. package/tooling/scripts/run-collab.sh +4 -4
  227. package/tooling/scripts/run-story.py +278 -20
  228. package/tooling/scripts/run-story.sh +3 -3
  229. package/tooling/scripts/setup-checkpoint-service.py +2 -9
  230. package/tooling/scripts/tech-debt-tracker.py +1 -12
  231. package/tooling/scripts/test_adversarial_swarm.py +452 -0
  232. package/tooling/scripts/validate-overrides.py +1 -10
  233. package/tooling/scripts/validate-overrides.sh +40 -40
  234. package/tooling/scripts/validate_loop.py +162 -0
  235. package/tooling/scripts/validate_setup.py +2 -30
  236. package/.claude/skills/init/SKILL.md +0 -496
@@ -80,42 +80,42 @@ info() {
80
80
  # Check if file has valid YAML syntax using basic shell parsing
81
81
  check_yaml_syntax() {
82
82
  local file="$1"
83
-
83
+
84
84
  # Check for common YAML syntax issues
85
85
  local line_num=0
86
86
  local in_list=false
87
87
  local prev_indent=0
88
-
88
+
89
89
  while IFS= read -r line || [[ -n "$line" ]]; do
90
90
  ((line_num++))
91
-
91
+
92
92
  # Skip empty lines and comments
93
93
  [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
94
-
94
+
95
95
  # Check for tabs (YAML should use spaces)
96
96
  if [[ "$line" == *$'\t'* ]]; then
97
97
  error "Line $line_num: Contains tabs (use spaces instead)"
98
98
  return 1
99
99
  fi
100
-
100
+
101
101
  # Check for trailing spaces
102
102
  if [[ "$line" =~ [[:space:]]$ ]]; then
103
103
  warning "Line $line_num: Trailing whitespace"
104
104
  fi
105
-
105
+
106
106
  # Check for unclosed quotes
107
107
  local quote_count=$(echo "$line" | grep -o '"' | wc -l | tr -d ' ')
108
108
  if [[ $((quote_count % 2)) -ne 0 ]]; then
109
109
  error "Line $line_num: Unclosed double quote"
110
110
  return 1
111
111
  fi
112
-
112
+
113
113
  local single_quote_count=$(echo "$line" | grep -o "'" | wc -l | tr -d ' ')
114
114
  if [[ $((single_quote_count % 2)) -ne 0 ]]; then
115
115
  error "Line $line_num: Unclosed single quote"
116
116
  return 1
117
117
  fi
118
-
118
+
119
119
  # Check for proper colon spacing in key-value pairs
120
120
  if [[ "$line" =~ ^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*:[^[:space:]] && ! "$line" =~ ^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*:$ ]]; then
121
121
  # Allow for URLs and special cases
@@ -123,9 +123,9 @@ check_yaml_syntax() {
123
123
  warning "Line $line_num: Missing space after colon"
124
124
  fi
125
125
  fi
126
-
126
+
127
127
  done < "$file"
128
-
128
+
129
129
  return 0
130
130
  }
131
131
 
@@ -152,10 +152,10 @@ validate_override_file() {
152
152
  local file="$1"
153
153
  local filename=$(basename "$file")
154
154
  local agent_name="${filename%.override.yaml}"
155
-
155
+
156
156
  echo ""
157
157
  echo -e "${BLUE}Validating:${NC} $filename"
158
-
158
+
159
159
  # Check if corresponding agent exists
160
160
  local agent_file="$AGENTS_DIR/${agent_name}.md"
161
161
  if [[ ! -f "$agent_file" ]]; then
@@ -164,14 +164,14 @@ validate_override_file() {
164
164
  else
165
165
  info "Agent file found: ${agent_name}.md"
166
166
  fi
167
-
167
+
168
168
  # Check YAML syntax
169
169
  if ! check_yaml_syntax "$file"; then
170
170
  error "YAML syntax validation failed"
171
171
  return 1
172
172
  fi
173
173
  success "YAML syntax is valid"
174
-
174
+
175
175
  # Validate model override if present
176
176
  local model=$(yaml_get "$file" "model")
177
177
  if [[ -n "$model" ]]; then
@@ -182,14 +182,14 @@ validate_override_file() {
182
182
  break
183
183
  fi
184
184
  done
185
-
185
+
186
186
  if [[ "$valid" == "true" ]]; then
187
187
  success "Model override is valid: $model"
188
188
  else
189
189
  error "Invalid model: '$model'. Valid options: ${VALID_MODELS[*]}"
190
190
  fi
191
191
  fi
192
-
192
+
193
193
  # Validate budget override if present
194
194
  local budget=$(yaml_get "$file" "max_budget_usd")
195
195
  if [[ -n "$budget" ]]; then
@@ -206,56 +206,56 @@ validate_override_file() {
206
206
  error "Invalid budget format: '$budget' (must be a number)"
207
207
  fi
208
208
  fi
209
-
209
+
210
210
  # Check for additional_rules
211
211
  if yaml_has_list "$file" "additional_rules"; then
212
212
  local rule_count=$(awk '/^additional_rules:/{found=1; next} found && /^[[:space:]]*-/{count++} found && /^[a-zA-Z]/{exit} END{print count}' "$file")
213
213
  success "Additional rules defined: ${rule_count:-0} rules"
214
214
  fi
215
-
215
+
216
216
  # Check for memories
217
217
  if yaml_has_list "$file" "memories"; then
218
218
  local memory_count=$(awk '/^memories:/{found=1; next} found && /^[[:space:]]*-/{count++} found && /^[a-zA-Z]/{exit} END{print count}' "$file")
219
219
  success "Memories defined: ${memory_count:-0} items"
220
220
  fi
221
-
221
+
222
222
  # Check for critical_actions
223
223
  if yaml_has_list "$file" "critical_actions"; then
224
224
  local action_count=$(awk '/^critical_actions:/{found=1; next} found && /^[[:space:]]*-/{count++} found && /^[a-zA-Z]/{exit} END{print count}' "$file")
225
225
  success "Critical actions defined: ${action_count:-0} actions"
226
226
  fi
227
-
227
+
228
228
  ((VALIDATED++))
229
229
  return 0
230
230
  }
231
231
 
232
232
  validate_user_profile() {
233
233
  local file="$OVERRIDES_DIR/user-profile.yaml"
234
-
234
+
235
235
  if [[ ! -f "$file" ]]; then
236
236
  warning "No user-profile.yaml found"
237
237
  return 0
238
238
  fi
239
-
239
+
240
240
  echo ""
241
241
  echo -e "${BLUE}Validating:${NC} user-profile.yaml"
242
-
242
+
243
243
  # Check YAML syntax
244
244
  if ! check_yaml_syntax "$file"; then
245
245
  error "YAML syntax validation failed"
246
246
  return 1
247
247
  fi
248
248
  success "YAML syntax is valid"
249
-
249
+
250
250
  # Check for user section
251
251
  if grep -q "^user:" "$file"; then
252
252
  success "User section found"
253
-
253
+
254
254
  local name=$(grep -A10 "^user:" "$file" | grep "name:" | sed 's/.*name:[[:space:]]*//' | head -1)
255
255
  if [[ -n "$name" && "$name" != "User" ]]; then
256
256
  success "User name configured: $name"
257
257
  fi
258
-
258
+
259
259
  local level=$(grep -A10 "^user:" "$file" | grep "technical_level:" | sed 's/.*technical_level:[[:space:]]*//' | head -1)
260
260
  if [[ -n "$level" ]]; then
261
261
  local valid_levels=("beginner" "intermediate" "advanced" "expert")
@@ -266,7 +266,7 @@ validate_user_profile() {
266
266
  break
267
267
  fi
268
268
  done
269
-
269
+
270
270
  if [[ "$valid" == "true" ]]; then
271
271
  success "Technical level: $level"
272
272
  else
@@ -276,7 +276,7 @@ validate_user_profile() {
276
276
  else
277
277
  warning "No user section found in profile"
278
278
  fi
279
-
279
+
280
280
  ((VALIDATED++))
281
281
  return 0
282
282
  }
@@ -305,13 +305,13 @@ auto_fix_file() {
305
305
  local file="$1"
306
306
  echo ""
307
307
  echo -e "${YELLOW}Auto-fixing:${NC} $(basename "$file")"
308
-
308
+
309
309
  # Backup original
310
310
  cp "$file" "${file}.bak"
311
-
311
+
312
312
  fix_trailing_whitespace "$file"
313
313
  fix_tabs "$file"
314
-
314
+
315
315
  # Remove backup if no changes
316
316
  if diff -q "$file" "${file}.bak" > /dev/null 2>&1; then
317
317
  rm "${file}.bak"
@@ -345,7 +345,7 @@ main() {
345
345
  local target=""
346
346
  local FIX_MODE=false
347
347
  VERBOSE=false
348
-
348
+
349
349
  # Parse arguments
350
350
  while [[ $# -gt 0 ]]; do
351
351
  case "$1" in
@@ -365,14 +365,14 @@ main() {
365
365
  esac
366
366
  shift
367
367
  done
368
-
368
+
369
369
  print_header
370
-
370
+
371
371
  if [[ ! -d "$OVERRIDES_DIR" ]]; then
372
372
  error "Overrides directory not found: $OVERRIDES_DIR"
373
373
  exit 1
374
374
  fi
375
-
375
+
376
376
  if [[ -n "$target" ]]; then
377
377
  # Validate specific override
378
378
  local file="$OVERRIDES_DIR/${target}.override.yaml"
@@ -380,7 +380,7 @@ main() {
380
380
  error "Override file not found: $file"
381
381
  exit 1
382
382
  fi
383
-
383
+
384
384
  if [[ "$FIX_MODE" == "true" ]]; then
385
385
  auto_fix_file "$file"
386
386
  fi
@@ -388,13 +388,13 @@ main() {
388
388
  else
389
389
  # Validate all overrides
390
390
  echo -e "${BLUE}Scanning:${NC} $OVERRIDES_DIR"
391
-
391
+
392
392
  # Validate user profile first
393
393
  if [[ "$FIX_MODE" == "true" && -f "$OVERRIDES_DIR/user-profile.yaml" ]]; then
394
394
  auto_fix_file "$OVERRIDES_DIR/user-profile.yaml"
395
395
  fi
396
396
  validate_user_profile
397
-
397
+
398
398
  # Validate all override files
399
399
  for file in "$OVERRIDES_DIR"/*.override.yaml; do
400
400
  if [[ -f "$file" ]]; then
@@ -405,7 +405,7 @@ main() {
405
405
  fi
406
406
  done
407
407
  fi
408
-
408
+
409
409
  # Summary
410
410
  echo ""
411
411
  echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
@@ -416,7 +416,7 @@ main() {
416
416
  echo -e " Errors: ${RED}$ERRORS${NC}"
417
417
  echo -e " Warnings: ${YELLOW}$WARNINGS${NC}"
418
418
  echo ""
419
-
419
+
420
420
  if [[ $ERRORS -gt 0 ]]; then
421
421
  echo -e "${RED} Validation failed with $ERRORS error(s)${NC}"
422
422
  exit 1
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Validation Loop CLI - Standalone validation runner for CI/CD and CLI usage.
4
+
5
+ Runs the three-tier validation system:
6
+ - Tier 1: Pre-flight (story exists, budget, dependencies)
7
+ - Tier 2: Inter-phase (code compiles, lint, transitions)
8
+ - Tier 3: Post-completion (tests, types, version sync)
9
+
10
+ Usage:
11
+ python validate_loop.py [options]
12
+
13
+ Options:
14
+ --story, -s Story key to validate
15
+ --tier, -t Validation tier (1, 2, 3) or omit for all
16
+ --all, -a Run all tiers
17
+ --auto-fix Attempt automatic fixes
18
+ --json Output as JSON
19
+ --quiet, -q Minimal output
20
+ --check Exit with non-zero if any failures (for CI)
21
+
22
+ Examples:
23
+ python validate_loop.py --story 3-5 --tier 3
24
+ python validate_loop.py --all --json
25
+ python validate_loop.py --tier 3 --auto-fix --check
26
+ """
27
+
28
+ import argparse
29
+ import json
30
+ import sys
31
+ from pathlib import Path
32
+
33
+ # Add lib directory
34
+ SCRIPT_DIR = Path(__file__).parent
35
+ sys.path.insert(0, str(SCRIPT_DIR / "lib"))
36
+
37
+ from validation_loop import (
38
+ INTER_PHASE_GATES,
39
+ POST_COMPLETION_GATES,
40
+ PREFLIGHT_GATES,
41
+ LoopContext,
42
+ ValidationLoop,
43
+ )
44
+
45
+
46
+ def parse_args():
47
+ """Parse command line arguments."""
48
+ parser = argparse.ArgumentParser(
49
+ description="Run validation loop checks",
50
+ formatter_class=argparse.RawDescriptionHelpFormatter,
51
+ epilog="""
52
+ Examples:
53
+ python validate_loop.py --story 3-5 --tier 3
54
+ python validate_loop.py --all --json
55
+ python validate_loop.py --tier 3 --auto-fix --check
56
+ """,
57
+ )
58
+
59
+ parser.add_argument("--story", "-s", default="validation-check", help="Story key to validate")
60
+ parser.add_argument(
61
+ "--tier",
62
+ "-t",
63
+ type=int,
64
+ choices=[1, 2, 3],
65
+ help="Validation tier (1=preflight, 2=inter-phase, 3=post-completion)",
66
+ )
67
+ parser.add_argument("--all", "-a", action="store_true", help="Run all tiers")
68
+ parser.add_argument("--auto-fix", action="store_true", help="Attempt automatic fixes")
69
+ parser.add_argument("--json", action="store_true", help="Output as JSON")
70
+ parser.add_argument("--quiet", "-q", action="store_true", help="Minimal output")
71
+ parser.add_argument(
72
+ "--check", action="store_true", help="Exit with non-zero if any failures (for CI)"
73
+ )
74
+
75
+ return parser.parse_args()
76
+
77
+
78
+ def run_tier(tier: int, story_key: str, auto_fix: bool, quiet: bool):
79
+ """Run a specific validation tier."""
80
+ if tier == 1:
81
+ gates = PREFLIGHT_GATES
82
+ tier_name = "Pre-flight"
83
+ elif tier == 2:
84
+ gates = INTER_PHASE_GATES
85
+ tier_name = "Inter-phase"
86
+ else:
87
+ gates = POST_COMPLETION_GATES
88
+ tier_name = "Post-completion"
89
+
90
+ if not quiet:
91
+ print(f"\n[VALIDATION] Running {tier_name} checks (Tier {tier})...")
92
+
93
+ loop = ValidationLoop(
94
+ gates=gates,
95
+ config={"auto_fix_enabled": auto_fix},
96
+ story_key=story_key,
97
+ )
98
+ context = LoopContext(story_key=story_key, phase=f"tier_{tier}")
99
+
100
+ if tier == 1:
101
+ report = loop.run_preflight(context)
102
+ elif tier == 2:
103
+ report = loop.run_inter_phase(context)
104
+ else:
105
+ report = loop.run_post_completion(context)
106
+
107
+ return report
108
+
109
+
110
+ def main():
111
+ args = parse_args()
112
+
113
+ reports = []
114
+ overall_passed = True
115
+
116
+ if args.all or args.tier is None:
117
+ # Run all tiers
118
+ for tier in [1, 2, 3]:
119
+ report = run_tier(tier, args.story, args.auto_fix, args.quiet)
120
+ reports.append(report)
121
+ if report.failed:
122
+ overall_passed = False
123
+ else:
124
+ # Run specific tier
125
+ report = run_tier(args.tier, args.story, args.auto_fix, args.quiet)
126
+ reports.append(report)
127
+ if report.failed:
128
+ overall_passed = False
129
+
130
+ # Output results
131
+ if args.json:
132
+ output = {
133
+ "story_key": args.story,
134
+ "overall_passed": overall_passed,
135
+ "reports": [r.to_dict() for r in reports],
136
+ }
137
+ print(json.dumps(output, indent=2))
138
+ elif not args.quiet:
139
+ print("\n" + "=" * 60)
140
+ print("VALIDATION SUMMARY")
141
+ print("=" * 60)
142
+
143
+ for report in reports:
144
+ print(f"\nTier {report.tier}: {report.overall_result.value.upper()}")
145
+ print(report.to_summary())
146
+
147
+ print("\n" + "=" * 60)
148
+ if overall_passed:
149
+ print("[PASS] All validation checks passed")
150
+ else:
151
+ print("[FAIL] Some validation checks failed")
152
+ print("=" * 60)
153
+
154
+ # Exit code for CI
155
+ if args.check:
156
+ sys.exit(0 if overall_passed else 1)
157
+
158
+ return 0 if overall_passed else 1
159
+
160
+
161
+ if __name__ == "__main__":
162
+ sys.exit(main())
@@ -24,6 +24,8 @@ from enum import Enum
24
24
  from pathlib import Path
25
25
  from typing import Optional
26
26
 
27
+ from lib.colors import Colors
28
+
27
29
 
28
30
  class CheckStatus(Enum):
29
31
  """Status of a validation check."""
@@ -46,36 +48,6 @@ class CheckResult:
46
48
  fix_command: Optional[str] = None
47
49
 
48
50
 
49
- class Colors:
50
- """ANSI color codes."""
51
-
52
- RESET = "\033[0m"
53
- RED = "\033[31m"
54
- GREEN = "\033[32m"
55
- YELLOW = "\033[33m"
56
- BLUE = "\033[34m"
57
- CYAN = "\033[36m"
58
- BOLD = "\033[1m"
59
- DIM = "\033[2m"
60
-
61
- @classmethod
62
- def disable(cls):
63
- """Disable colors (for non-TTY output)."""
64
- cls.RESET = ""
65
- cls.RED = ""
66
- cls.GREEN = ""
67
- cls.YELLOW = ""
68
- cls.BLUE = ""
69
- cls.CYAN = ""
70
- cls.BOLD = ""
71
- cls.DIM = ""
72
-
73
-
74
- # Detect if running in non-TTY
75
- if not sys.stdout.isatty():
76
- Colors.disable()
77
-
78
-
79
51
  # Project paths
80
52
  SCRIPT_DIR = Path(__file__).parent
81
53
  PROJECT_ROOT = SCRIPT_DIR.parent.parent