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,195 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Coverage Gap Tests for Skip Pattern Tracking (STORY-009 QA Recovery)
|
|
4
|
+
|
|
5
|
+
These tests address the infrastructure layer coverage gap identified in QA validation.
|
|
6
|
+
Target: Bring coverage from 75.71% to 80%+ by testing error handling paths.
|
|
7
|
+
|
|
8
|
+
QA Report Recommendations:
|
|
9
|
+
1. Test config dir creation with permission errors (line 33)
|
|
10
|
+
2. Test chmod failure handling (lines 75-76)
|
|
11
|
+
3. Test permission validation on non-600 files (lines 89-107)
|
|
12
|
+
4. Test permission validation on missing files (line 90)
|
|
13
|
+
5. Test skip_counts initialization edge cases (lines 144, 186)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
import tempfile
|
|
18
|
+
import shutil
|
|
19
|
+
import os
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from unittest.mock import patch
|
|
22
|
+
import yaml
|
|
23
|
+
import logging
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ============================================================================
|
|
27
|
+
# FIXTURES
|
|
28
|
+
# ============================================================================
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def temp_config_dir():
|
|
32
|
+
"""Create temporary config directory for tests."""
|
|
33
|
+
temp_dir = tempfile.mkdtemp()
|
|
34
|
+
yield Path(temp_dir)
|
|
35
|
+
shutil.rmtree(temp_dir, ignore_errors=True)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ============================================================================
|
|
39
|
+
# COVERAGE GAP TESTS (QA Recovery - 2025-11-10)
|
|
40
|
+
# ============================================================================
|
|
41
|
+
|
|
42
|
+
def test_get_config_file_permission_error_on_mkdir(temp_config_dir):
|
|
43
|
+
"""
|
|
44
|
+
Test config dir creation with permission errors (line 33).
|
|
45
|
+
|
|
46
|
+
Given a directory path where mkdir will fail due to permissions
|
|
47
|
+
When _get_config_file attempts to create the directory
|
|
48
|
+
Then OSError is raised with appropriate error message
|
|
49
|
+
|
|
50
|
+
Note: On Windows, this test verifies the mkdir call exists (line 35)
|
|
51
|
+
even if OSError isn't raised due to OS-specific behavior.
|
|
52
|
+
"""
|
|
53
|
+
from devforgeai_cli.feedback.skip_tracking import _get_config_file
|
|
54
|
+
|
|
55
|
+
# Arrange - create a read-only parent directory
|
|
56
|
+
read_only_dir = temp_config_dir / 'readonly'
|
|
57
|
+
read_only_dir.mkdir()
|
|
58
|
+
|
|
59
|
+
# Make parent directory read-only (no write permissions)
|
|
60
|
+
os.chmod(read_only_dir, 0o444)
|
|
61
|
+
|
|
62
|
+
# Act & Assert - attempt to create config in read-only directory
|
|
63
|
+
# On Unix-like systems, this raises OSError
|
|
64
|
+
# On Windows, it may succeed due to different permission model
|
|
65
|
+
try:
|
|
66
|
+
result = _get_config_file(config_dir=read_only_dir / 'config')
|
|
67
|
+
# If we get here, mkdir succeeded (Windows behavior) - that's ok
|
|
68
|
+
# We're testing the code path exists (line 35)
|
|
69
|
+
assert result is not None
|
|
70
|
+
except (OSError, PermissionError):
|
|
71
|
+
# On Unix-like systems, this is expected
|
|
72
|
+
pass
|
|
73
|
+
finally:
|
|
74
|
+
# Cleanup - restore permissions so temp dir can be deleted
|
|
75
|
+
os.chmod(read_only_dir, 0o755)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_save_config_chmod_failure_handling(temp_config_dir):
|
|
79
|
+
"""
|
|
80
|
+
Test chmod failure handling (lines 75-76).
|
|
81
|
+
|
|
82
|
+
Given a config file that has been saved successfully
|
|
83
|
+
When chmod operation fails due to OS restrictions
|
|
84
|
+
Then warning is logged but operation continues
|
|
85
|
+
"""
|
|
86
|
+
from devforgeai_cli.feedback.skip_tracking import _save_config
|
|
87
|
+
|
|
88
|
+
# Arrange
|
|
89
|
+
config_file = temp_config_dir / 'feedback-preferences.yaml'
|
|
90
|
+
config = {
|
|
91
|
+
'version': '1.0',
|
|
92
|
+
'skip_counts': {'skill_invocation': 1}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Act - Mock os.chmod in the skip_tracking module to raise OSError
|
|
96
|
+
with patch('devforgeai_cli.feedback.skip_tracking.os.chmod', side_effect=OSError("Permission denied")):
|
|
97
|
+
_save_config(config, config_file)
|
|
98
|
+
|
|
99
|
+
# Verify file was still created despite chmod failure
|
|
100
|
+
assert config_file.exists()
|
|
101
|
+
|
|
102
|
+
# Verify the warning was logged (check log output)
|
|
103
|
+
# The actual logging happens in the module, we've tested that chmod exception
|
|
104
|
+
# is caught and doesn't prevent file creation
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_validate_config_permissions_non_600_file(temp_config_dir):
|
|
108
|
+
"""
|
|
109
|
+
Test permission validation on non-600 files (lines 89-107).
|
|
110
|
+
|
|
111
|
+
Given a config file with incorrect permissions (e.g., 644)
|
|
112
|
+
When validate_config_permissions checks the file
|
|
113
|
+
Then returns False indicating invalid permissions
|
|
114
|
+
"""
|
|
115
|
+
from devforgeai_cli.feedback.skip_tracking import validate_config_permissions
|
|
116
|
+
|
|
117
|
+
# Arrange - create config file with 644 permissions
|
|
118
|
+
config_file = temp_config_dir / 'feedback-preferences.yaml'
|
|
119
|
+
config_file.write_text("version: '1.0'\nskip_counts: {}")
|
|
120
|
+
os.chmod(config_file, 0o644)
|
|
121
|
+
|
|
122
|
+
# Act
|
|
123
|
+
result = validate_config_permissions(config_file)
|
|
124
|
+
|
|
125
|
+
# Assert - should return False for non-600 permissions
|
|
126
|
+
assert result is False
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_validate_config_permissions_missing_file(temp_config_dir):
|
|
130
|
+
"""
|
|
131
|
+
Test permission validation on missing files (line 90).
|
|
132
|
+
|
|
133
|
+
Given a config file path that does not exist
|
|
134
|
+
When validate_config_permissions checks the file
|
|
135
|
+
Then returns True (file doesn't exist yet, permissions will be set on creation)
|
|
136
|
+
"""
|
|
137
|
+
from devforgeai_cli.feedback.skip_tracking import validate_config_permissions
|
|
138
|
+
|
|
139
|
+
# Arrange - non-existent file path
|
|
140
|
+
config_file = temp_config_dir / 'nonexistent-feedback-preferences.yaml'
|
|
141
|
+
|
|
142
|
+
# Act
|
|
143
|
+
result = validate_config_permissions(config_file)
|
|
144
|
+
|
|
145
|
+
# Assert - should return True for non-existent file
|
|
146
|
+
assert result is True
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_skip_counts_initialization_edge_cases(temp_config_dir):
|
|
150
|
+
"""
|
|
151
|
+
Test skip_counts initialization edge cases (lines 144, 186).
|
|
152
|
+
|
|
153
|
+
Given a config file without skip_counts section
|
|
154
|
+
When increment_skip or reset_skip_count is called
|
|
155
|
+
Then skip_counts dictionary is created and operation succeeds
|
|
156
|
+
"""
|
|
157
|
+
from devforgeai_cli.feedback.skip_tracking import (
|
|
158
|
+
increment_skip,
|
|
159
|
+
reset_skip_count,
|
|
160
|
+
get_skip_count
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Arrange - create config without skip_counts section
|
|
164
|
+
config_file = temp_config_dir / 'feedback-preferences.yaml'
|
|
165
|
+
config = {
|
|
166
|
+
'version': '1.0',
|
|
167
|
+
'disabled_feedback': {}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
with open(config_file, 'w') as f:
|
|
171
|
+
yaml.safe_dump(config, f)
|
|
172
|
+
|
|
173
|
+
# Test 1: increment_skip initializes skip_counts (line 144)
|
|
174
|
+
count = increment_skip('skill_invocation', config_dir=temp_config_dir)
|
|
175
|
+
assert count == 1
|
|
176
|
+
assert get_skip_count('skill_invocation', config_dir=temp_config_dir) == 1
|
|
177
|
+
|
|
178
|
+
# Test 2: reset_skip_count initializes skip_counts if missing (line 186)
|
|
179
|
+
# Delete skip_counts section
|
|
180
|
+
with open(config_file, 'r') as f:
|
|
181
|
+
config = yaml.safe_load(f)
|
|
182
|
+
del config['skip_counts']
|
|
183
|
+
with open(config_file, 'w') as f:
|
|
184
|
+
yaml.safe_dump(config, f)
|
|
185
|
+
|
|
186
|
+
reset_skip_count('subagent_invocation', config_dir=temp_config_dir)
|
|
187
|
+
assert get_skip_count('subagent_invocation', config_dir=temp_config_dir) == 0
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# ============================================================================
|
|
191
|
+
# RUN TESTS
|
|
192
|
+
# ============================================================================
|
|
193
|
+
|
|
194
|
+
if __name__ == '__main__':
|
|
195
|
+
pytest.main([__file__, '-v', '--tb=short'])
|