@pjmendonca/devflow 1.13.2 → 1.18.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 (224) hide show
  1. package/.claude/commands/agent.md +1 -1
  2. package/.claude/commands/bugfix.md +21 -0
  3. package/.claude/commands/checkpoint.md +0 -1
  4. package/.claude/commands/collab.md +0 -1
  5. package/.claude/commands/costs.md +88 -18
  6. package/.claude/commands/devflow.md +26 -0
  7. package/.claude/commands/handoff.md +0 -1
  8. package/.claude/commands/init.md +287 -0
  9. package/.claude/commands/memory.md +0 -1
  10. package/.claude/commands/pair.md +0 -1
  11. package/.claude/commands/review.md +27 -0
  12. package/.claude/commands/route.md +0 -1
  13. package/.claude/commands/swarm.md +0 -1
  14. package/.claude/commands/validate.md +55 -0
  15. package/.claude/hooks/session-notification.sh +44 -0
  16. package/.claude/hooks/session-startup.sh +427 -0
  17. package/.claude/hooks/session-stop.sh +38 -0
  18. package/.claude/hooks/session_tracker.py +272 -0
  19. package/.claude/settings.json +38 -0
  20. package/.claude/skills/costs/SKILL.md +156 -0
  21. package/.claude/skills/validate/SKILL.md +101 -0
  22. package/CHANGELOG.md +243 -0
  23. package/README.md +207 -10
  24. package/bin/devflow-install.js +2 -1
  25. package/bin/devflow.js +4 -0
  26. package/lib/constants.js +0 -1
  27. package/lib/exec-python.js +1 -1
  28. package/package.json +1 -1
  29. package/tooling/.automation/.checkpoint_lock +1 -0
  30. package/tooling/.automation/agents/architect.md +19 -0
  31. package/tooling/.automation/agents/ba.md +19 -0
  32. package/tooling/.automation/agents/maintainer.md +19 -0
  33. package/tooling/.automation/agents/pm.md +19 -0
  34. package/tooling/.automation/agents/reviewer.md +1 -1
  35. package/tooling/.automation/agents/writer.md +19 -0
  36. package/tooling/.automation/benchmarks/benchmark_20251230_100119.json +314 -0
  37. package/tooling/.automation/benchmarks/benchmark_20251230_100216.json +314 -0
  38. package/tooling/.automation/costs/config.json +31 -0
  39. package/tooling/.automation/costs/sessions/2025-12-29_20251229_164128.json +22 -0
  40. package/tooling/.automation/memory/knowledge/kg_integration-test.json +707 -1
  41. package/tooling/.automation/memory/knowledge/kg_test-story.json +3273 -2
  42. package/tooling/.automation/memory/shared/shared_integration-test.json +181 -1
  43. package/tooling/.automation/memory/shared/shared_test-story.json +721 -1
  44. package/tooling/.automation/memory/shared/shared_test.json +1254 -0
  45. package/tooling/.automation/memory/shared/shared_validation-check.json +227 -0
  46. package/tooling/.automation/overrides/templates/architect/cloud-native.yaml +5 -5
  47. package/tooling/.automation/overrides/templates/architect/enterprise-architect.yaml +23 -5
  48. package/tooling/.automation/overrides/templates/architect/pragmatic-minimalist.yaml +24 -6
  49. package/tooling/.automation/overrides/templates/ba/agile-storyteller.yaml +4 -4
  50. package/tooling/.automation/overrides/templates/ba/domain-expert.yaml +4 -4
  51. package/tooling/.automation/overrides/templates/ba/requirements-engineer.yaml +4 -4
  52. package/tooling/.automation/overrides/templates/dev/performance-engineer.yaml +18 -0
  53. package/tooling/.automation/overrides/templates/dev/rapid-prototyper.yaml +19 -1
  54. package/tooling/.automation/overrides/templates/dev/security-focused.yaml +18 -0
  55. package/tooling/.automation/overrides/templates/dev/user-advocate.yaml +54 -0
  56. package/tooling/.automation/overrides/templates/maintainer/devops-maintainer.yaml +4 -4
  57. package/tooling/.automation/overrides/templates/maintainer/legacy-steward.yaml +4 -4
  58. package/tooling/.automation/overrides/templates/maintainer/oss-maintainer.yaml +4 -4
  59. package/tooling/.automation/overrides/templates/maintainer/reliability-engineer.yaml +55 -0
  60. package/tooling/.automation/overrides/templates/pm/agile-pm.yaml +4 -4
  61. package/tooling/.automation/overrides/templates/pm/hybrid-delivery.yaml +3 -3
  62. package/tooling/.automation/overrides/templates/pm/traditional-pm.yaml +4 -4
  63. package/tooling/.automation/overrides/templates/reviewer/quick-sanity.yaml +18 -0
  64. package/tooling/.automation/overrides/templates/reviewer/thorough-critic.yaml +18 -0
  65. package/tooling/.automation/overrides/templates/sm/agile-coach.yaml +2 -2
  66. package/tooling/.automation/overrides/templates/sm/startup-pm.yaml +3 -3
  67. package/tooling/.automation/overrides/templates/writer/api-documentarian.yaml +5 -5
  68. package/tooling/.automation/overrides/templates/writer/docs-as-code.yaml +4 -4
  69. package/tooling/.automation/overrides/templates/writer/user-guide-author.yaml +5 -5
  70. package/tooling/.automation/validation/history/2025-12-29_val_002a28c1.json +32 -0
  71. package/tooling/.automation/validation/history/2025-12-29_val_01273bb1.json +32 -0
  72. package/tooling/.automation/validation/history/2025-12-29_val_03369914.json +41 -0
  73. package/tooling/.automation/validation/history/2025-12-29_val_07a449ba.json +32 -0
  74. package/tooling/.automation/validation/history/2025-12-29_val_0df1f0a2.json +41 -0
  75. package/tooling/.automation/validation/history/2025-12-29_val_10ff3d34.json +41 -0
  76. package/tooling/.automation/validation/history/2025-12-29_val_110771d7.json +32 -0
  77. package/tooling/.automation/validation/history/2025-12-29_val_13f3a7f9.json +32 -0
  78. package/tooling/.automation/validation/history/2025-12-29_val_17ba9d21.json +41 -0
  79. package/tooling/.automation/validation/history/2025-12-29_val_22247089.json +32 -0
  80. package/tooling/.automation/validation/history/2025-12-29_val_227ea6a4.json +32 -0
  81. package/tooling/.automation/validation/history/2025-12-29_val_2335d5ae.json +32 -0
  82. package/tooling/.automation/validation/history/2025-12-29_val_246824bb.json +41 -0
  83. package/tooling/.automation/validation/history/2025-12-29_val_28b4b9cd.json +32 -0
  84. package/tooling/.automation/validation/history/2025-12-29_val_2abd12cc.json +32 -0
  85. package/tooling/.automation/validation/history/2025-12-29_val_2c801b2f.json +59 -0
  86. package/tooling/.automation/validation/history/2025-12-29_val_2c8cfa8e.json +32 -0
  87. package/tooling/.automation/validation/history/2025-12-29_val_2ce76eb0.json +32 -0
  88. package/tooling/.automation/validation/history/2025-12-29_val_30351948.json +41 -0
  89. package/tooling/.automation/validation/history/2025-12-29_val_30eb7229.json +41 -0
  90. package/tooling/.automation/validation/history/2025-12-29_val_34df0e77.json +41 -0
  91. package/tooling/.automation/validation/history/2025-12-29_val_376e4d6a.json +32 -0
  92. package/tooling/.automation/validation/history/2025-12-29_val_3a4e8a1a.json +59 -0
  93. package/tooling/.automation/validation/history/2025-12-29_val_3b77a628.json +32 -0
  94. package/tooling/.automation/validation/history/2025-12-29_val_3ea4e1cf.json +59 -0
  95. package/tooling/.automation/validation/history/2025-12-29_val_44aacdb4.json +59 -0
  96. package/tooling/.automation/validation/history/2025-12-29_val_457ddfa8.json +32 -0
  97. package/tooling/.automation/validation/history/2025-12-29_val_45af6238.json +41 -0
  98. package/tooling/.automation/validation/history/2025-12-29_val_4735dba1.json +41 -0
  99. package/tooling/.automation/validation/history/2025-12-29_val_486b203c.json +41 -0
  100. package/tooling/.automation/validation/history/2025-12-29_val_49dc56cd.json +59 -0
  101. package/tooling/.automation/validation/history/2025-12-29_val_4d863d6d.json +32 -0
  102. package/tooling/.automation/validation/history/2025-12-29_val_5149a808.json +59 -0
  103. package/tooling/.automation/validation/history/2025-12-29_val_52e0bb43.json +32 -0
  104. package/tooling/.automation/validation/history/2025-12-29_val_585d6319.json +59 -0
  105. package/tooling/.automation/validation/history/2025-12-29_val_5b2d859a.json +32 -0
  106. package/tooling/.automation/validation/history/2025-12-29_val_635a7081.json +41 -0
  107. package/tooling/.automation/validation/history/2025-12-29_val_64df4905.json +32 -0
  108. package/tooling/.automation/validation/history/2025-12-29_val_70634cee.json +41 -0
  109. package/tooling/.automation/validation/history/2025-12-29_val_714553f9.json +32 -0
  110. package/tooling/.automation/validation/history/2025-12-29_val_7f7bfdbf.json +41 -0
  111. package/tooling/.automation/validation/history/2025-12-29_val_7faad91d.json +32 -0
  112. package/tooling/.automation/validation/history/2025-12-29_val_81821f8f.json +41 -0
  113. package/tooling/.automation/validation/history/2025-12-29_val_8249f3c9.json +32 -0
  114. package/tooling/.automation/validation/history/2025-12-29_val_8422b50f.json +41 -0
  115. package/tooling/.automation/validation/history/2025-12-29_val_8446c134.json +32 -0
  116. package/tooling/.automation/validation/history/2025-12-29_val_879f4e26.json +59 -0
  117. package/tooling/.automation/validation/history/2025-12-29_val_8b6d5bd7.json +32 -0
  118. package/tooling/.automation/validation/history/2025-12-29_val_8c5cd787.json +32 -0
  119. package/tooling/.automation/validation/history/2025-12-29_val_91d20bc7.json +32 -0
  120. package/tooling/.automation/validation/history/2025-12-29_val_958a12b7.json +41 -0
  121. package/tooling/.automation/validation/history/2025-12-29_val_95d91108.json +41 -0
  122. package/tooling/.automation/validation/history/2025-12-29_val_980dbb74.json +32 -0
  123. package/tooling/.automation/validation/history/2025-12-29_val_9e40c79b.json +32 -0
  124. package/tooling/.automation/validation/history/2025-12-29_val_9f499b7c.json +32 -0
  125. package/tooling/.automation/validation/history/2025-12-29_val_9f7c3b57.json +32 -0
  126. package/tooling/.automation/validation/history/2025-12-29_val_a30d5bd4.json +32 -0
  127. package/tooling/.automation/validation/history/2025-12-29_val_a6eb09c7.json +32 -0
  128. package/tooling/.automation/validation/history/2025-12-29_val_a86f7b83.json +41 -0
  129. package/tooling/.automation/validation/history/2025-12-29_val_ad5347e1.json +41 -0
  130. package/tooling/.automation/validation/history/2025-12-29_val_b0a5a993.json +32 -0
  131. package/tooling/.automation/validation/history/2025-12-29_val_bcb0192e.json +32 -0
  132. package/tooling/.automation/validation/history/2025-12-29_val_bf3c9aaa.json +32 -0
  133. package/tooling/.automation/validation/history/2025-12-29_val_c461ff88.json +32 -0
  134. package/tooling/.automation/validation/history/2025-12-29_val_c4f4e258.json +41 -0
  135. package/tooling/.automation/validation/history/2025-12-29_val_c7f0fa6d.json +41 -0
  136. package/tooling/.automation/validation/history/2025-12-29_val_c911b0e6.json +32 -0
  137. package/tooling/.automation/validation/history/2025-12-29_val_cc581964.json +32 -0
  138. package/tooling/.automation/validation/history/2025-12-29_val_cdd5a33b.json +32 -0
  139. package/tooling/.automation/validation/history/2025-12-29_val_cfd42495.json +32 -0
  140. package/tooling/.automation/validation/history/2025-12-29_val_d1c7a4ee.json +41 -0
  141. package/tooling/.automation/validation/history/2025-12-29_val_d2280d0e.json +32 -0
  142. package/tooling/.automation/validation/history/2025-12-29_val_d2a6ff69.json +32 -0
  143. package/tooling/.automation/validation/history/2025-12-29_val_d8c53ab2.json +59 -0
  144. package/tooling/.automation/validation/history/2025-12-29_val_d9c1247a.json +41 -0
  145. package/tooling/.automation/validation/history/2025-12-29_val_d9d58569.json +32 -0
  146. package/tooling/.automation/validation/history/2025-12-29_val_dabb4fd9.json +32 -0
  147. package/tooling/.automation/validation/history/2025-12-29_val_dd8fe359.json +32 -0
  148. package/tooling/.automation/validation/history/2025-12-29_val_decdffc9.json +32 -0
  149. package/tooling/.automation/validation/history/2025-12-29_val_e3a95476.json +59 -0
  150. package/tooling/.automation/validation/history/2025-12-29_val_e776dfca.json +32 -0
  151. package/tooling/.automation/validation/history/2025-12-29_val_ea70969f.json +59 -0
  152. package/tooling/.automation/validation/history/2025-12-29_val_ef41ea95.json +32 -0
  153. package/tooling/.automation/validation/history/2025-12-29_val_f384f9b1.json +32 -0
  154. package/tooling/.automation/validation/history/2025-12-29_val_f8adc38c.json +41 -0
  155. package/tooling/.automation/validation/history/2025-12-29_val_fa40b69e.json +32 -0
  156. package/tooling/.automation/validation/history/2025-12-29_val_fc538d54.json +41 -0
  157. package/tooling/.automation/validation/history/2025-12-29_val_fe814665.json +32 -0
  158. package/tooling/.automation/validation/history/2025-12-29_val_ffea4b12.json +32 -0
  159. package/tooling/.automation/validation/history/2025-12-30_val_02d001e5.json +59 -0
  160. package/tooling/.automation/validation/history/2025-12-30_val_0b8966dc.json +32 -0
  161. package/tooling/.automation/validation/history/2025-12-30_val_15455fbf.json +59 -0
  162. package/tooling/.automation/validation/history/2025-12-30_val_157e34b9.json +32 -0
  163. package/tooling/.automation/validation/history/2025-12-30_val_28d1d933.json +32 -0
  164. package/tooling/.automation/validation/history/2025-12-30_val_3442a52c.json +32 -0
  165. package/tooling/.automation/validation/history/2025-12-30_val_37f1ce1e.json +32 -0
  166. package/tooling/.automation/validation/history/2025-12-30_val_4f1d8a93.json +32 -0
  167. package/tooling/.automation/validation/history/2025-12-30_val_56ff1de3.json +32 -0
  168. package/tooling/.automation/validation/history/2025-12-30_val_664fd4e2.json +41 -0
  169. package/tooling/.automation/validation/history/2025-12-30_val_66afb0a7.json +32 -0
  170. package/tooling/.automation/validation/history/2025-12-30_val_7634663c.json +41 -0
  171. package/tooling/.automation/validation/history/2025-12-30_val_8ea830c3.json +41 -0
  172. package/tooling/.automation/validation/history/2025-12-30_val_998957c2.json +32 -0
  173. package/tooling/.automation/validation/history/2025-12-30_val_a52177db.json +32 -0
  174. package/tooling/.automation/validation/history/2025-12-30_val_a5b65a63.json +32 -0
  175. package/tooling/.automation/validation/history/2025-12-30_val_ae391d0e.json +32 -0
  176. package/tooling/.automation/validation/history/2025-12-30_val_c7895339.json +41 -0
  177. package/tooling/.automation/validation/history/2025-12-30_val_ca416593.json +41 -0
  178. package/tooling/.automation/validation/history/2025-12-30_val_cee19422.json +32 -0
  179. package/tooling/.automation/validation/history/2025-12-30_val_ddd4f4e6.json +32 -0
  180. package/tooling/.automation/validation/history/2025-12-30_val_f2e1394b.json +32 -0
  181. package/tooling/.automation/validation/history/2025-12-30_val_f4a7fa06.json +41 -0
  182. package/tooling/.automation/validation/history/2025-12-30_val_ffea3369.json +32 -0
  183. package/tooling/.automation/validation-config.yaml +103 -0
  184. package/tooling/completions/DevflowCompletion.ps1 +21 -21
  185. package/tooling/completions/_run-story +3 -3
  186. package/tooling/completions/run-story-completion.bash +8 -8
  187. package/tooling/docs/DOC-STANDARD.md +14 -14
  188. package/tooling/docs/templates/migration-spec.md +4 -4
  189. package/tooling/scripts/context_checkpoint.py +5 -15
  190. package/tooling/scripts/cost_dashboard.py +610 -13
  191. package/tooling/scripts/create-persona.py +1 -12
  192. package/tooling/scripts/create-persona.sh +44 -44
  193. package/tooling/scripts/lib/__init__.py +12 -1
  194. package/tooling/scripts/lib/agent_handoff.py +11 -2
  195. package/tooling/scripts/lib/agent_router.py +31 -10
  196. package/tooling/scripts/lib/colors.py +106 -0
  197. package/tooling/scripts/lib/context_monitor.py +766 -0
  198. package/tooling/scripts/lib/cost_config.py +229 -10
  199. package/tooling/scripts/lib/cost_display.py +20 -45
  200. package/tooling/scripts/lib/cost_tracker.py +462 -15
  201. package/tooling/scripts/lib/currency_converter.py +28 -5
  202. package/tooling/scripts/lib/pair_programming.py +102 -3
  203. package/tooling/scripts/lib/personality_system.py +949 -0
  204. package/tooling/scripts/lib/platform.py +55 -0
  205. package/tooling/scripts/lib/shared_memory.py +9 -3
  206. package/tooling/scripts/lib/swarm_orchestrator.py +514 -75
  207. package/tooling/scripts/lib/validation_loop.py +1014 -0
  208. package/tooling/scripts/memory_summarize.py +9 -2
  209. package/tooling/scripts/new-doc.py +2 -9
  210. package/tooling/scripts/personalize_agent.py +1 -12
  211. package/tooling/scripts/rollback-migration.sh +60 -60
  212. package/tooling/scripts/run-collab.ps1 +16 -16
  213. package/tooling/scripts/run-collab.py +88 -53
  214. package/tooling/scripts/run-collab.sh +4 -4
  215. package/tooling/scripts/run-story.py +278 -20
  216. package/tooling/scripts/run-story.sh +3 -3
  217. package/tooling/scripts/setup-checkpoint-service.py +2 -9
  218. package/tooling/scripts/tech-debt-tracker.py +1 -12
  219. package/tooling/scripts/test_adversarial_swarm.py +452 -0
  220. package/tooling/scripts/validate-overrides.py +1 -10
  221. package/tooling/scripts/validate-overrides.sh +40 -40
  222. package/tooling/scripts/validate_loop.py +162 -0
  223. package/tooling/scripts/validate_setup.py +2 -30
  224. package/.claude/skills/init/SKILL.md +0 -496
@@ -19,18 +19,7 @@ import sys
19
19
  from dataclasses import dataclass, field
20
20
  from pathlib import Path
21
21
 
22
-
23
- # Colors for terminal output
24
- class Colors:
25
- RED = "\033[0;31m"
26
- GREEN = "\033[0;32m"
27
- YELLOW = "\033[1;33m"
28
- BLUE = "\033[0;34m"
29
- CYAN = "\033[0;36m"
30
- MAGENTA = "\033[0;35m"
31
- BOLD = "\033[1m"
32
- NC = "\033[0m"
33
-
22
+ from lib.colors import Colors
34
23
 
35
24
  # Persona templates
36
25
  PERSONA_TEMPLATES = {
@@ -44,15 +44,15 @@ prompt() {
44
44
  local message="$1"
45
45
  local default="$2"
46
46
  local result
47
-
47
+
48
48
  if [[ -n "$default" ]]; then
49
49
  echo -n -e "${BLUE}${message}${NC} [${default}]: "
50
50
  else
51
51
  echo -n -e "${BLUE}${message}${NC}: "
52
52
  fi
53
-
53
+
54
54
  read result
55
-
55
+
56
56
  if [[ -z "$result" && -n "$default" ]]; then
57
57
  echo "$default"
58
58
  else
@@ -65,15 +65,15 @@ prompt_list() {
65
65
  local min_items="${2:-0}"
66
66
  local items=()
67
67
  local count=0
68
-
68
+
69
69
  echo -e "${BLUE}${message}${NC}"
70
70
  echo " (Enter items one per line, empty line to finish)"
71
-
71
+
72
72
  while true; do
73
73
  ((count++))
74
74
  echo -n " $count. "
75
75
  read item
76
-
76
+
77
77
  if [[ -z "$item" ]]; then
78
78
  if [[ ${#items[@]} -ge $min_items ]]; then
79
79
  break
@@ -83,10 +83,10 @@ prompt_list() {
83
83
  continue
84
84
  fi
85
85
  fi
86
-
86
+
87
87
  items+=("$item")
88
88
  done
89
-
89
+
90
90
  printf '%s\n' "${items[@]}"
91
91
  }
92
92
 
@@ -96,7 +96,7 @@ prompt_list() {
96
96
 
97
97
  get_template() {
98
98
  local template_name="$1"
99
-
99
+
100
100
  case "$template_name" in
101
101
  developer|dev)
102
102
  echo "developer|Software Developer|Writing clean, maintainable code|sonnet"
@@ -136,9 +136,9 @@ generate_agent_file() {
136
136
  local model="$4"
137
137
  shift 4
138
138
  local responsibilities=("${@}")
139
-
139
+
140
140
  local file="$AGENTS_DIR/${name}.md"
141
-
141
+
142
142
  cat > "$file" << EOF
143
143
  # ${role} Agent
144
144
 
@@ -147,13 +147,13 @@ You are a ${role}. ${focus}
147
147
  ## Responsibilities
148
148
 
149
149
  EOF
150
-
150
+
151
151
  local count=0
152
152
  for resp in "${responsibilities[@]}"; do
153
153
  ((count++))
154
154
  echo "$count. $resp" >> "$file"
155
155
  done
156
-
156
+
157
157
  cat >> "$file" << 'EOF'
158
158
 
159
159
  ## Principles
@@ -185,25 +185,25 @@ If you sense context is running low, output a warning:
185
185
  ```
186
186
 
187
187
  EOF
188
-
188
+
189
189
  echo "## Model" >> "$file"
190
190
  echo "" >> "$file"
191
191
  echo "Recommended model: \`${model}\`" >> "$file"
192
192
  echo "" >> "$file"
193
-
193
+
194
194
  echo "$file"
195
195
  }
196
196
 
197
197
  generate_override_file() {
198
198
  local name="$1"
199
-
199
+
200
200
  local file="$OVERRIDES_DIR/${name}.override.yaml"
201
-
201
+
202
202
  # Don't overwrite existing
203
203
  if [[ -f "$file" ]]; then
204
204
  return
205
205
  fi
206
-
206
+
207
207
  cat > "$file" << EOF
208
208
  # ${name^^} Agent Override
209
209
  # Customize this agent's behavior without modifying the core agent file
@@ -228,7 +228,7 @@ critical_actions:
228
228
  # max_budget_usd: 10.00
229
229
 
230
230
  EOF
231
-
231
+
232
232
  echo "$file"
233
233
  }
234
234
 
@@ -239,50 +239,50 @@ EOF
239
239
  list_personas() {
240
240
  echo -e "${BOLD}Available Agent Personas:${NC}"
241
241
  echo ""
242
-
242
+
243
243
  if [[ ! -d "$AGENTS_DIR" ]]; then
244
244
  echo -e " ${YELLOW}No agents directory found.${NC}"
245
245
  return
246
246
  fi
247
-
247
+
248
248
  printf " %-15s │ %-25s │ Override\n" "NAME" "ROLE"
249
249
  printf " %s\n" "$(printf '─%.0s' {1..50})"
250
-
250
+
251
251
  for agent_file in "$AGENTS_DIR"/*.md; do
252
252
  if [[ -f "$agent_file" ]]; then
253
253
  local name=$(basename "$agent_file" .md)
254
254
  local role=$(head -1 "$agent_file" | sed 's/# //' | sed 's/ Agent$//')
255
-
255
+
256
256
  local has_override=" "
257
257
  if [[ -f "$OVERRIDES_DIR/${name}.override.yaml" ]]; then
258
258
  has_override="[OK]"
259
259
  fi
260
-
260
+
261
261
  printf " ${GREEN}%-15s${NC} │ %-25s │ %s\n" "$name" "$role" "$has_override"
262
262
  fi
263
263
  done
264
-
264
+
265
265
  echo ""
266
266
  }
267
267
 
268
268
  create_from_template() {
269
269
  local template_name="$1"
270
270
  local persona_name="$2"
271
-
271
+
272
272
  local template=$(get_template "$template_name")
273
-
273
+
274
274
  if [[ -z "$template" ]]; then
275
275
  echo -e "${RED}Unknown template: $template_name${NC}"
276
276
  echo "Available templates: developer, reviewer, architect, tester, security, devops, documentation"
277
277
  exit 1
278
278
  fi
279
-
279
+
280
280
  # Parse template
281
281
  IFS='|' read -r tpl_name role focus model <<< "$template"
282
-
282
+
283
283
  # Use provided name or template name
284
284
  local name="${persona_name:-$tpl_name}"
285
-
285
+
286
286
  # Default responsibilities
287
287
  local responsibilities=(
288
288
  "Complete assigned tasks efficiently"
@@ -290,12 +290,12 @@ create_from_template() {
290
290
  "Document work appropriately"
291
291
  "Communicate progress and blockers"
292
292
  )
293
-
293
+
294
294
  mkdir -p "$AGENTS_DIR" "$OVERRIDES_DIR"
295
-
295
+
296
296
  local agent_file=$(generate_agent_file "$name" "$role" "$focus" "$model" "${responsibilities[@]}")
297
297
  local override_file=$(generate_override_file "$name")
298
-
298
+
299
299
  echo -e "${GREEN}[OK] Persona created from template!${NC}"
300
300
  echo ""
301
301
  echo " Agent file: $agent_file"
@@ -306,16 +306,16 @@ create_from_template() {
306
306
  interactive_create() {
307
307
  echo -e "${BOLD}Let's create your custom agent persona!${NC}"
308
308
  echo ""
309
-
309
+
310
310
  # Get name
311
311
  local name=$(prompt "Persona name (e.g., 'qa', 'frontend-dev')")
312
312
  name=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
313
-
313
+
314
314
  if [[ -z "$name" ]]; then
315
315
  echo -e "${RED}Name is required.${NC}"
316
316
  exit 1
317
317
  fi
318
-
318
+
319
319
  # Check if exists
320
320
  if [[ -f "$AGENTS_DIR/${name}.md" ]]; then
321
321
  echo -e "${YELLOW}Persona '$name' already exists.${NC}"
@@ -324,25 +324,25 @@ interactive_create() {
324
324
  exit 0
325
325
  fi
326
326
  fi
327
-
327
+
328
328
  # Get details
329
329
  echo ""
330
330
  local role=$(prompt "Role (e.g., 'Senior QA Engineer')")
331
331
  local focus=$(prompt "Focus (one-line description)")
332
-
332
+
333
333
  echo ""
334
334
  echo "Select model:"
335
335
  echo " 1. sonnet (default - balanced)"
336
336
  echo " 2. opus (complex tasks)"
337
337
  echo " 3. haiku (quick tasks)"
338
338
  local model_choice=$(prompt "Choice" "1")
339
-
339
+
340
340
  local model="sonnet"
341
341
  case "$model_choice" in
342
342
  2|opus) model="opus" ;;
343
343
  3|haiku) model="haiku" ;;
344
344
  esac
345
-
345
+
346
346
  echo ""
347
347
  echo "Enter responsibilities (what this agent does):"
348
348
  local responsibilities=()
@@ -361,13 +361,13 @@ interactive_create() {
361
361
  fi
362
362
  responsibilities+=("$resp")
363
363
  done
364
-
364
+
365
365
  # Create files
366
366
  mkdir -p "$AGENTS_DIR" "$OVERRIDES_DIR"
367
-
367
+
368
368
  local agent_file=$(generate_agent_file "$name" "$role" "$focus" "$model" "${responsibilities[@]}")
369
369
  local override_file=$(generate_override_file "$name")
370
-
370
+
371
371
  echo ""
372
372
  echo -e "${GREEN}[OK] Persona created successfully!${NC}"
373
373
  echo ""
@@ -405,7 +405,7 @@ print_usage() {
405
405
 
406
406
  main() {
407
407
  print_header
408
-
408
+
409
409
  case "$1" in
410
410
  --list|-l)
411
411
  list_personas
@@ -2,34 +2,45 @@
2
2
  Devflow Library - Core modules for the Devflow automation system.
3
3
 
4
4
  This package provides:
5
+ - colors: Shared terminal color codes
6
+ - platform: Cross-platform detection utilities
5
7
  - cost_tracker: Token usage and cost tracking
6
8
  - cost_display: Terminal-based cost monitoring display
7
9
  - cost_config: Configuration management for costs
8
10
  - currency_converter: Multi-currency support
11
+ - context_monitor: Real-time context window tracking
9
12
  - errors: Enhanced error handling
10
13
  - agent_router: Dynamic agent selection
11
14
  - agent_handoff: Structured agent transitions
12
15
  - shared_memory: Cross-agent knowledge sharing
13
16
  - swarm_orchestrator: Multi-agent collaboration
14
17
  - pair_programming: DEV + REVIEWER collaboration
18
+ - validation_loop: Three-tier validation framework
15
19
 
16
20
  Usage:
17
21
  from lib.cost_tracker import CostTracker
22
+ from lib.context_monitor import ContextMonitor, StatusLine, get_status_manager
18
23
  from lib.agent_router import AgentRouter
24
+ from lib.colors import Colors
25
+ from lib.platform import get_platform, IS_WINDOWS
19
26
  """
20
27
 
21
- __version__ = "1.13.2"
28
+ __version__ = "1.18.0"
22
29
 
23
30
  # Lazy imports to avoid circular dependencies
24
31
  __all__ = [
32
+ "colors",
33
+ "platform",
25
34
  "cost_tracker",
26
35
  "cost_display",
27
36
  "cost_config",
28
37
  "currency_converter",
38
+ "context_monitor",
29
39
  "errors",
30
40
  "agent_router",
31
41
  "agent_handoff",
32
42
  "shared_memory",
33
43
  "swarm_orchestrator",
34
44
  "pair_programming",
45
+ "validation_loop",
35
46
  ]
@@ -226,7 +226,12 @@ class HandoffGenerator:
226
226
  )
227
227
 
228
228
  return changes
229
- except Exception:
229
+ except subprocess.SubprocessError as e:
230
+ # Git command failed - likely not a git repo or git not installed
231
+ print(f"Warning: Could not get git changes: {e}")
232
+ return []
233
+ except OSError as e:
234
+ print(f"Warning: Error accessing git: {e}")
230
235
  return []
231
236
 
232
237
  def get_staged_changes(self) -> list[FileChange]:
@@ -255,7 +260,11 @@ class HandoffGenerator:
255
260
  )
256
261
 
257
262
  return changes
258
- except Exception:
263
+ except subprocess.SubprocessError as e:
264
+ print(f"Warning: Could not get staged changes: {e}")
265
+ return []
266
+ except OSError as e:
267
+ print(f"Warning: Error accessing git for staged changes: {e}")
259
268
  return []
260
269
 
261
270
  def extract_decisions_from_memory(self, agent: str) -> list[str]:
@@ -29,6 +29,14 @@ from enum import Enum
29
29
  from pathlib import Path
30
30
  from typing import Optional
31
31
 
32
+ # Configuration constants (can be overridden via environment or config)
33
+ CONFIDENCE_BASE = 0.3 # Base confidence score
34
+ CONFIDENCE_PATTERN_WEIGHT = 0.1 # Weight per detected pattern
35
+ CONFIDENCE_FILE_CONTEXT_WEIGHT = 0.1 # Weight per file context match
36
+ COMPLEXITY_SIMPLE_THRESHOLD = 2 # Complexity <= this is "simple"
37
+ COST_OPT_COMPLEXITY_THRESHOLD = 3 # Max complexity for cost optimization
38
+ MAX_ALTERNATIVES = 3 # Maximum alternative agents to suggest
39
+
32
40
 
33
41
  class TaskType(Enum):
34
42
  """Types of development tasks."""
@@ -242,6 +250,12 @@ TASK_PATTERNS = {
242
250
  ],
243
251
  }
244
252
 
253
+ # Pre-compile regex patterns for performance
254
+ COMPILED_TASK_PATTERNS: dict[TaskType, list[re.Pattern]] = {
255
+ task_type: [re.compile(pattern, re.IGNORECASE) for pattern in patterns]
256
+ for task_type, patterns in TASK_PATTERNS.items()
257
+ }
258
+
245
259
  # File extension to specialty mapping
246
260
  FILE_SPECIALTIES = {
247
261
  # Security-sensitive files
@@ -337,14 +351,14 @@ class AgentRouter:
337
351
  """
338
352
  description_lower = description.lower()
339
353
 
340
- # Detect task type from patterns
354
+ # Detect task type from pre-compiled patterns (faster than re.findall each time)
341
355
  type_scores: dict[TaskType, int] = {}
342
356
  detected_patterns: list[str] = []
343
357
 
344
- for task_type, patterns in TASK_PATTERNS.items():
358
+ for task_type, compiled_patterns in COMPILED_TASK_PATTERNS.items():
345
359
  score = 0
346
- for pattern in patterns:
347
- matches = re.findall(pattern, description_lower)
360
+ for pattern in compiled_patterns:
361
+ matches = pattern.findall(description_lower)
348
362
  if matches:
349
363
  score += len(matches)
350
364
  detected_patterns.extend(matches)
@@ -368,8 +382,13 @@ class AgentRouter:
368
382
  # Estimate complexity
369
383
  complexity = self._estimate_complexity(description, files)
370
384
 
371
- # Calculate confidence
372
- confidence = min(1.0, 0.3 + (0.1 * len(detected_patterns)) + (0.1 * len(file_contexts)))
385
+ # Calculate confidence using configurable weights
386
+ confidence = min(
387
+ 1.0,
388
+ CONFIDENCE_BASE
389
+ + (CONFIDENCE_PATTERN_WEIGHT * len(detected_patterns))
390
+ + (CONFIDENCE_FILE_CONTEXT_WEIGHT * len(file_contexts)),
391
+ )
373
392
 
374
393
  return TaskAnalysis(
375
394
  task_type=task_type,
@@ -562,7 +581,9 @@ class AgentRouter:
562
581
  }
563
582
 
564
583
  # Determine complexity level
565
- complexity_level = "simple" if complexity.value <= 2 else "complex"
584
+ complexity_level = (
585
+ "simple" if complexity.value <= COMPLEXITY_SIMPLE_THRESHOLD else "complex"
586
+ )
566
587
 
567
588
  # Get routing
568
589
  rule = routing_rules.get(task_type, {}).get(complexity_level)
@@ -572,11 +593,11 @@ class AgentRouter:
572
593
  agents, workflow, reasoning = rule
573
594
 
574
595
  # Cost optimization
575
- if prefer_cost and complexity.value <= 3:
596
+ if prefer_cost and complexity.value <= COST_OPT_COMPLEXITY_THRESHOLD:
576
597
  # Replace Opus agents with Sonnet equivalents where possible
577
598
  cost_effective_agents = []
578
599
  for agent in agents:
579
- if agent == "REVIEWER" and complexity.value <= 2:
600
+ if agent == "REVIEWER" and complexity.value <= COMPLEXITY_SIMPLE_THRESHOLD:
580
601
  cost_effective_agents.append("SM") # SM can do simple reviews
581
602
  else:
582
603
  cost_effective_agents.append(agent)
@@ -601,7 +622,7 @@ class AgentRouter:
601
622
  if matches and agent.max_complexity >= analysis.complexity.value:
602
623
  alternatives.append(name)
603
624
 
604
- return alternatives[:3] # Top 3 alternatives
625
+ return alternatives[:MAX_ALTERNATIVES]
605
626
 
606
627
  def get_workflow_for_agents(self, agents: list[str]) -> str:
607
628
  """Determine the best workflow for a set of agents."""
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Shared Colors Module for Devflow.
4
+
5
+ Provides consistent ANSI color codes for terminal output across all scripts.
6
+
7
+ Usage:
8
+ from lib.colors import Colors
9
+
10
+ print(f"{Colors.GREEN}Success!{Colors.RESET}")
11
+ print(f"{Colors.BOLD_RED}Error!{Colors.RESET}")
12
+ """
13
+
14
+ import os
15
+ import sys
16
+
17
+
18
+ def _supports_color() -> bool:
19
+ """Check if the terminal supports color output."""
20
+ # Check for explicit NO_COLOR environment variable
21
+ if os.getenv("NO_COLOR"):
22
+ return False
23
+
24
+ # Check for explicit FORCE_COLOR
25
+ if os.getenv("FORCE_COLOR"):
26
+ return True
27
+
28
+ # Check if output is a TTY
29
+ if not hasattr(sys.stdout, "isatty") or not sys.stdout.isatty():
30
+ return False
31
+
32
+ # Windows-specific handling
33
+ if sys.platform == "win32":
34
+ try:
35
+ import ctypes
36
+
37
+ kernel32 = ctypes.windll.kernel32
38
+ # Enable ANSI escape sequences on Windows 10+
39
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
40
+ return True
41
+ except Exception:
42
+ return False
43
+
44
+ return True
45
+
46
+
47
+ class Colors:
48
+ """ANSI color codes for terminal output."""
49
+
50
+ _USE_COLORS = _supports_color()
51
+
52
+ # Reset
53
+ RESET = "\033[0m" if _USE_COLORS else ""
54
+ END = RESET # Alias for compatibility
55
+
56
+ # Regular colors
57
+ BLACK = "\033[30m" if _USE_COLORS else ""
58
+ RED = "\033[31m" if _USE_COLORS else ""
59
+ GREEN = "\033[32m" if _USE_COLORS else ""
60
+ YELLOW = "\033[33m" if _USE_COLORS else ""
61
+ BLUE = "\033[34m" if _USE_COLORS else ""
62
+ MAGENTA = "\033[35m" if _USE_COLORS else ""
63
+ CYAN = "\033[36m" if _USE_COLORS else ""
64
+ WHITE = "\033[37m" if _USE_COLORS else ""
65
+
66
+ # Bold colors
67
+ BOLD = "\033[1m" if _USE_COLORS else ""
68
+ BOLD_RED = "\033[1;31m" if _USE_COLORS else ""
69
+ BOLD_GREEN = "\033[1;32m" if _USE_COLORS else ""
70
+ BOLD_YELLOW = "\033[1;33m" if _USE_COLORS else ""
71
+ BOLD_BLUE = "\033[1;34m" if _USE_COLORS else ""
72
+ BOLD_MAGENTA = "\033[1;35m" if _USE_COLORS else ""
73
+ BOLD_CYAN = "\033[1;36m" if _USE_COLORS else ""
74
+ BOLD_WHITE = "\033[1;37m" if _USE_COLORS else ""
75
+
76
+ # Background colors
77
+ BG_RED = "\033[41m" if _USE_COLORS else ""
78
+ BG_GREEN = "\033[42m" if _USE_COLORS else ""
79
+ BG_YELLOW = "\033[43m" if _USE_COLORS else ""
80
+ BG_BLUE = "\033[44m" if _USE_COLORS else ""
81
+
82
+ # Styles
83
+ DIM = "\033[2m" if _USE_COLORS else ""
84
+ UNDERLINE = "\033[4m" if _USE_COLORS else ""
85
+
86
+ # Common aliases used across codebase
87
+ HEADER = BOLD_MAGENTA
88
+ OKBLUE = BLUE
89
+ OKCYAN = CYAN
90
+ OKGREEN = GREEN
91
+ WARNING = YELLOW
92
+ FAIL = RED
93
+ ENDC = RESET
94
+ NC = RESET # No Color alias
95
+
96
+ @staticmethod
97
+ def strip(text: str) -> str:
98
+ """Remove ANSI codes from text."""
99
+ import re
100
+
101
+ return re.sub(r"\033\[[0-9;]*m", "", text)
102
+
103
+ @classmethod
104
+ def enabled(cls) -> bool:
105
+ """Check if colors are enabled."""
106
+ return cls._USE_COLORS