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.
- package/CLAUDE.md +120 -0
- package/package.json +9 -1
- package/src/CLAUDE.md +699 -0
- package/src/claude/scripts/README.md +396 -0
- package/src/claude/scripts/audit-command-skill-overlap.sh +67 -0
- package/src/claude/scripts/check-hooks-fast.sh +70 -0
- package/src/claude/scripts/devforgeai-validate +6 -0
- package/src/claude/scripts/devforgeai_cli/README.md +531 -0
- package/src/claude/scripts/devforgeai_cli/__init__.py +12 -0
- package/src/claude/scripts/devforgeai_cli/cli.py +716 -0
- package/src/claude/scripts/devforgeai_cli/commands/__init__.py +1 -0
- package/src/claude/scripts/devforgeai_cli/commands/check_hooks.py +384 -0
- package/src/claude/scripts/devforgeai_cli/commands/invoke_hooks.py +149 -0
- package/src/claude/scripts/devforgeai_cli/commands/phase_commands.py +731 -0
- package/src/claude/scripts/devforgeai_cli/commands/validate_installation.py +412 -0
- package/src/claude/scripts/devforgeai_cli/context_extraction.py +426 -0
- package/src/claude/scripts/devforgeai_cli/feedback/AC_TO_TEST_MAPPING.md +636 -0
- package/src/claude/scripts/devforgeai_cli/feedback/DELIVERY_SUMMARY.txt +329 -0
- package/src/claude/scripts/devforgeai_cli/feedback/README_TEST_SPECS.md +486 -0
- package/src/claude/scripts/devforgeai_cli/feedback/TEST_IMPLEMENTATION_GUIDE.md +529 -0
- package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECIFICATIONS.md +2652 -0
- package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECS_INDEX.md +398 -0
- package/src/claude/scripts/devforgeai_cli/feedback/__init__.py +34 -0
- package/src/claude/scripts/devforgeai_cli/feedback/adaptive_questioning_engine.py +581 -0
- package/src/claude/scripts/devforgeai_cli/feedback/aggregation.py +179 -0
- package/src/claude/scripts/devforgeai_cli/feedback/commands.py +535 -0
- package/src/claude/scripts/devforgeai_cli/feedback/config_defaults.py +58 -0
- package/src/claude/scripts/devforgeai_cli/feedback/config_manager.py +423 -0
- package/src/claude/scripts/devforgeai_cli/feedback/config_models.py +192 -0
- package/src/claude/scripts/devforgeai_cli/feedback/config_schema.py +140 -0
- package/src/claude/scripts/devforgeai_cli/feedback/coverage.json +1 -0
- package/src/claude/scripts/devforgeai_cli/feedback/feature_flag.py +152 -0
- package/src/claude/scripts/devforgeai_cli/feedback/feedback_indexer.py +394 -0
- package/src/claude/scripts/devforgeai_cli/feedback/hot_reload.py +226 -0
- package/src/claude/scripts/devforgeai_cli/feedback/longitudinal.py +115 -0
- package/src/claude/scripts/devforgeai_cli/feedback/models.py +67 -0
- package/src/claude/scripts/devforgeai_cli/feedback/question_router.py +236 -0
- package/src/claude/scripts/devforgeai_cli/feedback/retrospective.py +233 -0
- package/src/claude/scripts/devforgeai_cli/feedback/skip_tracker.py +177 -0
- package/src/claude/scripts/devforgeai_cli/feedback/skip_tracking.py +221 -0
- package/src/claude/scripts/devforgeai_cli/feedback/template_engine.py +549 -0
- package/src/claude/scripts/devforgeai_cli/feedback/validation.py +163 -0
- package/src/claude/scripts/devforgeai_cli/headless/__init__.py +30 -0
- package/src/claude/scripts/devforgeai_cli/headless/answer_models.py +206 -0
- package/src/claude/scripts/devforgeai_cli/headless/answer_resolver.py +204 -0
- package/src/claude/scripts/devforgeai_cli/headless/exceptions.py +36 -0
- package/src/claude/scripts/devforgeai_cli/headless/pattern_matcher.py +156 -0
- package/src/claude/scripts/devforgeai_cli/hooks.py +313 -0
- package/src/claude/scripts/devforgeai_cli/metrics/__init__.py +46 -0
- package/src/claude/scripts/devforgeai_cli/metrics/command_metrics.py +142 -0
- package/src/claude/scripts/devforgeai_cli/metrics/failure_modes.py +152 -0
- package/src/claude/scripts/devforgeai_cli/metrics/story_segmentation.py +181 -0
- package/src/claude/scripts/devforgeai_cli/orchestrate_hooks.py +780 -0
- package/src/claude/scripts/devforgeai_cli/phase_state.py +1229 -0
- package/src/claude/scripts/devforgeai_cli/session/__init__.py +30 -0
- package/src/claude/scripts/devforgeai_cli/session/checkpoint.py +268 -0
- package/src/claude/scripts/devforgeai_cli/tests/__init__.py +1 -0
- package/src/claude/scripts/devforgeai_cli/tests/conftest.py +29 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/TEST_EXECUTION_GUIDE.md +298 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/__init__.py +3 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_adaptive_questioning_engine.py +2171 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_aggregation.py +476 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_defaults.py +133 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_manager.py +592 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_models.py +373 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_schema.py +130 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py +1355 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_edge_cases.py +308 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feature_flag.py +307 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feedback_indexer.py +384 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_hot_reload.py +580 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_integration.py +402 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_models.py +105 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_question_routing.py +262 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_retrospective.py +333 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracker.py +410 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking.py +159 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking_integration.py +1155 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_template_engine.py +1389 -0
- package/src/claude/scripts/devforgeai_cli/tests/feedback/test_validation_comprehensive.py +210 -0
- package/src/claude/scripts/devforgeai_cli/tests/fixtures/autonomous-deferral-story.md +46 -0
- package/src/claude/scripts/devforgeai_cli/tests/fixtures/missing-impl-notes.md +31 -0
- package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-deferral-story.md +46 -0
- package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-story-complete.md +48 -0
- package/src/claude/scripts/devforgeai_cli/tests/manual_test_invoke_hooks.sh +200 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/DELIVERABLES.md +518 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/TEST_SUMMARY.md +468 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/__init__.py +6 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/corrupted-checkpoint.json +1 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/missing-fields-checkpoint.json +4 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/valid-checkpoint.json +15 -0
- package/src/claude/scripts/devforgeai_cli/tests/session/test_checkpoint.py +851 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_check_hooks.py +1886 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_depends_on_normalizer.py +171 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_dod_validator.py +97 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_invoke_hooks.py +1902 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands.py +320 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_error_handling.py +1021 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_import.py +697 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_phase_state.py +2187 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking.py +2141 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking_coverage_gap.py +195 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_subagent_enforcement.py +539 -0
- package/src/claude/scripts/devforgeai_cli/tests/test_validate_installation.py +361 -0
- package/src/claude/scripts/devforgeai_cli/utils/__init__.py +11 -0
- package/src/claude/scripts/devforgeai_cli/utils/depends_on_normalizer.py +149 -0
- package/src/claude/scripts/devforgeai_cli/utils/markdown_parser.py +219 -0
- package/src/claude/scripts/devforgeai_cli/utils/story_analyzer.py +249 -0
- package/src/claude/scripts/devforgeai_cli/utils/yaml_parser.py +152 -0
- package/src/claude/scripts/devforgeai_cli/validators/__init__.py +27 -0
- package/src/claude/scripts/devforgeai_cli/validators/ast_grep_validator.py +373 -0
- package/src/claude/scripts/devforgeai_cli/validators/context_validator.py +180 -0
- package/src/claude/scripts/devforgeai_cli/validators/dod_validator.py +309 -0
- package/src/claude/scripts/devforgeai_cli/validators/git_validator.py +107 -0
- package/src/claude/scripts/devforgeai_cli/validators/grep_fallback.py +300 -0
- package/src/claude/scripts/install_hooks.sh +186 -0
- package/src/claude/scripts/invoke_feedback_hooks.sh +59 -0
- package/src/claude/scripts/migrate-ac-headers.sh +122 -0
- package/src/claude/scripts/plan_file_kb.sh +704 -0
- package/src/claude/scripts/requirements.txt +8 -0
- package/src/claude/scripts/session_catalog.sh +543 -0
- package/src/claude/scripts/setup.py +55 -0
- package/src/claude/scripts/start-devforgeai.sh +16 -0
- package/src/claude/scripts/statusline.sh +27 -0
- package/src/claude/scripts/validate_deferrals.py +344 -0
- package/src/claude/skills/devforgeai-qa/SKILL.md +1 -1
- package/src/claude/skills/researching-market/SKILL.md +2 -1
- package/src/cli/lib/copier.js +13 -1
- package/src/claude/skills/designing-systems/scripts/__pycache__/detect_anti_patterns.cpython-312.pyc +0 -0
- package/src/claude/skills/designing-systems/scripts/__pycache__/validate_all_context.cpython-312.pyc +0 -0
- package/src/claude/skills/designing-systems/scripts/__pycache__/validate_architecture.cpython-312.pyc +0 -0
- package/src/claude/skills/designing-systems/scripts/__pycache__/validate_dependencies.cpython-312.pyc +0 -0
- package/src/claude/skills/devforgeai-story-creation/scripts/__pycache__/migrate_story_v1_to_v2.cpython-312.pyc +0 -0
- package/src/claude/skills/devforgeai-story-creation/scripts/tests/__pycache__/measure_accuracy.cpython-312.pyc +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session management for DevForgeAI CLI.
|
|
3
|
+
|
|
4
|
+
Provides checkpoint functionality for TDD workflow session recovery.
|
|
5
|
+
Enables resuming development sessions after context window fills.
|
|
6
|
+
|
|
7
|
+
STORY-120: Session Checkpoint Protocol
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .checkpoint import (
|
|
11
|
+
write_checkpoint,
|
|
12
|
+
read_checkpoint,
|
|
13
|
+
delete_checkpoint,
|
|
14
|
+
CHECKPOINT_FILENAME,
|
|
15
|
+
SESSIONS_DIR,
|
|
16
|
+
PHASE_NAMES,
|
|
17
|
+
PHASE_PROGRESS,
|
|
18
|
+
REQUIRED_FIELDS,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
'write_checkpoint',
|
|
23
|
+
'read_checkpoint',
|
|
24
|
+
'delete_checkpoint',
|
|
25
|
+
'CHECKPOINT_FILENAME',
|
|
26
|
+
'SESSIONS_DIR',
|
|
27
|
+
'PHASE_NAMES',
|
|
28
|
+
'PHASE_PROGRESS',
|
|
29
|
+
'REQUIRED_FIELDS',
|
|
30
|
+
]
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session Checkpoint Management for DevForgeAI CLI.
|
|
3
|
+
|
|
4
|
+
Enables resuming TDD implementation across context window resets.
|
|
5
|
+
Checkpoints are written at each phase completion and read by /resume-dev
|
|
6
|
+
for automatic phase detection.
|
|
7
|
+
|
|
8
|
+
STORY-120: Session Checkpoint Protocol
|
|
9
|
+
|
|
10
|
+
Based on patterns from: devforgeai_cli/validators/dod_validator.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import shutil
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Dict, Optional, Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ============================================================================
|
|
23
|
+
# CONSTANTS
|
|
24
|
+
# ============================================================================
|
|
25
|
+
|
|
26
|
+
CHECKPOINT_FILENAME = "checkpoint.json"
|
|
27
|
+
SESSIONS_DIR = "devforgeai/sessions"
|
|
28
|
+
|
|
29
|
+
# Phase 0-7 maps to TDD workflow phases (AC#1: phases 0-7)
|
|
30
|
+
PHASE_NAMES: Dict[int, str] = {
|
|
31
|
+
0: "Pre-Flight",
|
|
32
|
+
1: "Red (Test Generation)",
|
|
33
|
+
2: "Green (Implementation)",
|
|
34
|
+
3: "Refactor",
|
|
35
|
+
4: "Integration",
|
|
36
|
+
5: "Deferral Challenge",
|
|
37
|
+
6: "DoD Update",
|
|
38
|
+
7: "Git Workflow",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
PHASE_PROGRESS: Dict[int, int] = {
|
|
42
|
+
0: 10,
|
|
43
|
+
1: 20,
|
|
44
|
+
2: 30,
|
|
45
|
+
3: 40,
|
|
46
|
+
4: 50,
|
|
47
|
+
5: 60,
|
|
48
|
+
6: 75,
|
|
49
|
+
7: 100,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
REQUIRED_FIELDS = [
|
|
53
|
+
"story_id",
|
|
54
|
+
"phase",
|
|
55
|
+
"phase_name",
|
|
56
|
+
"timestamp",
|
|
57
|
+
"progress_percentage",
|
|
58
|
+
"dod_completion",
|
|
59
|
+
"next_action",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
# Validation patterns
|
|
63
|
+
STORY_ID_PATTERN = re.compile(r"^STORY-\d{3,}$")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
# HELPER FUNCTIONS
|
|
68
|
+
# ============================================================================
|
|
69
|
+
|
|
70
|
+
def _get_sessions_dir() -> str:
|
|
71
|
+
"""Get sessions directory from environment or default."""
|
|
72
|
+
return os.environ.get("DEVFORGEAI_SESSIONS_DIR", SESSIONS_DIR)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _validate_story_id(story_id: str) -> bool:
|
|
76
|
+
"""Validate story ID format (STORY-NNN)."""
|
|
77
|
+
if not story_id or not isinstance(story_id, str):
|
|
78
|
+
return False
|
|
79
|
+
return bool(STORY_ID_PATTERN.match(story_id))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _validate_phase(phase: int) -> bool:
|
|
83
|
+
"""Validate phase is in valid range (0-7)."""
|
|
84
|
+
if not isinstance(phase, int):
|
|
85
|
+
return False
|
|
86
|
+
return 0 <= phase <= 7
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _validate_dod_completion(dod_completion: Any) -> bool:
|
|
90
|
+
"""Validate dod_completion has required keys."""
|
|
91
|
+
if not isinstance(dod_completion, dict):
|
|
92
|
+
return False
|
|
93
|
+
required_keys = ["implementation", "quality", "testing", "documentation"]
|
|
94
|
+
return all(key in dod_completion for key in required_keys)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _get_checkpoint_path(story_id: str) -> Path:
|
|
98
|
+
"""Get standardized checkpoint file path."""
|
|
99
|
+
sessions_dir = _get_sessions_dir()
|
|
100
|
+
return Path(sessions_dir) / story_id / CHECKPOINT_FILENAME
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ============================================================================
|
|
104
|
+
# PUBLIC FUNCTIONS
|
|
105
|
+
# ============================================================================
|
|
106
|
+
|
|
107
|
+
def write_checkpoint(
|
|
108
|
+
story_id: str,
|
|
109
|
+
phase: int,
|
|
110
|
+
progress: Dict[str, Any],
|
|
111
|
+
) -> bool:
|
|
112
|
+
"""
|
|
113
|
+
Write checkpoint to session directory.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
story_id: Story identifier (STORY-NNN format)
|
|
117
|
+
phase: Current phase number (0-7)
|
|
118
|
+
progress: Checkpoint data dict containing dod_completion and next_action
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
True on success, False on failure
|
|
122
|
+
|
|
123
|
+
Raises:
|
|
124
|
+
ValueError: If story_id or phase are invalid (optional behavior)
|
|
125
|
+
"""
|
|
126
|
+
# Validate inputs
|
|
127
|
+
if not _validate_story_id(story_id):
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
if not _validate_phase(phase):
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
# Extract or default dod_completion
|
|
134
|
+
dod_completion = progress.get("dod_completion", {
|
|
135
|
+
"implementation": [0, 0],
|
|
136
|
+
"quality": [0, 0],
|
|
137
|
+
"testing": [0, 0],
|
|
138
|
+
"documentation": [0, 0],
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
if not _validate_dod_completion(dod_completion):
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
# Build checkpoint data
|
|
145
|
+
# Use progress_percentage from input if provided, else default from PHASE_PROGRESS
|
|
146
|
+
progress_pct = progress.get("progress_percentage", PHASE_PROGRESS.get(phase, 0))
|
|
147
|
+
|
|
148
|
+
checkpoint_data = {
|
|
149
|
+
"story_id": story_id,
|
|
150
|
+
"phase": phase,
|
|
151
|
+
"phase_name": progress.get("phase_name", PHASE_NAMES.get(phase, f"Phase {phase}")),
|
|
152
|
+
"timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
|
153
|
+
"progress_percentage": progress_pct,
|
|
154
|
+
"dod_completion": dod_completion,
|
|
155
|
+
"last_action": progress.get("last_action", ""),
|
|
156
|
+
"next_action": progress.get("next_action", f"Phase {phase + 1}"),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
# Get checkpoint path
|
|
161
|
+
checkpoint_path = _get_checkpoint_path(story_id)
|
|
162
|
+
|
|
163
|
+
# Create directory if not exists
|
|
164
|
+
checkpoint_path.parent.mkdir(parents=True, exist_ok=True)
|
|
165
|
+
|
|
166
|
+
# Write JSON with atomic pattern (write to temp, then rename)
|
|
167
|
+
temp_path = checkpoint_path.with_suffix(".tmp")
|
|
168
|
+
with open(temp_path, "w", encoding="utf-8") as f:
|
|
169
|
+
json.dump(checkpoint_data, f, indent=2)
|
|
170
|
+
|
|
171
|
+
# Atomic rename
|
|
172
|
+
shutil.move(str(temp_path), str(checkpoint_path))
|
|
173
|
+
|
|
174
|
+
return True
|
|
175
|
+
|
|
176
|
+
except (IOError, OSError, json.JSONDecodeError) as e:
|
|
177
|
+
# Log error but don't crash
|
|
178
|
+
# Graceful failure - checkpoint is optional for workflow
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def read_checkpoint(story_id: str) -> Optional[Dict[str, Any]]:
|
|
183
|
+
"""
|
|
184
|
+
Read checkpoint from session directory.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
story_id: Story identifier (STORY-NNN format)
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Checkpoint data dict if valid, None if missing or corrupted
|
|
191
|
+
|
|
192
|
+
AC#5: Graceful fallback if missing/corrupted
|
|
193
|
+
"""
|
|
194
|
+
# Validate input
|
|
195
|
+
if not _validate_story_id(story_id):
|
|
196
|
+
return None
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
checkpoint_path = _get_checkpoint_path(story_id)
|
|
200
|
+
|
|
201
|
+
# Check if file exists
|
|
202
|
+
if not checkpoint_path.exists():
|
|
203
|
+
return None
|
|
204
|
+
|
|
205
|
+
# Read and parse JSON
|
|
206
|
+
with open(checkpoint_path, "r", encoding="utf-8") as f:
|
|
207
|
+
data = json.load(f)
|
|
208
|
+
|
|
209
|
+
# Validate required fields (AC#5: graceful fallback)
|
|
210
|
+
if not isinstance(data, dict):
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
for field in REQUIRED_FIELDS:
|
|
214
|
+
if field not in data:
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
# Validate specific field types
|
|
218
|
+
if not isinstance(data.get("phase"), int):
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
if not _validate_dod_completion(data.get("dod_completion")):
|
|
222
|
+
return None
|
|
223
|
+
|
|
224
|
+
return data
|
|
225
|
+
|
|
226
|
+
except (IOError, OSError, json.JSONDecodeError, KeyError, TypeError):
|
|
227
|
+
# Corrupted or unreadable - return None for graceful fallback
|
|
228
|
+
return None
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def delete_checkpoint(story_id: str) -> bool:
|
|
232
|
+
"""
|
|
233
|
+
Delete checkpoint file and clean up empty directory.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
story_id: Story identifier (STORY-NNN format)
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
True on success (including if file didn't exist), False on error
|
|
240
|
+
|
|
241
|
+
AC#4: Checkpoint cleaned up on Released status
|
|
242
|
+
"""
|
|
243
|
+
# Validate input (but still succeed if invalid - idempotent)
|
|
244
|
+
if not _validate_story_id(story_id):
|
|
245
|
+
return True # Nothing to delete for invalid ID
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
checkpoint_path = _get_checkpoint_path(story_id)
|
|
249
|
+
|
|
250
|
+
# Remove checkpoint file if exists
|
|
251
|
+
if checkpoint_path.exists():
|
|
252
|
+
checkpoint_path.unlink()
|
|
253
|
+
|
|
254
|
+
# Remove empty parent directory
|
|
255
|
+
session_dir = checkpoint_path.parent
|
|
256
|
+
if session_dir.exists() and session_dir.is_dir():
|
|
257
|
+
try:
|
|
258
|
+
# Only remove if empty
|
|
259
|
+
session_dir.rmdir()
|
|
260
|
+
except OSError:
|
|
261
|
+
# Directory not empty - that's fine
|
|
262
|
+
pass
|
|
263
|
+
|
|
264
|
+
return True
|
|
265
|
+
|
|
266
|
+
except (IOError, OSError) as e:
|
|
267
|
+
# Return False only on actual errors
|
|
268
|
+
return False
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tests for DevForgeAI CLI validators."""
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pytest configuration and shared fixtures for devforgeai_cli tests.
|
|
3
|
+
|
|
4
|
+
Provides common fixtures for all test modules:
|
|
5
|
+
- Environment setup
|
|
6
|
+
- Temporary directories
|
|
7
|
+
- Mock utilities
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture(scope="session")
|
|
17
|
+
def project_root():
|
|
18
|
+
"""Get the project root directory."""
|
|
19
|
+
return Path(__file__).parent.parent.parent.parent.parent.parent
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def monkeypatch_devforgeai_home(monkeypatch, tmp_path):
|
|
24
|
+
"""Set up a temporary DevForgeAI home directory for testing."""
|
|
25
|
+
devforgeai_home = tmp_path / "devforgeai"
|
|
26
|
+
devforgeai_home.mkdir(parents=True, exist_ok=True)
|
|
27
|
+
|
|
28
|
+
monkeypatch.setenv("DEVFORGEAI_HOME", str(devforgeai_home))
|
|
29
|
+
yield devforgeai_home
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# STORY-011: Configuration Management - Test Execution Guide
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
### Run All Tests
|
|
6
|
+
```bash
|
|
7
|
+
cd /mnt/c/Projects/DevForgeAI2
|
|
8
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py -v
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Run Specific Test Categories
|
|
12
|
+
|
|
13
|
+
#### YAML Parsing Tests
|
|
14
|
+
```bash
|
|
15
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestYamlParsing -v
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
#### Validation Tests
|
|
19
|
+
```bash
|
|
20
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestConfigurationValidation -v
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Integration Tests
|
|
24
|
+
```bash
|
|
25
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestConfigurationLoading -v
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Edge Cases
|
|
29
|
+
```bash
|
|
30
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestEdgeCases -v
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Performance Tests
|
|
34
|
+
```bash
|
|
35
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestPerformance -v
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Advanced Usage
|
|
39
|
+
|
|
40
|
+
### Run with Coverage Report
|
|
41
|
+
```bash
|
|
42
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py \
|
|
43
|
+
--cov=.claude/scripts/devforgeai_cli/feedback \
|
|
44
|
+
--cov-report=html \
|
|
45
|
+
--cov-report=term
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Run Single Test
|
|
49
|
+
```bash
|
|
50
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestYamlParsing::test_valid_yaml_structure_parses_successfully -v
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Run with Verbose Output
|
|
54
|
+
```bash
|
|
55
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py -vv -s
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Run and Stop on First Failure
|
|
59
|
+
```bash
|
|
60
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py -x
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Run with Warnings
|
|
64
|
+
```bash
|
|
65
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py -W all
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Generate Test Report
|
|
69
|
+
```bash
|
|
70
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py \
|
|
71
|
+
--html=test_report.html \
|
|
72
|
+
--self-contained-html
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Installation Requirements
|
|
76
|
+
|
|
77
|
+
### Ensure pytest is installed
|
|
78
|
+
```bash
|
|
79
|
+
pip install pytest pytest-cov pytest-html pytest-watch
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Install Dependencies (if needed)
|
|
83
|
+
```bash
|
|
84
|
+
pip install pyyaml
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Understanding Test Results
|
|
88
|
+
|
|
89
|
+
### All Tests Pass (Green) ✅
|
|
90
|
+
```
|
|
91
|
+
========== 67 passed in 2.34s ===========
|
|
92
|
+
```
|
|
93
|
+
**Meaning:** Implementation correctly satisfies all requirements.
|
|
94
|
+
|
|
95
|
+
### Tests Fail Initially (Red) ❌
|
|
96
|
+
```
|
|
97
|
+
========== 67 failed in 0.45s ===========
|
|
98
|
+
```
|
|
99
|
+
**Expected:** This is TDD Red phase - no implementation yet.
|
|
100
|
+
|
|
101
|
+
### After Implementation (Green) ✅
|
|
102
|
+
```
|
|
103
|
+
========== 67 passed in 1.89s ===========
|
|
104
|
+
Coverage: 96% ✅
|
|
105
|
+
```
|
|
106
|
+
**Expected:** All tests pass after implementation complete.
|
|
107
|
+
|
|
108
|
+
## Test Execution Flow
|
|
109
|
+
|
|
110
|
+
### Phase 1: Red (Currently Here)
|
|
111
|
+
1. ✅ Tests written (this file)
|
|
112
|
+
2. ✅ All tests fail (no implementation)
|
|
113
|
+
3. Next: Implement code
|
|
114
|
+
|
|
115
|
+
### Phase 2: Green (Next Step)
|
|
116
|
+
1. ❌ Implement FeedbackConfiguration class
|
|
117
|
+
2. ❌ Implement YAML parser
|
|
118
|
+
3. ❌ Implement validation logic
|
|
119
|
+
4. ❌ Implement hot-reload
|
|
120
|
+
5. ✅ All tests pass
|
|
121
|
+
|
|
122
|
+
### Phase 3: Refactor (After Green)
|
|
123
|
+
1. ✅ Improve code quality
|
|
124
|
+
2. ✅ Extract common patterns
|
|
125
|
+
3. ✅ Optimize performance
|
|
126
|
+
4. ✅ Ensure tests still pass
|
|
127
|
+
|
|
128
|
+
## Test Categories and Expected Status
|
|
129
|
+
|
|
130
|
+
| Category | Count | Expected Status | Time |
|
|
131
|
+
|----------|-------|-----------------|------|
|
|
132
|
+
| YAML Parsing | 5 | ❌ FAIL | <1s |
|
|
133
|
+
| Validation | 10 | ❌ FAIL | <1s |
|
|
134
|
+
| Defaults | 5 | ❌ FAIL | <1s |
|
|
135
|
+
| Master Control | 3 | ❌ FAIL | <1s |
|
|
136
|
+
| Trigger Modes | 6 | ❌ FAIL | <1s |
|
|
137
|
+
| Conversation | 5 | ❌ FAIL | <1s |
|
|
138
|
+
| Skip Tracking | 4 | ❌ FAIL | <1s |
|
|
139
|
+
| Templates | 6 | ❌ FAIL | <1s |
|
|
140
|
+
| Hot-Reload | 4 | ❌ FAIL | <1s |
|
|
141
|
+
| Integration | 3 | ❌ FAIL | <1s |
|
|
142
|
+
| Edge Cases | 7 | ❌ FAIL | <2s |
|
|
143
|
+
| Performance | 4 | ❌ FAIL | <5s |
|
|
144
|
+
| **TOTAL** | **~67** | **❌ ALL FAIL** | **<20s** |
|
|
145
|
+
|
|
146
|
+
## Debugging Failed Tests
|
|
147
|
+
|
|
148
|
+
### Identify Which Tests Failed
|
|
149
|
+
```bash
|
|
150
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py \
|
|
151
|
+
--tb=short # Short traceback
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### See Detailed Error
|
|
155
|
+
```bash
|
|
156
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py::TestYamlParsing::test_valid_yaml_structure_parses_successfully \
|
|
157
|
+
-vv --tb=long
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### See Test Setup and Fixtures
|
|
161
|
+
```bash
|
|
162
|
+
pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py \
|
|
163
|
+
--setup-show
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Implementation Checklist
|
|
167
|
+
|
|
168
|
+
Use this checklist when implementing to ensure all requirements met:
|
|
169
|
+
|
|
170
|
+
- [ ] FeedbackConfiguration dataclass created
|
|
171
|
+
- [ ] ConversationSettings dataclass created
|
|
172
|
+
- [ ] SkipTrackingSettings dataclass created
|
|
173
|
+
- [ ] TemplateSettings dataclass created
|
|
174
|
+
- [ ] TriggerMode enum defined
|
|
175
|
+
- [ ] TemplateFormat enum defined
|
|
176
|
+
- [ ] TemplateTone enum defined
|
|
177
|
+
- [ ] YAML parser implemented
|
|
178
|
+
- [ ] Configuration loader implemented with defaults
|
|
179
|
+
- [ ] Validation logic for all 10 fields
|
|
180
|
+
- [ ] Master enable/disable control
|
|
181
|
+
- [ ] Trigger mode filtering
|
|
182
|
+
- [ ] Question limit tracking
|
|
183
|
+
- [ ] Skip tracking with atomic counter
|
|
184
|
+
- [ ] Hot-reload with file watcher
|
|
185
|
+
- [ ] Error logging
|
|
186
|
+
- [ ] Performance optimization (<100ms load)
|
|
187
|
+
|
|
188
|
+
## CI/CD Integration
|
|
189
|
+
|
|
190
|
+
### GitHub Actions Example
|
|
191
|
+
```yaml
|
|
192
|
+
name: Test STORY-011
|
|
193
|
+
|
|
194
|
+
on: [push, pull_request]
|
|
195
|
+
|
|
196
|
+
jobs:
|
|
197
|
+
test:
|
|
198
|
+
runs-on: ubuntu-latest
|
|
199
|
+
steps:
|
|
200
|
+
- uses: actions/checkout@v2
|
|
201
|
+
- uses: actions/setup-python@v2
|
|
202
|
+
with:
|
|
203
|
+
python-version: '3.9'
|
|
204
|
+
- run: pip install -r requirements.txt
|
|
205
|
+
- run: pytest .claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py --cov --cov-report=xml
|
|
206
|
+
- uses: codecov/codecov-action@v2
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Expected Test Behavior
|
|
210
|
+
|
|
211
|
+
### During Development
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
# Initial run (Red phase)
|
|
215
|
+
$ pytest test_configuration_management.py
|
|
216
|
+
FAILED ❌ test_valid_yaml_structure_parses_successfully - No such file
|
|
217
|
+
FAILED ❌ test_enabled_true_allows_feedback_collection - AttributeError
|
|
218
|
+
FAILED ❌ test_trigger_mode_always_triggers_unconditionally - NameError
|
|
219
|
+
...
|
|
220
|
+
========== 67 failed in 0.34s ===========
|
|
221
|
+
|
|
222
|
+
# After implementation (Green phase)
|
|
223
|
+
$ pytest test_configuration_management.py
|
|
224
|
+
PASSED ✅ test_valid_yaml_structure_parses_successfully
|
|
225
|
+
PASSED ✅ test_enabled_true_allows_feedback_collection
|
|
226
|
+
PASSED ✅ test_trigger_mode_always_triggers_unconditionally
|
|
227
|
+
...
|
|
228
|
+
========== 67 passed in 1.89s ===========
|
|
229
|
+
|
|
230
|
+
# After refactoring (Refactor phase - should still pass)
|
|
231
|
+
$ pytest test_configuration_management.py --cov
|
|
232
|
+
PASSED ✅ test_valid_yaml_structure_parses_successfully
|
|
233
|
+
PASSED ✅ test_enabled_true_allows_feedback_collection
|
|
234
|
+
PASSED ✅ test_trigger_mode_always_triggers_unconditionally
|
|
235
|
+
...
|
|
236
|
+
========== 67 passed in 1.92s ===========
|
|
237
|
+
Coverage: 96% ✅
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Troubleshooting
|
|
241
|
+
|
|
242
|
+
### Issue: "ModuleNotFoundError: No module named 'pytest'"
|
|
243
|
+
**Solution:** `pip install pytest`
|
|
244
|
+
|
|
245
|
+
### Issue: "ModuleNotFoundError: No module named 'yaml'"
|
|
246
|
+
**Solution:** `pip install pyyaml`
|
|
247
|
+
|
|
248
|
+
### Issue: Tests timeout
|
|
249
|
+
**Solution:** Increase timeout: `pytest --timeout=10`
|
|
250
|
+
|
|
251
|
+
### Issue: Permission errors on temp files
|
|
252
|
+
**Solution:** Ensure temp directory is writable: `chmod 777 /tmp`
|
|
253
|
+
|
|
254
|
+
### Issue: Cannot create temp directory
|
|
255
|
+
**Solution:** Check disk space: `df -h`
|
|
256
|
+
|
|
257
|
+
## Test Metrics
|
|
258
|
+
|
|
259
|
+
### Test File Statistics
|
|
260
|
+
- **Total Lines:** 1,338
|
|
261
|
+
- **Test Classes:** 12
|
|
262
|
+
- **Test Methods:** 67+
|
|
263
|
+
- **Parametrized Tests:** 5 functions with multiple parameters
|
|
264
|
+
- **Documentation Lines:** 200+
|
|
265
|
+
- **Code Lines:** 900+
|
|
266
|
+
|
|
267
|
+
### Coverage Targets
|
|
268
|
+
- Acceptance Criteria: 100% (9/9 ACs tested)
|
|
269
|
+
- Data Fields: 100% (10/10 fields tested)
|
|
270
|
+
- Edge Cases: 100% (7/7 cases tested)
|
|
271
|
+
- Business Logic: >95%
|
|
272
|
+
|
|
273
|
+
### Execution Metrics
|
|
274
|
+
- **Total Test Time:** <20 seconds
|
|
275
|
+
- **Average Test:** <150ms
|
|
276
|
+
- **Slowest Test:** ~5s (performance tests intentional)
|
|
277
|
+
- **Fastest Test:** <1ms (mocked operations)
|
|
278
|
+
|
|
279
|
+
## References
|
|
280
|
+
|
|
281
|
+
- [pytest Documentation](https://docs.pytest.org/)
|
|
282
|
+
- [Test Summary Report](./STORY-011-test-generation-summary.md)
|
|
283
|
+
- [Configuration Management Story](../../../devforgeai/specs/Stories/STORY-011-configuration-management.story.md)
|
|
284
|
+
- [DevForgeAI Framework](../../../CLAUDE.md)
|
|
285
|
+
|
|
286
|
+
## Contact & Support
|
|
287
|
+
|
|
288
|
+
For test-related questions:
|
|
289
|
+
1. Review test docstrings (explain purpose)
|
|
290
|
+
2. Check test comments (explain setup)
|
|
291
|
+
3. Review the test summary document
|
|
292
|
+
4. Check the story acceptance criteria
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
**Ready for Green Phase Implementation!** 🚀
|
|
297
|
+
|
|
298
|
+
All 67 tests are ready to guide implementation of STORY-011.
|