specpulse 1.2.1__py3-none-any.whl → 1.2.3__py3-none-any.whl
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.
- specpulse/__init__.py +1 -1
- specpulse/cli/main.py +37 -0
- specpulse/core/validator.py +175 -2
- specpulse/resources/commands/claude/sp-decompose.md +1 -1
- specpulse/resources/commands/claude/sp-plan.md +6 -17
- specpulse/resources/commands/claude/sp-pulse.md +3 -5
- specpulse/resources/commands/claude/sp-spec.md +5 -12
- specpulse/resources/commands/claude/sp-task.md +9 -29
- specpulse/resources/commands/gemini/sp-plan.toml +4 -6
- specpulse/resources/commands/gemini/sp-pulse.toml +2 -3
- specpulse/resources/commands/gemini/sp-spec.toml +4 -6
- specpulse/resources/commands/gemini/sp-task.toml +6 -9
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/METADATA +9 -13
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/RECORD +18 -23
- specpulse/resources/scripts/sp-pulse-decompose.py +0 -66
- specpulse/resources/scripts/sp-pulse-init.py +0 -171
- specpulse/resources/scripts/sp-pulse-plan.py +0 -216
- specpulse/resources/scripts/sp-pulse-spec.py +0 -187
- specpulse/resources/scripts/sp-pulse-task.py +0 -273
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/WHEEL +0 -0
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/entry_points.txt +0 -0
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/licenses/LICENSE +0 -0
- {specpulse-1.2.1.dist-info → specpulse-1.2.3.dist-info}/top_level.txt +0 -0
specpulse/__init__.py
CHANGED
specpulse/cli/main.py
CHANGED
@@ -31,6 +31,13 @@ class SpecPulseCLI:
|
|
31
31
|
template: str = "web"):
|
32
32
|
"""Initialize SpecPulse in an existing or new project"""
|
33
33
|
|
34
|
+
# Validate project name for invalid characters
|
35
|
+
import re
|
36
|
+
if project_name and not here:
|
37
|
+
if not re.match(r'^[a-zA-Z0-9_-]+$', project_name):
|
38
|
+
self.console.error(f"Project name contains invalid characters: {project_name}")
|
39
|
+
return False
|
40
|
+
|
34
41
|
if here:
|
35
42
|
project_path = Path.cwd()
|
36
43
|
project_name = project_path.name
|
@@ -620,6 +627,13 @@ graph LR
|
|
620
627
|
project_path = Path.cwd()
|
621
628
|
sync_items = []
|
622
629
|
|
630
|
+
# Create missing directories if they don't exist
|
631
|
+
for dir_name in ["specs", "plans", "tasks", "memory", "templates", "scripts"]:
|
632
|
+
dir_path = project_path / dir_name
|
633
|
+
if not dir_path.exists():
|
634
|
+
dir_path.mkdir(parents=True, exist_ok=True)
|
635
|
+
sync_items.append((dir_name, "Created"))
|
636
|
+
|
623
637
|
self.console.spinner("Synchronizing project state")
|
624
638
|
import time
|
625
639
|
|
@@ -657,6 +671,29 @@ graph LR
|
|
657
671
|
|
658
672
|
return True
|
659
673
|
|
674
|
+
def list_specs(self):
|
675
|
+
"""List all specifications in the project"""
|
676
|
+
specs_dir = Path("specs")
|
677
|
+
if not specs_dir.exists():
|
678
|
+
self.console.warning("No specs directory found")
|
679
|
+
return []
|
680
|
+
|
681
|
+
spec_files = []
|
682
|
+
for feature_dir in specs_dir.iterdir():
|
683
|
+
if feature_dir.is_dir():
|
684
|
+
for spec_file in feature_dir.glob("spec-*.md"):
|
685
|
+
spec_files.append(spec_file)
|
686
|
+
|
687
|
+
if not spec_files:
|
688
|
+
self.console.warning("No specifications found")
|
689
|
+
return []
|
690
|
+
|
691
|
+
self.console.info(f"Found {len(spec_files)} specifications")
|
692
|
+
for spec_file in spec_files:
|
693
|
+
self.console.info(f" - {spec_file.relative_to(specs_dir)}")
|
694
|
+
|
695
|
+
return spec_files
|
696
|
+
|
660
697
|
def doctor(self):
|
661
698
|
"""System check and diagnostics"""
|
662
699
|
self.console.show_banner(mini=True)
|
specpulse/core/validator.py
CHANGED
@@ -11,8 +11,13 @@ import re
|
|
11
11
|
class Validator:
|
12
12
|
"""Validates SpecPulse project components"""
|
13
13
|
|
14
|
-
def __init__(self):
|
14
|
+
def __init__(self, project_root: Optional[Path] = None):
|
15
15
|
self.results = []
|
16
|
+
self.constitution = None
|
17
|
+
self.phase_gates = []
|
18
|
+
|
19
|
+
if project_root:
|
20
|
+
self._load_constitution(project_root)
|
16
21
|
|
17
22
|
def validate_all(self, project_path: Path, fix: bool = False, verbose: bool = False) -> List[Dict]:
|
18
23
|
"""Validate entire project"""
|
@@ -329,4 +334,172 @@ class Validator:
|
|
329
334
|
self.results.append({
|
330
335
|
"status": "warning",
|
331
336
|
"message": "Constitution enforcement disabled"
|
332
|
-
})
|
337
|
+
})
|
338
|
+
|
339
|
+
def _load_constitution(self, project_root: Path):
|
340
|
+
"""Load constitution from project"""
|
341
|
+
constitution_path = project_root / "memory" / "constitution.md"
|
342
|
+
if constitution_path.exists():
|
343
|
+
self.constitution = constitution_path.read_text()
|
344
|
+
# Extract phase gates from constitution
|
345
|
+
self._extract_phase_gates()
|
346
|
+
|
347
|
+
def _extract_phase_gates(self):
|
348
|
+
"""Extract phase gates from constitution"""
|
349
|
+
if not self.constitution:
|
350
|
+
return
|
351
|
+
|
352
|
+
# Simple extraction of phase gates from constitution text
|
353
|
+
gates = []
|
354
|
+
lines = self.constitution.split('\n')
|
355
|
+
for line in lines:
|
356
|
+
if 'Phase Gate' in line or 'phase gate' in line:
|
357
|
+
gates.append(line.strip())
|
358
|
+
self.phase_gates = gates
|
359
|
+
|
360
|
+
def load_constitution(self, project_root: Path) -> bool:
|
361
|
+
"""Load constitution from a project"""
|
362
|
+
self._load_constitution(project_root)
|
363
|
+
return self.constitution is not None
|
364
|
+
|
365
|
+
def validate_spec(self, spec_path: Path, verbose: bool = False) -> Dict:
|
366
|
+
"""Validate a single specification file"""
|
367
|
+
if not spec_path.exists():
|
368
|
+
return {"status": "error", "message": f"Spec file not found: {spec_path}"}
|
369
|
+
|
370
|
+
content = spec_path.read_text()
|
371
|
+
result = {"status": "valid", "issues": []}
|
372
|
+
|
373
|
+
# Check required sections
|
374
|
+
required_sections = ["## Requirements", "## User Stories", "## Acceptance Criteria"]
|
375
|
+
for section in required_sections:
|
376
|
+
if section not in content:
|
377
|
+
result["issues"].append(f"Missing section: {section}")
|
378
|
+
|
379
|
+
if result["issues"]:
|
380
|
+
result["status"] = "invalid"
|
381
|
+
|
382
|
+
return result
|
383
|
+
|
384
|
+
def validate_plan(self, plan_path: Path, verbose: bool = False) -> Dict:
|
385
|
+
"""Validate a single plan file"""
|
386
|
+
if not plan_path.exists():
|
387
|
+
return {"status": "error", "message": f"Plan file not found: {plan_path}"}
|
388
|
+
|
389
|
+
content = plan_path.read_text()
|
390
|
+
result = {"status": "valid", "issues": []}
|
391
|
+
|
392
|
+
# Check required sections
|
393
|
+
required_sections = ["## Architecture", "## Phases", "## Technology Stack"]
|
394
|
+
for section in required_sections:
|
395
|
+
if section not in content:
|
396
|
+
result["issues"].append(f"Missing section: {section}")
|
397
|
+
|
398
|
+
if result["issues"]:
|
399
|
+
result["status"] = "invalid"
|
400
|
+
|
401
|
+
return result
|
402
|
+
|
403
|
+
def validate_task(self, task_path: Path, verbose: bool = False) -> Dict:
|
404
|
+
"""Validate a single task file"""
|
405
|
+
if not task_path.exists():
|
406
|
+
return {"status": "error", "message": f"Task file not found: {task_path}"}
|
407
|
+
|
408
|
+
content = task_path.read_text()
|
409
|
+
result = {"status": "valid", "issues": []}
|
410
|
+
|
411
|
+
# Check for task format
|
412
|
+
if not re.search(r'T\d{3}', content):
|
413
|
+
result["issues"].append("No task IDs found (T001 format)")
|
414
|
+
|
415
|
+
if result["issues"]:
|
416
|
+
result["status"] = "invalid"
|
417
|
+
|
418
|
+
return result
|
419
|
+
|
420
|
+
def validate_constitution_compliance(self, spec_content: str, verbose: bool = False) -> Dict:
|
421
|
+
"""Validate that content complies with constitution"""
|
422
|
+
result = {"status": "compliant", "violations": []}
|
423
|
+
|
424
|
+
if not self.constitution:
|
425
|
+
return result
|
426
|
+
|
427
|
+
# Check for simplicity principle
|
428
|
+
if 'complexity' in spec_content.lower() and 'simple' not in spec_content.lower():
|
429
|
+
result["violations"].append("Simplicity principle: Complex solution without justification")
|
430
|
+
|
431
|
+
if result["violations"]:
|
432
|
+
result["status"] = "non-compliant"
|
433
|
+
|
434
|
+
return result
|
435
|
+
|
436
|
+
def check_phase_gate(self, gate_name: str, context: Dict) -> bool:
|
437
|
+
"""Check if a phase gate passes"""
|
438
|
+
# Simple gate checking logic
|
439
|
+
if gate_name == "simplicity":
|
440
|
+
return context.get("module_count", 0) <= 3
|
441
|
+
elif gate_name == "test-first":
|
442
|
+
return context.get("tests_written", False)
|
443
|
+
return True
|
444
|
+
|
445
|
+
def validate_all_project(self, project_root: Path, verbose: bool = False) -> Dict:
|
446
|
+
"""Validate entire project"""
|
447
|
+
results = {
|
448
|
+
"specs": [],
|
449
|
+
"plans": [],
|
450
|
+
"tasks": [],
|
451
|
+
"constitution_compliance": True
|
452
|
+
}
|
453
|
+
|
454
|
+
# Validate specs
|
455
|
+
specs_dir = project_root / "specs"
|
456
|
+
if specs_dir.exists():
|
457
|
+
for spec_file in specs_dir.glob("*/spec*.md"):
|
458
|
+
results["specs"].append(self.validate_spec(spec_file, verbose))
|
459
|
+
|
460
|
+
# Validate plans
|
461
|
+
plans_dir = project_root / "plans"
|
462
|
+
if plans_dir.exists():
|
463
|
+
for plan_file in plans_dir.glob("*/plan*.md"):
|
464
|
+
results["plans"].append(self.validate_plan(plan_file, verbose))
|
465
|
+
|
466
|
+
# Validate tasks
|
467
|
+
tasks_dir = project_root / "tasks"
|
468
|
+
if tasks_dir.exists():
|
469
|
+
for task_file in tasks_dir.glob("*/task*.md"):
|
470
|
+
results["tasks"].append(self.validate_task(task_file, verbose))
|
471
|
+
|
472
|
+
return results
|
473
|
+
|
474
|
+
def format_validation_report(self, results: Dict) -> str:
|
475
|
+
"""Format validation results as a report"""
|
476
|
+
report = "# Validation Report\n\n"
|
477
|
+
|
478
|
+
# Specs section
|
479
|
+
report += "## Specifications\n"
|
480
|
+
for spec in results.get("specs", []):
|
481
|
+
status = spec.get("status", "unknown")
|
482
|
+
report += f"- Status: {status}\n"
|
483
|
+
if spec.get("issues"):
|
484
|
+
for issue in spec["issues"]:
|
485
|
+
report += f" - Issue: {issue}\n"
|
486
|
+
|
487
|
+
# Plans section
|
488
|
+
report += "\n## Plans\n"
|
489
|
+
for plan in results.get("plans", []):
|
490
|
+
status = plan.get("status", "unknown")
|
491
|
+
report += f"- Status: {status}\n"
|
492
|
+
if plan.get("issues"):
|
493
|
+
for issue in plan["issues"]:
|
494
|
+
report += f" - Issue: {issue}\n"
|
495
|
+
|
496
|
+
# Tasks section
|
497
|
+
report += "\n## Tasks\n"
|
498
|
+
for task in results.get("tasks", []):
|
499
|
+
status = task.get("status", "unknown")
|
500
|
+
report += f"- Status: {status}\n"
|
501
|
+
if task.get("issues"):
|
502
|
+
for issue in task["issues"]:
|
503
|
+
report += f" - Issue: {issue}\n"
|
504
|
+
|
505
|
+
return report
|
@@ -112,7 +112,7 @@ When called with `/sp-decompose $ARGUMENTS`, I will:
|
|
112
112
|
- Create feature-specific plan template with services
|
113
113
|
- Prepare for `/sp-plan generate` with service context
|
114
114
|
- Enable `/sp-task breakdown` per service
|
115
|
-
- Run validation: `
|
115
|
+
- Run validation: `bash scripts/sp-pulse-decompose.sh validate`
|
116
116
|
|
117
117
|
## Examples
|
118
118
|
|
@@ -47,14 +47,9 @@ When called with `/sp-plan $ARGUMENTS`, I will:
|
|
47
47
|
- Generate single monolithic plan
|
48
48
|
d. **Find and validate specification** from selected spec file
|
49
49
|
|
50
|
-
d. **
|
50
|
+
d. **Validation** using script:
|
51
51
|
```bash
|
52
|
-
|
53
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
54
|
-
python scripts/sp-pulse-plan.py "$FEATURE_DIR"
|
55
|
-
else
|
56
|
-
bash scripts/sp-pulse-plan.sh "$FEATURE_DIR" || python scripts/sp-pulse-plan.py "$FEATURE_DIR"
|
57
|
-
fi
|
52
|
+
bash scripts/sp-pulse-plan.sh "$FEATURE_DIR"
|
58
53
|
```
|
59
54
|
|
60
55
|
e. **Run Constitutional Phase Gates** (Article VII):
|
@@ -102,14 +97,9 @@ When called with `/sp-plan $ARGUMENTS`, I will:
|
|
102
97
|
4. **For `/sp-plan validate`:**
|
103
98
|
a. **Show existing plan files**: List all plan-XXX.md files in current feature directory
|
104
99
|
b. **Ask user to select**: Which plan file to validate
|
105
|
-
c. **
|
100
|
+
c. **Validation** using script:
|
106
101
|
```bash
|
107
|
-
|
108
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
109
|
-
python scripts/sp-pulse-plan.py "$FEATURE_DIR"
|
110
|
-
else
|
111
|
-
bash scripts/sp-pulse-plan.sh "$FEATURE_DIR" || python scripts/sp-pulse-plan.py "$FEATURE_DIR"
|
112
|
-
fi
|
102
|
+
bash scripts/sp-pulse-plan.sh "$FEATURE_DIR"
|
113
103
|
```
|
114
104
|
d. Verify all constitutional gates are addressed
|
115
105
|
e. Check complexity exceptions have proper justifications
|
@@ -202,14 +192,13 @@ I will analyze and recommend complexity reductions.
|
|
202
192
|
## Enhanced Features
|
203
193
|
|
204
194
|
- **AI-optimized templates** with Jinja2-style variables
|
205
|
-
- **
|
206
|
-
- **Enhanced script integration** for Bash and Python
|
195
|
+
- **Script execution** with Bash
|
207
196
|
- **Constitutional compliance tracking** with gate status
|
208
197
|
- **Complexity exception management** with justifications
|
209
198
|
- **Performance and security considerations** integrated
|
210
199
|
- **Integration-first approach** with real service usage
|
211
200
|
- **Detailed validation reporting** with specific recommendations
|
212
|
-
- **
|
201
|
+
- **Cross-platform operation** with Bash
|
213
202
|
|
214
203
|
## Error Handling
|
215
204
|
|
@@ -23,9 +23,8 @@ Initialize a new feature following SpecPulse methodology with constitutional com
|
|
23
23
|
When called with `/sp-pulse $ARGUMENTS`, I will:
|
24
24
|
|
25
25
|
1. **Validate arguments** and extract feature name + optional ID
|
26
|
-
2. **Run initialization script
|
27
|
-
-
|
28
|
-
- **Python Fallback**: `python scripts/sp-pulse-init.py "$FEATURE_NAME" "$OPTIONAL_ID"`
|
26
|
+
2. **Run initialization script**:
|
27
|
+
- `bash scripts/sp-pulse-init.sh "$FEATURE_NAME" "$OPTIONAL_ID"`
|
29
28
|
3. **Create complete feature structure**:
|
30
29
|
- Generate feature ID (001, 002, etc.) or use provided ID
|
31
30
|
- Create sanitized branch name: `ID-feature-name`
|
@@ -105,8 +104,7 @@ The system automatically detects which feature you're working on:
|
|
105
104
|
- **Git integration** with branch management
|
106
105
|
- **Template validation** before copying
|
107
106
|
- **Todo list creation** for progress tracking
|
108
|
-
- **Cross-platform script execution** with
|
109
|
-
- **Multiple language support**: Bash, PowerShell, Python
|
107
|
+
- **Cross-platform script execution** with Bash
|
110
108
|
- **Platform-agnostic operation** for any development environment
|
111
109
|
|
112
110
|
## Feature Progress Tracking
|
@@ -56,9 +56,8 @@ When called with `/sp-spec $ARGUMENTS`, I will:
|
|
56
56
|
- Use detected feature context to determine target directory
|
57
57
|
- **Version management**: Check existing spec files and create next version (spec-001.md, spec-002.md, etc.)
|
58
58
|
- Write specification to `specs/ID-feature-name/spec-XXX.md`
|
59
|
-
- Run
|
60
|
-
-
|
61
|
-
- **Python Fallback**: `python scripts/sp-pulse-spec.py "$FEATURE_DIR"`
|
59
|
+
- Run validation:
|
60
|
+
- `bash scripts/sp-pulse-spec.sh "$FEATURE_DIR"`
|
62
61
|
|
63
62
|
4. **For `/sp-spec update`:**
|
64
63
|
- **Show existing spec files**: List all spec-XXX.md files in current feature directory
|
@@ -75,12 +74,7 @@ When called with `/sp-spec $ARGUMENTS`, I will:
|
|
75
74
|
- Read selected specification file from detected context
|
76
75
|
- Check all required sections using enhanced validation:
|
77
76
|
```bash
|
78
|
-
|
79
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
80
|
-
python scripts/sp-pulse-spec.py "$FEATURE_DIR"
|
81
|
-
else
|
82
|
-
bash scripts/sp-pulse-spec.sh "$FEATURE_DIR" || python scripts/sp-pulse-spec.py "$FEATURE_DIR"
|
83
|
-
fi
|
77
|
+
bash scripts/sp-pulse-spec.sh "$FEATURE_DIR"
|
84
78
|
```
|
85
79
|
- Count `[NEEDS CLARIFICATION]` markers
|
86
80
|
- Verify acceptance criteria follow Given-When-Then format
|
@@ -164,10 +158,9 @@ The AI-optimized specification template includes:
|
|
164
158
|
|
165
159
|
## Integration Features
|
166
160
|
|
167
|
-
- **
|
168
|
-
- **Enhanced script integration** with Bash and Python support
|
161
|
+
- **Script execution** with Bash support
|
169
162
|
- **Template variable processing** for AI optimization
|
170
163
|
- **Automated validation** with detailed reporting
|
171
164
|
- **Context-aware operation** using memory/context.md
|
172
165
|
- **Progress tracking** with todo list integration
|
173
|
-
- **
|
166
|
+
- **Cross-platform operation** with Bash
|
@@ -48,14 +48,9 @@ When called with `/sp-task $ARGUMENTS`, I will:
|
|
48
48
|
c. **If not decomposed**:
|
49
49
|
- Show existing plan files and ask user to select
|
50
50
|
- Generate single task file with standard IDs (T001, T002)
|
51
|
-
c. **
|
51
|
+
c. **Validation** using script:
|
52
52
|
```bash
|
53
|
-
|
54
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
55
|
-
python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
56
|
-
else
|
57
|
-
bash scripts/sp-pulse-task.sh "$FEATURE_DIR" || python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
58
|
-
fi
|
53
|
+
bash scripts/sp-pulse-task.sh "$FEATURE_DIR"
|
59
54
|
```
|
60
55
|
|
61
56
|
d. **Read implementation plan** from selected plan file
|
@@ -112,14 +107,9 @@ When called with `/sp-task $ARGUMENTS`, I will:
|
|
112
107
|
4. **For `/sp-task update`:**
|
113
108
|
a. **Show existing task files**: List all task-XXX.md files in current feature directory
|
114
109
|
b. **Ask user to select**: Which task file to update
|
115
|
-
c. **
|
110
|
+
c. **Analysis** using script:
|
116
111
|
```bash
|
117
|
-
|
118
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
119
|
-
python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
120
|
-
else
|
121
|
-
bash scripts/sp-pulse-task.sh "$FEATURE_DIR" || python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
122
|
-
fi
|
112
|
+
bash scripts/sp-pulse-task.sh "$FEATURE_DIR"
|
123
113
|
```
|
124
114
|
d. **Parse current tasks** from selected file with comprehensive status:
|
125
115
|
- Total tasks, completed, pending, blocked
|
@@ -253,12 +243,7 @@ User: /sp-task execute AUTH-T001
|
|
253
243
|
I will:
|
254
244
|
- Run: Cross-platform detection and execution
|
255
245
|
```bash
|
256
|
-
|
257
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
258
|
-
python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
259
|
-
else
|
260
|
-
bash scripts/sp-pulse-task.sh "$FEATURE_DIR" || python scripts/sp-pulse-task.py "$FEATURE_DIR"
|
261
|
-
fi
|
246
|
+
bash scripts/sp-pulse-task.sh "$FEATURE_DIR"
|
262
247
|
```
|
263
248
|
- Create: AI-optimized task structure with template variables
|
264
249
|
- Output: `TOTAL_TASKS=25, PARALLEL_TASKS=8, STATUS=generated`
|
@@ -283,27 +268,22 @@ I will:
|
|
283
268
|
- Validate: Constitutional gates compliance and task readiness
|
284
269
|
- Execute: Cross-platform task execution
|
285
270
|
```bash
|
286
|
-
|
287
|
-
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
288
|
-
python scripts/sp-pulse-task.py "$FEATURE_DIR" "execute:$TASK_ID"
|
289
|
-
else
|
290
|
-
bash scripts/sp-pulse-task.sh "$FEATURE_DIR" "execute:$TASK_ID" || python scripts/sp-pulse-task.py "$FEATURE_DIR" "execute:$TASK_ID"
|
291
|
-
fi
|
271
|
+
bash scripts/sp-pulse-task.sh "$FEATURE_DIR" "execute:$TASK_ID"
|
292
272
|
```
|
293
273
|
- Track: Results and update progress automatically
|
294
274
|
|
295
275
|
## Enhanced Features
|
296
276
|
|
297
|
-
- **
|
277
|
+
- **Script execution** with Bash
|
298
278
|
- **AI-optimized templates** with Jinja2-style variables
|
299
|
-
- **
|
279
|
+
- **Script integration** for validation and execution
|
300
280
|
- **Constitutional gates compliance** tracking
|
301
281
|
- **Parallel task identification** and execution
|
302
282
|
- **Comprehensive progress tracking** with YAML configuration
|
303
283
|
- **Automatic percentage calculation** and velocity metrics
|
304
284
|
- **Task dependency management** with conflict detection
|
305
285
|
- **Execution command generation** with script integration
|
306
|
-
- **
|
286
|
+
- **Cross-platform operation** with Bash
|
307
287
|
|
308
288
|
## Error Handling
|
309
289
|
|
@@ -38,17 +38,15 @@ Parse arguments to determine action:
|
|
38
38
|
|
39
39
|
7. Check existing plan files and create next version (plan-001.md, plan-002.md, etc.)
|
40
40
|
8. Write plan to plans/XXX-feature/plan-XXX.md
|
41
|
-
9. Run
|
42
|
-
-
|
43
|
-
- Fallback: !{python scripts/sp-pulse-plan.py "XXX-feature"}
|
41
|
+
9. Run validation:
|
42
|
+
- !{bash scripts/sp-pulse-plan.sh "XXX-feature"}
|
44
43
|
|
45
44
|
## For /sp-plan validate:
|
46
45
|
1. Show list of existing plan files in current feature directory
|
47
46
|
2. Ask user which plan file to validate
|
48
47
|
3. Read selected plan from @{plans/*/plan-XXX.md}
|
49
|
-
4. Run
|
50
|
-
-
|
51
|
-
- Fallback: !{python scripts/sp-pulse-plan.py "XXX-feature"}
|
48
|
+
4. Run validation:
|
49
|
+
- !{bash scripts/sp-pulse-plan.sh "XXX-feature"}
|
52
50
|
5. Verify Phase Gates compliance
|
53
51
|
6. Check complexity tracking
|
54
52
|
7. Ensure test-first approach
|
@@ -5,9 +5,8 @@ Initialize a new SpecPulse feature with the name: {{args}}
|
|
5
5
|
Please follow these steps:
|
6
6
|
|
7
7
|
1. Extract the feature name from the provided arguments
|
8
|
-
2. Run the initialization script
|
9
|
-
-
|
10
|
-
- Fallback: !{python scripts/sp-pulse-init.py "{{args}}"}
|
8
|
+
2. Run the initialization script:
|
9
|
+
- !{bash scripts/sp-pulse-init.sh "{{args}}"}
|
11
10
|
3. Create the feature structure:
|
12
11
|
- Generate feature ID (001, 002, etc.)
|
13
12
|
- Create directories: specs/XXX-feature/, plans/XXX-feature/, tasks/XXX-feature/
|
@@ -24,9 +24,8 @@ Parse the arguments to determine the action:
|
|
24
24
|
4. Find current feature directory from detected context
|
25
25
|
5. Check existing spec files and create next version (spec-001.md, spec-002.md, etc.)
|
26
26
|
6. Write specification to specs/XXX-feature/spec-XXX.md
|
27
|
-
7. Run
|
28
|
-
-
|
29
|
-
- Fallback: !{python scripts/sp-pulse-spec.py "XXX-feature"}
|
27
|
+
7. Run validation:
|
28
|
+
- !{bash scripts/sp-pulse-spec.sh "XXX-feature"}
|
30
29
|
|
31
30
|
## For /sp-spec update:
|
32
31
|
1. Show list of existing spec files in current feature directory
|
@@ -39,9 +38,8 @@ Parse the arguments to determine the action:
|
|
39
38
|
## For /sp-spec validate:
|
40
39
|
1. Show list of existing spec files in current feature directory
|
41
40
|
2. Ask user which spec file to validate
|
42
|
-
3. Run
|
43
|
-
-
|
44
|
-
- Fallback: !{python scripts/sp-pulse-spec.py "XXX-feature"}
|
41
|
+
3. Run validation:
|
42
|
+
- !{bash scripts/sp-pulse-spec.sh "XXX-feature"}
|
45
43
|
4. Check all required sections are filled
|
46
44
|
5. Count [NEEDS CLARIFICATION] markers
|
47
45
|
6. Verify acceptance criteria are testable
|
@@ -35,9 +35,8 @@ Parse arguments to determine action:
|
|
35
35
|
|
36
36
|
5. Check existing task files and create next version (task-001.md, task-002.md, etc.)
|
37
37
|
6. Write tasks to tasks/XXX-feature/task-XXX.md
|
38
|
-
7. Run
|
39
|
-
-
|
40
|
-
- Fallback: !{python scripts/sp-pulse-task.py "XXX-feature"}
|
38
|
+
7. Run validation:
|
39
|
+
- !{bash scripts/sp-pulse-task.sh "XXX-feature"}
|
41
40
|
|
42
41
|
## For /sp-task update:
|
43
42
|
1. Show list of existing task files in current feature directory
|
@@ -48,17 +47,15 @@ Parse arguments to determine action:
|
|
48
47
|
6. Add newly discovered tasks
|
49
48
|
7. Update dependencies and blockers
|
50
49
|
8. Save updated task list
|
51
|
-
9. Run
|
52
|
-
-
|
53
|
-
- Fallback: !{python scripts/sp-pulse-task.py "XXX-feature"}
|
50
|
+
9. Run validation:
|
51
|
+
- !{bash scripts/sp-pulse-task.sh "XXX-feature"}
|
54
52
|
|
55
53
|
## For /sp-task status:
|
56
54
|
1. Show list of existing task files in current feature directory
|
57
55
|
2. Ask user which task file to show status for
|
58
56
|
3. Read selected current tasks
|
59
|
-
4. Run
|
60
|
-
-
|
61
|
-
- Fallback: !{python scripts/sp-pulse-task.py "XXX-feature"}
|
57
|
+
4. Run analysis:
|
58
|
+
- !{bash scripts/sp-pulse-task.sh "XXX-feature"}
|
62
59
|
5. Count completed vs total
|
63
60
|
6. Show current phase progress
|
64
61
|
7. List any blockers
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: specpulse
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.3
|
4
4
|
Summary: Specification-Driven Development Framework
|
5
5
|
Home-page: https://github.com/specpulse
|
6
6
|
Author: SpecPulse
|
@@ -94,11 +94,10 @@ pip install specpulse --upgrade
|
|
94
94
|
- Claude or Gemini CLI (for AI integration)
|
95
95
|
|
96
96
|
**Cross-Platform Support:**
|
97
|
-
- **Windows**:
|
98
|
-
- **Linux**:
|
99
|
-
- **macOS**:
|
97
|
+
- **Windows**: Requires Git Bash or WSL
|
98
|
+
- **Linux**: Native Bash support
|
99
|
+
- **macOS**: Native Bash support
|
100
100
|
- **Source Installation**: Works perfectly from source code (not just PyPI)
|
101
|
-
- **Automatic Detection**: AI commands automatically detect OS and choose appropriate script
|
102
101
|
|
103
102
|
## 🚀 Quick Start
|
104
103
|
|
@@ -269,10 +268,9 @@ Stop guessing what users want:
|
|
269
268
|
|
270
269
|
Claude and Gemini use slash commands that accept arguments via `$ARGUMENTS`:
|
271
270
|
|
272
|
-
**
|
273
|
-
- **
|
274
|
-
- **
|
275
|
-
- **Automatic Detection**: AI commands detect OS and choose appropriate script
|
271
|
+
**Script Execution:**
|
272
|
+
- **All Platforms**: Bash (.sh) scripts only
|
273
|
+
- **Requirements**: Bash shell required (Git Bash on Windows, native on Linux/macOS)
|
276
274
|
- **Universal Compatibility**: Works whether installed via PyPI or source code
|
277
275
|
- **Unicode Support**: Full international character support (≤, ≥, →, ←)
|
278
276
|
|
@@ -292,13 +290,11 @@ Claude and Gemini use slash commands that accept arguments via `$ARGUMENTS`:
|
|
292
290
|
|
293
291
|
**Behind the Scenes:**
|
294
292
|
- Commands capture arguments using `$ARGUMENTS` variable
|
295
|
-
- **
|
296
|
-
- `sp-pulse-*.
|
297
|
-
- `sp-pulse-*.sh` - Bash scripts (Linux/macOS)
|
293
|
+
- **Shell scripts** in `resources/scripts/` folder process the arguments:
|
294
|
+
- `sp-pulse-*.sh` - Bash scripts (all platforms)
|
298
295
|
- AI reads templates from `resources/templates/` folder
|
299
296
|
- Results are saved in `specs/`, `plans/`, `tasks/` folders
|
300
297
|
- Memory system tracks progress in `memory/` folder
|
301
|
-
- **Automatic platform detection** ensures the right script runs on each OS
|
302
298
|
|
303
299
|
**Claude vs Gemini:**
|
304
300
|
- **Claude**: Uses Markdown command files (`.claude/commands/*.md`) with YAML frontmatter
|