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,152 @@
1
+ """
2
+ Failure mode identification and ranking module.
3
+
4
+ AC#2: Identify and rank most common failure modes from error entries.
5
+
6
+ STORY-227: Calculate Workflow Success Metrics
7
+ """
8
+ from collections import Counter
9
+ from typing import Any, Dict, List
10
+
11
+
12
+ # Category mapping for error types
13
+ CATEGORY_MAP: Dict[str, str] = {
14
+ "test_failure": "testing",
15
+ "coverage_gap": "quality",
16
+ "validation_failure": "validation",
17
+ "timeout": "infrastructure",
18
+ }
19
+
20
+
21
+ def identify_failure_modes(error_entries: List[Dict[str, Any]]) -> List[str]:
22
+ """
23
+ Return list of unique failure modes (error_type values).
24
+
25
+ Args:
26
+ error_entries: List of error entries with 'error_type' field.
27
+
28
+ Returns:
29
+ List of unique failure mode strings.
30
+ Skips entries without error_type field.
31
+ Returns empty list for empty input.
32
+ """
33
+ if not error_entries:
34
+ return []
35
+
36
+ # Extract unique error_type values, skipping entries without the field
37
+ failure_modes = set()
38
+ for entry in error_entries:
39
+ error_type = entry.get("error_type")
40
+ if error_type is not None:
41
+ failure_modes.add(error_type)
42
+
43
+ return list(failure_modes)
44
+
45
+
46
+ def rank_failure_modes(error_entries: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
47
+ """
48
+ Return failure modes ranked by frequency (most common first).
49
+
50
+ Args:
51
+ error_entries: List of error entries with 'error_type' field.
52
+
53
+ Returns:
54
+ List of dicts, each containing:
55
+ - error_type: str
56
+ - count: int
57
+ - percentage: float (0-100)
58
+ Returns empty list for empty input.
59
+ """
60
+ if not error_entries:
61
+ return []
62
+
63
+ # Count occurrences of each error_type (skip entries without error_type)
64
+ error_types = [
65
+ entry.get("error_type")
66
+ for entry in error_entries
67
+ if entry.get("error_type") is not None
68
+ ]
69
+
70
+ if not error_types:
71
+ return []
72
+
73
+ # Count frequencies
74
+ counter = Counter(error_types)
75
+ total_errors = len(error_types)
76
+
77
+ # Sort by count (descending) and create result
78
+ ranked = []
79
+ for error_type, count in counter.most_common():
80
+ percentage = (count / total_errors) * 100.0
81
+ ranked.append({
82
+ "error_type": error_type,
83
+ "count": count,
84
+ "percentage": percentage,
85
+ })
86
+
87
+ return ranked
88
+
89
+
90
+ def categorize_failure_mode(error_type: str) -> str:
91
+ """
92
+ Categorize error types into categories.
93
+
94
+ Args:
95
+ error_type: The error type string to categorize.
96
+
97
+ Returns:
98
+ Category string:
99
+ - "test_failure" -> "testing"
100
+ - "coverage_gap" -> "quality"
101
+ - "validation_failure" -> "validation"
102
+ - "timeout" -> "infrastructure"
103
+ - anything else -> "unknown"
104
+ """
105
+ return CATEGORY_MAP.get(error_type, "unknown")
106
+
107
+
108
+ def get_failure_mode_summary(error_entries: List[Dict[str, Any]]) -> Dict[str, Any]:
109
+ """
110
+ Return summary of failure modes.
111
+
112
+ Args:
113
+ error_entries: List of error entries with 'error_type' field.
114
+
115
+ Returns:
116
+ Dictionary containing:
117
+ - total_errors: int
118
+ - unique_failure_modes: int
119
+ - ranked_modes: List[Dict] (from rank_failure_modes)
120
+ - by_category: Dict[str, int] (count per category)
121
+ """
122
+ if not error_entries:
123
+ return {
124
+ "total_errors": 0,
125
+ "unique_failure_modes": 0,
126
+ "ranked_modes": [],
127
+ "by_category": {},
128
+ }
129
+
130
+ # Get failure modes and ranked list
131
+ failure_modes = identify_failure_modes(error_entries)
132
+ ranked_modes = rank_failure_modes(error_entries)
133
+
134
+ # Count by category
135
+ by_category: Dict[str, int] = {}
136
+ for entry in error_entries:
137
+ error_type = entry.get("error_type")
138
+ if error_type is not None:
139
+ category = categorize_failure_mode(error_type)
140
+ by_category[category] = by_category.get(category, 0) + 1
141
+
142
+ # Count total errors (only entries with error_type)
143
+ total_errors = sum(
144
+ 1 for entry in error_entries if entry.get("error_type") is not None
145
+ )
146
+
147
+ return {
148
+ "total_errors": total_errors,
149
+ "unique_failure_modes": len(failure_modes),
150
+ "ranked_modes": ranked_modes,
151
+ "by_category": by_category,
152
+ }
@@ -0,0 +1,181 @@
1
+ """
2
+ Story point segmentation and averages module.
3
+
4
+ AC#3: Segment metrics by story points (1, 2, 3, 5, 8 - Fibonacci-based).
5
+
6
+ STORY-227: Calculate Workflow Success Metrics
7
+ """
8
+ from typing import Any, Dict, List, Optional
9
+
10
+
11
+ # Valid Fibonacci-based story points
12
+ VALID_STORY_POINTS: List[int] = [1, 2, 3, 5, 8]
13
+
14
+
15
+ def get_valid_story_points() -> List[int]:
16
+ """
17
+ Return the list of valid story point values.
18
+
19
+ Returns:
20
+ [1, 2, 3, 5, 8] (Fibonacci-based story points)
21
+ """
22
+ return VALID_STORY_POINTS.copy()
23
+
24
+
25
+ def is_valid_story_point(point: Any) -> bool:
26
+ """
27
+ Check if a value is a valid story point.
28
+
29
+ Args:
30
+ point: The value to check.
31
+
32
+ Returns:
33
+ True if point is in [1, 2, 3, 5, 8], False otherwise.
34
+ Returns False for None.
35
+ """
36
+ if point is None:
37
+ return False
38
+ return point in VALID_STORY_POINTS
39
+
40
+
41
+ def segment_metrics_by_story_points(
42
+ workflow_metrics: List[Dict[str, Any]]
43
+ ) -> Dict[int, List[Dict[str, Any]]]:
44
+ """
45
+ Segment metrics by story points.
46
+
47
+ Args:
48
+ workflow_metrics: List of workflow metric entries with 'story_points' field.
49
+
50
+ Returns:
51
+ Dictionary with valid story points as keys:
52
+ {
53
+ 1: [stories with 1 point...],
54
+ 2: [stories with 2 points...],
55
+ 3: [], # empty if no stories
56
+ 5: [],
57
+ 8: []
58
+ }
59
+ - Only includes valid points (1, 2, 3, 5, 8)
60
+ - Excludes stories with missing/invalid story_points
61
+ - Returns structure with empty lists for empty input
62
+ """
63
+ # Initialize result with empty lists for each valid point
64
+ result: Dict[int, List[Dict[str, Any]]] = {
65
+ point: [] for point in VALID_STORY_POINTS
66
+ }
67
+
68
+ if not workflow_metrics:
69
+ return result
70
+
71
+ for metric in workflow_metrics:
72
+ story_points = metric.get("story_points")
73
+
74
+ # Skip if story_points is missing, None, or invalid
75
+ if not is_valid_story_point(story_points):
76
+ continue
77
+
78
+ # Add to appropriate segment
79
+ result[story_points].append(metric)
80
+
81
+ return result
82
+
83
+
84
+ def calculate_segment_averages(
85
+ segments: Dict[int, List[Dict[str, Any]]]
86
+ ) -> Dict[int, Dict[str, Optional[float]]]:
87
+ """
88
+ Calculate averages per segment.
89
+
90
+ Args:
91
+ segments: Dictionary of story point segments from segment_metrics_by_story_points.
92
+
93
+ Returns:
94
+ Dictionary with averages per segment:
95
+ {
96
+ 1: {"avg_completion_rate": float, "avg_error_rate": float},
97
+ 2: {...},
98
+ ...
99
+ }
100
+ - Returns 0.0 for empty segments
101
+ """
102
+ result: Dict[int, Dict[str, Optional[float]]] = {}
103
+
104
+ for point in VALID_STORY_POINTS:
105
+ stories = segments.get(point, [])
106
+
107
+ if not stories:
108
+ result[point] = {
109
+ "avg_completion_rate": 0.0,
110
+ "avg_error_rate": 0.0,
111
+ }
112
+ else:
113
+ # Calculate averages
114
+ total_completion = sum(
115
+ story.get("completion_rate", 0.0) for story in stories
116
+ )
117
+ total_error = sum(
118
+ story.get("error_rate", 0.0) for story in stories
119
+ )
120
+
121
+ avg_completion = total_completion / len(stories)
122
+ avg_error = total_error / len(stories)
123
+
124
+ # Round to 2 decimal places
125
+ result[point] = {
126
+ "avg_completion_rate": round(avg_completion, 2),
127
+ "avg_error_rate": round(avg_error, 2),
128
+ }
129
+
130
+ return result
131
+
132
+
133
+ def get_segmentation_summary(
134
+ workflow_metrics: List[Dict[str, Any]]
135
+ ) -> Dict[str, Any]:
136
+ """
137
+ Return summary of story point segmentation.
138
+
139
+ Args:
140
+ workflow_metrics: List of workflow metric entries.
141
+
142
+ Returns:
143
+ Dictionary containing:
144
+ - total_stories: int (all stories including invalid)
145
+ - segmented_stories: int (stories with valid points)
146
+ - excluded_stories: int (stories without valid points)
147
+ - segments: Dict[int, List[Dict]] (from segment_metrics_by_story_points)
148
+ - averages_by_segment: Dict[int, Dict] (from calculate_segment_averages)
149
+ """
150
+ if not workflow_metrics:
151
+ return {
152
+ "total_stories": 0,
153
+ "segmented_stories": 0,
154
+ "excluded_stories": 0,
155
+ "segments": {point: [] for point in VALID_STORY_POINTS},
156
+ "averages_by_segment": {
157
+ point: {"avg_completion_rate": 0.0, "avg_error_rate": 0.0}
158
+ for point in VALID_STORY_POINTS
159
+ },
160
+ }
161
+
162
+ # Segment the metrics
163
+ segments = segment_metrics_by_story_points(workflow_metrics)
164
+
165
+ # Count segmented stories
166
+ segmented_count = sum(len(stories) for stories in segments.values())
167
+
168
+ # Calculate total and excluded
169
+ total_stories = len(workflow_metrics)
170
+ excluded_stories = total_stories - segmented_count
171
+
172
+ # Calculate averages
173
+ averages = calculate_segment_averages(segments)
174
+
175
+ return {
176
+ "total_stories": total_stories,
177
+ "segmented_stories": segmented_count,
178
+ "excluded_stories": excluded_stories,
179
+ "segments": segments,
180
+ "averages_by_segment": averages,
181
+ }