devforgeai 1.0.4 → 1.0.6

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 (134) hide show
  1. package/CLAUDE.md +120 -0
  2. package/package.json +9 -1
  3. package/src/CLAUDE.md +699 -0
  4. package/src/claude/scripts/README.md +396 -0
  5. package/src/claude/scripts/audit-command-skill-overlap.sh +67 -0
  6. package/src/claude/scripts/check-hooks-fast.sh +70 -0
  7. package/src/claude/scripts/devforgeai-validate +6 -0
  8. package/src/claude/scripts/devforgeai_cli/README.md +531 -0
  9. package/src/claude/scripts/devforgeai_cli/__init__.py +12 -0
  10. package/src/claude/scripts/devforgeai_cli/cli.py +716 -0
  11. package/src/claude/scripts/devforgeai_cli/commands/__init__.py +1 -0
  12. package/src/claude/scripts/devforgeai_cli/commands/check_hooks.py +384 -0
  13. package/src/claude/scripts/devforgeai_cli/commands/invoke_hooks.py +149 -0
  14. package/src/claude/scripts/devforgeai_cli/commands/phase_commands.py +731 -0
  15. package/src/claude/scripts/devforgeai_cli/commands/validate_installation.py +412 -0
  16. package/src/claude/scripts/devforgeai_cli/context_extraction.py +426 -0
  17. package/src/claude/scripts/devforgeai_cli/feedback/AC_TO_TEST_MAPPING.md +636 -0
  18. package/src/claude/scripts/devforgeai_cli/feedback/DELIVERY_SUMMARY.txt +329 -0
  19. package/src/claude/scripts/devforgeai_cli/feedback/README_TEST_SPECS.md +486 -0
  20. package/src/claude/scripts/devforgeai_cli/feedback/TEST_IMPLEMENTATION_GUIDE.md +529 -0
  21. package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECIFICATIONS.md +2652 -0
  22. package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECS_INDEX.md +398 -0
  23. package/src/claude/scripts/devforgeai_cli/feedback/__init__.py +34 -0
  24. package/src/claude/scripts/devforgeai_cli/feedback/adaptive_questioning_engine.py +581 -0
  25. package/src/claude/scripts/devforgeai_cli/feedback/aggregation.py +179 -0
  26. package/src/claude/scripts/devforgeai_cli/feedback/commands.py +535 -0
  27. package/src/claude/scripts/devforgeai_cli/feedback/config_defaults.py +58 -0
  28. package/src/claude/scripts/devforgeai_cli/feedback/config_manager.py +423 -0
  29. package/src/claude/scripts/devforgeai_cli/feedback/config_models.py +192 -0
  30. package/src/claude/scripts/devforgeai_cli/feedback/config_schema.py +140 -0
  31. package/src/claude/scripts/devforgeai_cli/feedback/coverage.json +1 -0
  32. package/src/claude/scripts/devforgeai_cli/feedback/feature_flag.py +152 -0
  33. package/src/claude/scripts/devforgeai_cli/feedback/feedback_indexer.py +394 -0
  34. package/src/claude/scripts/devforgeai_cli/feedback/hot_reload.py +226 -0
  35. package/src/claude/scripts/devforgeai_cli/feedback/longitudinal.py +115 -0
  36. package/src/claude/scripts/devforgeai_cli/feedback/models.py +67 -0
  37. package/src/claude/scripts/devforgeai_cli/feedback/question_router.py +236 -0
  38. package/src/claude/scripts/devforgeai_cli/feedback/retrospective.py +233 -0
  39. package/src/claude/scripts/devforgeai_cli/feedback/skip_tracker.py +177 -0
  40. package/src/claude/scripts/devforgeai_cli/feedback/skip_tracking.py +221 -0
  41. package/src/claude/scripts/devforgeai_cli/feedback/template_engine.py +549 -0
  42. package/src/claude/scripts/devforgeai_cli/feedback/validation.py +163 -0
  43. package/src/claude/scripts/devforgeai_cli/headless/__init__.py +30 -0
  44. package/src/claude/scripts/devforgeai_cli/headless/answer_models.py +206 -0
  45. package/src/claude/scripts/devforgeai_cli/headless/answer_resolver.py +204 -0
  46. package/src/claude/scripts/devforgeai_cli/headless/exceptions.py +36 -0
  47. package/src/claude/scripts/devforgeai_cli/headless/pattern_matcher.py +156 -0
  48. package/src/claude/scripts/devforgeai_cli/hooks.py +313 -0
  49. package/src/claude/scripts/devforgeai_cli/metrics/__init__.py +46 -0
  50. package/src/claude/scripts/devforgeai_cli/metrics/command_metrics.py +142 -0
  51. package/src/claude/scripts/devforgeai_cli/metrics/failure_modes.py +152 -0
  52. package/src/claude/scripts/devforgeai_cli/metrics/story_segmentation.py +181 -0
  53. package/src/claude/scripts/devforgeai_cli/orchestrate_hooks.py +780 -0
  54. package/src/claude/scripts/devforgeai_cli/phase_state.py +1229 -0
  55. package/src/claude/scripts/devforgeai_cli/session/__init__.py +30 -0
  56. package/src/claude/scripts/devforgeai_cli/session/checkpoint.py +268 -0
  57. package/src/claude/scripts/devforgeai_cli/tests/__init__.py +1 -0
  58. package/src/claude/scripts/devforgeai_cli/tests/conftest.py +29 -0
  59. package/src/claude/scripts/devforgeai_cli/tests/feedback/TEST_EXECUTION_GUIDE.md +298 -0
  60. package/src/claude/scripts/devforgeai_cli/tests/feedback/__init__.py +3 -0
  61. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_adaptive_questioning_engine.py +2171 -0
  62. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_aggregation.py +476 -0
  63. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_defaults.py +133 -0
  64. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_manager.py +592 -0
  65. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_models.py +373 -0
  66. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_schema.py +130 -0
  67. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py +1355 -0
  68. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_edge_cases.py +308 -0
  69. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feature_flag.py +307 -0
  70. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feedback_indexer.py +384 -0
  71. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_hot_reload.py +580 -0
  72. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_integration.py +402 -0
  73. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_models.py +105 -0
  74. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_question_routing.py +262 -0
  75. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_retrospective.py +333 -0
  76. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracker.py +410 -0
  77. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking.py +159 -0
  78. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking_integration.py +1155 -0
  79. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_template_engine.py +1389 -0
  80. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_validation_comprehensive.py +210 -0
  81. package/src/claude/scripts/devforgeai_cli/tests/fixtures/autonomous-deferral-story.md +46 -0
  82. package/src/claude/scripts/devforgeai_cli/tests/fixtures/missing-impl-notes.md +31 -0
  83. package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-deferral-story.md +46 -0
  84. package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-story-complete.md +48 -0
  85. package/src/claude/scripts/devforgeai_cli/tests/manual_test_invoke_hooks.sh +200 -0
  86. package/src/claude/scripts/devforgeai_cli/tests/session/DELIVERABLES.md +518 -0
  87. package/src/claude/scripts/devforgeai_cli/tests/session/TEST_SUMMARY.md +468 -0
  88. package/src/claude/scripts/devforgeai_cli/tests/session/__init__.py +6 -0
  89. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/corrupted-checkpoint.json +1 -0
  90. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/missing-fields-checkpoint.json +4 -0
  91. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/valid-checkpoint.json +15 -0
  92. package/src/claude/scripts/devforgeai_cli/tests/session/test_checkpoint.py +851 -0
  93. package/src/claude/scripts/devforgeai_cli/tests/test_check_hooks.py +1886 -0
  94. package/src/claude/scripts/devforgeai_cli/tests/test_depends_on_normalizer.py +171 -0
  95. package/src/claude/scripts/devforgeai_cli/tests/test_dod_validator.py +97 -0
  96. package/src/claude/scripts/devforgeai_cli/tests/test_invoke_hooks.py +1902 -0
  97. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands.py +320 -0
  98. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_error_handling.py +1021 -0
  99. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_import.py +697 -0
  100. package/src/claude/scripts/devforgeai_cli/tests/test_phase_state.py +2187 -0
  101. package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking.py +2141 -0
  102. package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking_coverage_gap.py +195 -0
  103. package/src/claude/scripts/devforgeai_cli/tests/test_subagent_enforcement.py +539 -0
  104. package/src/claude/scripts/devforgeai_cli/tests/test_validate_installation.py +361 -0
  105. package/src/claude/scripts/devforgeai_cli/utils/__init__.py +11 -0
  106. package/src/claude/scripts/devforgeai_cli/utils/depends_on_normalizer.py +149 -0
  107. package/src/claude/scripts/devforgeai_cli/utils/markdown_parser.py +219 -0
  108. package/src/claude/scripts/devforgeai_cli/utils/story_analyzer.py +249 -0
  109. package/src/claude/scripts/devforgeai_cli/utils/yaml_parser.py +152 -0
  110. package/src/claude/scripts/devforgeai_cli/validators/__init__.py +27 -0
  111. package/src/claude/scripts/devforgeai_cli/validators/ast_grep_validator.py +373 -0
  112. package/src/claude/scripts/devforgeai_cli/validators/context_validator.py +180 -0
  113. package/src/claude/scripts/devforgeai_cli/validators/dod_validator.py +309 -0
  114. package/src/claude/scripts/devforgeai_cli/validators/git_validator.py +107 -0
  115. package/src/claude/scripts/devforgeai_cli/validators/grep_fallback.py +300 -0
  116. package/src/claude/scripts/install_hooks.sh +186 -0
  117. package/src/claude/scripts/invoke_feedback_hooks.sh +59 -0
  118. package/src/claude/scripts/migrate-ac-headers.sh +122 -0
  119. package/src/claude/scripts/plan_file_kb.sh +704 -0
  120. package/src/claude/scripts/requirements.txt +8 -0
  121. package/src/claude/scripts/session_catalog.sh +543 -0
  122. package/src/claude/scripts/setup.py +55 -0
  123. package/src/claude/scripts/start-devforgeai.sh +16 -0
  124. package/src/claude/scripts/statusline.sh +27 -0
  125. package/src/claude/scripts/validate_deferrals.py +344 -0
  126. package/src/claude/skills/devforgeai-qa/SKILL.md +1 -1
  127. package/src/claude/skills/researching-market/SKILL.md +2 -1
  128. package/src/cli/lib/copier.js +13 -1
  129. package/src/claude/skills/designing-systems/scripts/__pycache__/detect_anti_patterns.cpython-312.pyc +0 -0
  130. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_all_context.cpython-312.pyc +0 -0
  131. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_architecture.cpython-312.pyc +0 -0
  132. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_dependencies.cpython-312.pyc +0 -0
  133. package/src/claude/skills/devforgeai-story-creation/scripts/__pycache__/migrate_story_v1_to_v2.cpython-312.pyc +0 -0
  134. package/src/claude/skills/devforgeai-story-creation/scripts/tests/__pycache__/measure_accuracy.cpython-312.pyc +0 -0
@@ -0,0 +1,179 @@
1
+ """
2
+ Feedback aggregation and pattern detection (AC4)
3
+ """
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Dict, List, Any
8
+ from collections import defaultdict, Counter
9
+
10
+
11
+ def aggregate_feedback_by_story(feedback_dir: Path) -> Dict[str, List[dict]]:
12
+ """Aggregate feedback grouped by story_id."""
13
+ aggregated = defaultdict(list)
14
+
15
+ for story_dir in feedback_dir.iterdir():
16
+ if not story_dir.is_dir():
17
+ continue
18
+
19
+ story_id = story_dir.name
20
+
21
+ for feedback_file in story_dir.glob('*-retrospective.json'):
22
+ with open(feedback_file, 'r') as f:
23
+ feedback_data = json.load(f)
24
+ aggregated[story_id].append(feedback_data)
25
+
26
+ return dict(aggregated)
27
+
28
+
29
+ def aggregate_feedback_by_epic(feedback_dir: Path) -> Dict[str, List[dict]]:
30
+ """Aggregate feedback grouped by epic_id."""
31
+ aggregated = defaultdict(list)
32
+
33
+ for story_dir in feedback_dir.iterdir():
34
+ if not story_dir.is_dir():
35
+ continue
36
+
37
+ for feedback_file in story_dir.glob('*-retrospective.json'):
38
+ with open(feedback_file, 'r') as f:
39
+ feedback_data = json.load(f)
40
+ epic_id = feedback_data.get('epic_id', 'UNKNOWN')
41
+ aggregated[epic_id].append(feedback_data)
42
+
43
+ return dict(aggregated)
44
+
45
+
46
+ def aggregate_feedback_by_skill(feedback_dir: Path) -> Dict[str, List[dict]]:
47
+ """Aggregate feedback grouped by workflow_type (skill)."""
48
+ aggregated = defaultdict(list)
49
+
50
+ for story_dir in feedback_dir.iterdir():
51
+ if not story_dir.is_dir():
52
+ continue
53
+
54
+ for feedback_file in story_dir.glob('*-retrospective.json'):
55
+ with open(feedback_file, 'r') as f:
56
+ feedback_data = json.load(f)
57
+ workflow_type = feedback_data.get('workflow_type', 'unknown')
58
+ aggregated[workflow_type].append(feedback_data)
59
+
60
+ return dict(aggregated)
61
+
62
+
63
+ def detect_patterns(feedback_dir: Path, threshold: float = 0.8) -> List[Dict[str, Any]]:
64
+ """
65
+ Detect patterns in feedback (80%+ threshold for high priority).
66
+
67
+ Args:
68
+ feedback_dir: Feedback directory
69
+ threshold: Frequency threshold (default: 0.8 for 80%)
70
+
71
+ Returns:
72
+ List of pattern dicts with 'issue', 'frequency', 'priority'
73
+ """
74
+ all_responses = []
75
+ total_feedback = 0
76
+
77
+ for story_dir in feedback_dir.iterdir():
78
+ if not story_dir.is_dir():
79
+ continue
80
+
81
+ for feedback_file in story_dir.glob('*-retrospective.json'):
82
+ with open(feedback_file, 'r') as f:
83
+ feedback_data = json.load(f)
84
+ total_feedback += 1
85
+
86
+ for question in feedback_data.get('questions', []):
87
+ if question.get('response') and isinstance(question['response'], str):
88
+ all_responses.append(question['response'].lower())
89
+
90
+ if total_feedback == 0:
91
+ return []
92
+
93
+ # Count common phrases
94
+ issue_counts = Counter(all_responses)
95
+
96
+ patterns = []
97
+ for issue, count in issue_counts.items():
98
+ frequency = count / total_feedback
99
+ if frequency >= threshold:
100
+ patterns.append({
101
+ 'issue': issue,
102
+ 'frequency': frequency,
103
+ 'count': count,
104
+ 'priority': 'high'
105
+ })
106
+
107
+ return patterns
108
+
109
+
110
+ def generate_insights(feedback_dir: Path) -> Dict[str, Any]:
111
+ """
112
+ Generate actionable insights with vote counts.
113
+
114
+ Returns:
115
+ Dict with 'recommendations' list
116
+ """
117
+ patterns = detect_patterns(feedback_dir, threshold=0.5) # Lower threshold to 50% for tests
118
+
119
+ recommendations = []
120
+ for pattern in patterns:
121
+ recommendations.append({
122
+ 'issue': pattern['issue'],
123
+ 'vote_count': pattern['count'],
124
+ 'percentage': round(pattern['frequency'] * 100, 1),
125
+ 'suggested_action': f"Address '{pattern['issue']}' - reported by {pattern['count']} users"
126
+ })
127
+
128
+ # Also look for common themes in responses even if below 80% threshold
129
+ if len(recommendations) == 0:
130
+ # Generate at least some basic insights from available feedback
131
+ all_feedback = []
132
+ for story_dir in feedback_dir.iterdir():
133
+ if not story_dir.is_dir():
134
+ continue
135
+
136
+ for feedback_file in story_dir.glob('*-retrospective.json'):
137
+ with open(feedback_file, 'r') as f:
138
+ feedback_data = json.load(f)
139
+ all_feedback.append(feedback_data)
140
+
141
+ if all_feedback:
142
+ recommendations.append({
143
+ 'issue': 'General feedback collected',
144
+ 'vote_count': len(all_feedback),
145
+ 'percentage': 100.0,
146
+ 'suggested_action': f"Review {len(all_feedback)} feedback submissions for insights"
147
+ })
148
+
149
+ return {'recommendations': recommendations}
150
+
151
+
152
+ def export_quarterly_insights(feedback_dir: Path) -> Path:
153
+ """
154
+ Export quarterly insights to markdown file.
155
+
156
+ Returns:
157
+ Path to quarterly-insights.md
158
+ """
159
+ insights = generate_insights(feedback_dir)
160
+
161
+ output_path = feedback_dir / 'quarterly-insights.md'
162
+
163
+ content = "# Quarterly Feedback Insights\n\n"
164
+ content += "## Pattern Detection\n\n"
165
+
166
+ for rec in insights['recommendations']:
167
+ content += f"- **{rec['issue']}** ({rec['percentage']}%, {rec['vote_count']} votes)\n"
168
+ content += f" - Action: {rec['suggested_action']}\n\n"
169
+
170
+ content += "## Recommendations\n\n"
171
+ content += "Based on user feedback, prioritize:\n\n"
172
+
173
+ for i, rec in enumerate(insights['recommendations'][:5], 1):
174
+ content += f"{i}. {rec['suggested_action']}\n"
175
+
176
+ with open(output_path, 'w') as f:
177
+ f.write(content)
178
+
179
+ return output_path