devforgeai 1.0.5 → 1.0.7
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/bin/devforgeai.js +0 -0
- package/package.json +9 -1
- package/src/CLAUDE.md +699 -0
- package/src/claude/hooks/phase-completion-gate.sh +0 -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/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,344 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Lightweight Deferral Format Validator (Hybrid Approach - Layer 1)
|
|
4
|
+
|
|
5
|
+
Quick format validation for deferred Definition of Done items.
|
|
6
|
+
Part of three-layer defense architecture:
|
|
7
|
+
- Layer 1 (this script): Fast format validation (~200 tokens, <100ms)
|
|
8
|
+
- Layer 2 (task file): Interactive user approval checkpoint
|
|
9
|
+
- Layer 3 (subagent): Comprehensive AI analysis (feasibility, circular deps)
|
|
10
|
+
|
|
11
|
+
This script provides FAST FEEDBACK by catching basic format errors instantly,
|
|
12
|
+
allowing comprehensive validation to be handled by AI subagent (deferral-validator).
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
# Format-only validation (non-blocking warnings)
|
|
16
|
+
python validate_deferrals.py --story-file STORY-006.story.md --format-only
|
|
17
|
+
|
|
18
|
+
# Quiet mode (for automation)
|
|
19
|
+
python validate_deferrals.py --story-file STORY-006.story.md --quiet
|
|
20
|
+
|
|
21
|
+
Exit Codes:
|
|
22
|
+
0 - Format valid OR warnings only (format-only mode)
|
|
23
|
+
1 - Format invalid (strict mode, not used in hybrid approach)
|
|
24
|
+
2 - Configuration error (file not found, parse error)
|
|
25
|
+
|
|
26
|
+
Design Philosophy:
|
|
27
|
+
- Simple and fast (regex pattern matching only)
|
|
28
|
+
- Non-blocking in hybrid architecture (warnings, not errors)
|
|
29
|
+
- Delegates complex analysis to deferral-validator subagent
|
|
30
|
+
- Follows DevForgeAI validation script patterns (Color class, argparse)
|
|
31
|
+
|
|
32
|
+
Related:
|
|
33
|
+
- RCA-006 Recommendation 3 (automated validation)
|
|
34
|
+
- Native Tools Efficiency Analysis (40-73% token savings)
|
|
35
|
+
- .claude/agents/deferral-validator.md (comprehensive validation)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
import argparse
|
|
39
|
+
import re
|
|
40
|
+
import sys
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
from typing import List, Tuple
|
|
43
|
+
from dataclasses import dataclass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Color:
|
|
47
|
+
"""
|
|
48
|
+
ANSI color codes for terminal output.
|
|
49
|
+
|
|
50
|
+
Pattern from DevForgeAI framework validation scripts:
|
|
51
|
+
- .claude/skills/designing-systems/scripts/validate_all_context.py
|
|
52
|
+
- .claude/skills/devforgeai-qa/scripts/security_scan.py
|
|
53
|
+
"""
|
|
54
|
+
RED = '\033[91m'
|
|
55
|
+
GREEN = '\033[92m'
|
|
56
|
+
YELLOW = '\033[93m'
|
|
57
|
+
BLUE = '\033[94m'
|
|
58
|
+
CYAN = '\033[96m'
|
|
59
|
+
BOLD = '\033[1m'
|
|
60
|
+
END = '\033[0m'
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class DoDItem:
|
|
65
|
+
"""
|
|
66
|
+
Definition of Done item from story file.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
text: Item description text
|
|
70
|
+
line_num: Line number in DoD section (1-indexed)
|
|
71
|
+
context: Next 3 lines after item (for justification detection)
|
|
72
|
+
"""
|
|
73
|
+
text: str
|
|
74
|
+
line_num: int
|
|
75
|
+
context: str
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class FormatValidator:
|
|
79
|
+
"""
|
|
80
|
+
Lightweight format validator for deferral justifications.
|
|
81
|
+
|
|
82
|
+
Validates ONLY format compliance:
|
|
83
|
+
- Incomplete items have justification text
|
|
84
|
+
- Justification matches expected patterns
|
|
85
|
+
|
|
86
|
+
Does NOT validate (delegated to deferral-validator subagent):
|
|
87
|
+
- Story references exist (AI checks file system)
|
|
88
|
+
- ADR references exist (AI checks file system)
|
|
89
|
+
- Circular deferrals (AI analyzes chains)
|
|
90
|
+
- Implementation feasibility (AI analyzes tech spec)
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# Valid deferral patterns (case-insensitive)
|
|
94
|
+
VALID_PATTERNS = [
|
|
95
|
+
r'Deferred to STORY-\d+:', # Story split deferral
|
|
96
|
+
r'Blocked by:', # External blocker
|
|
97
|
+
r'Out of scope: ADR-\d+' # Scope change with ADR
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
def __init__(self, story_file: Path):
|
|
101
|
+
"""
|
|
102
|
+
Initialize validator.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
story_file: Path to story markdown file
|
|
106
|
+
"""
|
|
107
|
+
self.story_file = story_file
|
|
108
|
+
|
|
109
|
+
def validate(self) -> Tuple[bool, List[str]]:
|
|
110
|
+
"""
|
|
111
|
+
Run format validation.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Tuple of (is_valid, violations_list)
|
|
115
|
+
- is_valid: True if all incomplete items have valid format
|
|
116
|
+
- violations_list: List of violation messages (empty if valid)
|
|
117
|
+
"""
|
|
118
|
+
# Step 1: Read story file
|
|
119
|
+
story_content = self._read_story()
|
|
120
|
+
|
|
121
|
+
# Step 2: Extract DoD section
|
|
122
|
+
dod_section = self._extract_dod_section(story_content)
|
|
123
|
+
|
|
124
|
+
if not dod_section:
|
|
125
|
+
# No DoD section found - unusual but not an error for this script
|
|
126
|
+
# (Comprehensive validation in subagent will catch this)
|
|
127
|
+
return True, []
|
|
128
|
+
|
|
129
|
+
# Step 3: Extract incomplete items
|
|
130
|
+
incomplete_items = self._extract_incomplete_items(dod_section)
|
|
131
|
+
|
|
132
|
+
if not incomplete_items:
|
|
133
|
+
# All items complete - valid
|
|
134
|
+
return True, []
|
|
135
|
+
|
|
136
|
+
# Step 4: Check format for each incomplete item
|
|
137
|
+
violations = []
|
|
138
|
+
for item in incomplete_items:
|
|
139
|
+
if not self._has_valid_format(item):
|
|
140
|
+
violations.append(
|
|
141
|
+
f"Line {item.line_num}: '{self._truncate(item.text, 60)}'\n"
|
|
142
|
+
f" Missing justification. Expected one of:\n"
|
|
143
|
+
f" - Deferred to STORY-XXX: [reason]\n"
|
|
144
|
+
f" - Blocked by: [external dependency]\n"
|
|
145
|
+
f" - Out of scope: ADR-XXX"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
is_valid = len(violations) == 0
|
|
149
|
+
return is_valid, violations
|
|
150
|
+
|
|
151
|
+
def _read_story(self) -> str:
|
|
152
|
+
"""
|
|
153
|
+
Read story file content using Python stdlib.
|
|
154
|
+
|
|
155
|
+
Note: Uses Python file I/O (not Bash cat) per native tools efficiency guidance.
|
|
156
|
+
While this script is invoked via Bash, it uses Python stdlib internally,
|
|
157
|
+
which is equivalent to native tool efficiency.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Story file content as string
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
SystemExit(2): If file not found or read error
|
|
164
|
+
"""
|
|
165
|
+
try:
|
|
166
|
+
with open(self.story_file, 'r', encoding='utf-8') as f:
|
|
167
|
+
return f.read()
|
|
168
|
+
except FileNotFoundError:
|
|
169
|
+
print(
|
|
170
|
+
f"{Color.RED}ERROR: Story file not found: {self.story_file}{Color.END}",
|
|
171
|
+
file=sys.stderr
|
|
172
|
+
)
|
|
173
|
+
sys.exit(2)
|
|
174
|
+
except Exception as e:
|
|
175
|
+
print(
|
|
176
|
+
f"{Color.RED}ERROR reading file: {e}{Color.END}",
|
|
177
|
+
file=sys.stderr
|
|
178
|
+
)
|
|
179
|
+
sys.exit(2)
|
|
180
|
+
|
|
181
|
+
def _extract_dod_section(self, content: str) -> str:
|
|
182
|
+
"""
|
|
183
|
+
Extract Definition of Done section from story content.
|
|
184
|
+
|
|
185
|
+
Searches for markdown section between:
|
|
186
|
+
- Start: ## Definition of Done
|
|
187
|
+
- End: Next ## heading (or end of file)
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
content: Full story file content
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
DoD section content (empty string if not found)
|
|
194
|
+
"""
|
|
195
|
+
# Match DoD section (until next ## heading)
|
|
196
|
+
match = re.search(
|
|
197
|
+
r'## Definition of Done\n(.*?)(?:\n## |\Z)',
|
|
198
|
+
content,
|
|
199
|
+
re.DOTALL
|
|
200
|
+
)
|
|
201
|
+
return match.group(1).strip() if match else ""
|
|
202
|
+
|
|
203
|
+
def _extract_incomplete_items(self, dod_section: str) -> List[DoDItem]:
|
|
204
|
+
"""
|
|
205
|
+
Extract all incomplete (- [ ]) items with context.
|
|
206
|
+
|
|
207
|
+
Each item includes the next 3 lines as context for justification detection.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
dod_section: Definition of Done section content
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
List of DoDItem objects for incomplete items
|
|
214
|
+
"""
|
|
215
|
+
lines = dod_section.split('\n')
|
|
216
|
+
items = []
|
|
217
|
+
|
|
218
|
+
for i, line in enumerate(lines):
|
|
219
|
+
if line.strip().startswith('- [ ]'):
|
|
220
|
+
# Extract item text (after "- [ ]" marker)
|
|
221
|
+
text = line.strip()[6:].strip()
|
|
222
|
+
|
|
223
|
+
# Get next 3 lines as context (for justification detection)
|
|
224
|
+
context_lines = lines[i+1:min(i+4, len(lines))]
|
|
225
|
+
context = '\n'.join(context_lines)
|
|
226
|
+
|
|
227
|
+
items.append(DoDItem(
|
|
228
|
+
text=text,
|
|
229
|
+
line_num=i+1,
|
|
230
|
+
context=context
|
|
231
|
+
))
|
|
232
|
+
|
|
233
|
+
return items
|
|
234
|
+
|
|
235
|
+
def _has_valid_format(self, item: DoDItem) -> bool:
|
|
236
|
+
"""
|
|
237
|
+
Check if item has valid deferral justification format.
|
|
238
|
+
|
|
239
|
+
Valid formats (in context lines following item):
|
|
240
|
+
- "Deferred to STORY-XXX: [reason]"
|
|
241
|
+
- "Blocked by: [external dependency]"
|
|
242
|
+
- "Out of scope: ADR-XXX"
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
item: DoDItem to validate
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
True if valid format found in context, False otherwise
|
|
249
|
+
"""
|
|
250
|
+
for pattern in self.VALID_PATTERNS:
|
|
251
|
+
if re.search(pattern, item.context, re.IGNORECASE):
|
|
252
|
+
return True
|
|
253
|
+
return False
|
|
254
|
+
|
|
255
|
+
@staticmethod
|
|
256
|
+
def _truncate(text: str, max_len: int) -> str:
|
|
257
|
+
"""Truncate text to max length with ellipsis."""
|
|
258
|
+
return text if len(text) <= max_len else text[:max_len] + "..."
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def main():
|
|
262
|
+
"""Main entry point for validation script."""
|
|
263
|
+
parser = argparse.ArgumentParser(
|
|
264
|
+
description="Lightweight deferral format validator (Hybrid Approach - Layer 1)",
|
|
265
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
266
|
+
epilog="""
|
|
267
|
+
Examples:
|
|
268
|
+
# Format-only validation (non-blocking)
|
|
269
|
+
python validate_deferrals.py --story-file devforgeai/specs/Stories/STORY-006.story.md --format-only
|
|
270
|
+
|
|
271
|
+
# Quiet mode (automation/git hooks)
|
|
272
|
+
python validate_deferrals.py --story-file devforgeai/specs/Stories/STORY-006.story.md --quiet
|
|
273
|
+
|
|
274
|
+
Exit Codes:
|
|
275
|
+
0 - Validation passed (or warnings only in format-only mode)
|
|
276
|
+
1 - Validation failed (strict mode, not used in hybrid architecture)
|
|
277
|
+
2 - Configuration error (file not found, parse error)
|
|
278
|
+
|
|
279
|
+
Integration:
|
|
280
|
+
- Invoked by /dev command Phase 2.5a (Layer 1 quick check)
|
|
281
|
+
- Followed by interactive checkpoint (Layer 2)
|
|
282
|
+
- Followed by deferral-validator subagent (Layer 3)
|
|
283
|
+
"""
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
parser.add_argument(
|
|
287
|
+
"--story-file",
|
|
288
|
+
type=Path,
|
|
289
|
+
required=True,
|
|
290
|
+
help="Path to story file to validate (devforgeai/specs/Stories/STORY-XXX.story.md)"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
parser.add_argument(
|
|
294
|
+
"--format-only",
|
|
295
|
+
action="store_true",
|
|
296
|
+
help="Only validate format (non-blocking, always exit 0 with warnings)"
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
parser.add_argument(
|
|
300
|
+
"--quiet",
|
|
301
|
+
action="store_true",
|
|
302
|
+
help="Suppress output (only return exit code)"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
args = parser.parse_args()
|
|
306
|
+
|
|
307
|
+
# Validate story file exists (early check)
|
|
308
|
+
if not args.story_file.exists():
|
|
309
|
+
if not args.quiet:
|
|
310
|
+
print(
|
|
311
|
+
f"{Color.RED}ERROR: Story file not found: {args.story_file}{Color.END}",
|
|
312
|
+
file=sys.stderr
|
|
313
|
+
)
|
|
314
|
+
sys.exit(2)
|
|
315
|
+
|
|
316
|
+
# Run validation
|
|
317
|
+
validator = FormatValidator(args.story_file)
|
|
318
|
+
is_valid, violations = validator.validate()
|
|
319
|
+
|
|
320
|
+
# Display results (unless quiet mode)
|
|
321
|
+
if not args.quiet:
|
|
322
|
+
if is_valid:
|
|
323
|
+
print(f"{Color.GREEN}✓ Deferral format validation PASSED{Color.END}")
|
|
324
|
+
print(f" All incomplete DoD items have basic justification format")
|
|
325
|
+
else:
|
|
326
|
+
print(f"{Color.YELLOW}⚠️ Format issues detected ({len(violations)} items){Color.END}\n")
|
|
327
|
+
for violation in violations:
|
|
328
|
+
print(f"{Color.YELLOW}{violation}{Color.END}\n")
|
|
329
|
+
|
|
330
|
+
if args.format_only:
|
|
331
|
+
print(f"{Color.CYAN}Note: Format-only mode - warnings only (non-blocking){Color.END}")
|
|
332
|
+
print(f"{Color.CYAN}Interactive checkpoint will guide you through resolution.{Color.END}")
|
|
333
|
+
|
|
334
|
+
# Exit code handling
|
|
335
|
+
if args.format_only:
|
|
336
|
+
# Format-only mode: Always exit 0 (warnings only, non-blocking)
|
|
337
|
+
sys.exit(0)
|
|
338
|
+
else:
|
|
339
|
+
# Strict mode: Exit 1 on violations (not used in hybrid approach)
|
|
340
|
+
sys.exit(0 if is_valid else 1)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
if __name__ == "__main__":
|
|
344
|
+
main()
|
package/src/claude/skills/designing-systems/scripts/__pycache__/detect_anti_patterns.cpython-312.pyc
DELETED
|
Binary file
|
package/src/claude/skills/designing-systems/scripts/__pycache__/validate_all_context.cpython-312.pyc
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|