specpulse 1.0.6__py3-none-any.whl → 1.1.0__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 +598 -617
- specpulse/core/specpulse.py +1110 -1105
- specpulse/resources/commands/claude/sp-continue.md +203 -0
- specpulse/resources/commands/claude/{plan.md → sp-plan.md} +53 -38
- specpulse/resources/commands/claude/sp-pulse.md +142 -0
- specpulse/resources/commands/claude/{spec.md → sp-spec.md} +36 -23
- specpulse/resources/commands/claude/sp-status.md +170 -0
- specpulse/resources/commands/claude/{task.md → sp-task.md} +68 -48
- specpulse/resources/commands/gemini/sp-continue.toml +56 -0
- specpulse/resources/commands/gemini/sp-plan.toml +68 -0
- specpulse/resources/commands/gemini/{pulse.toml → sp-pulse.toml} +12 -6
- specpulse/resources/commands/gemini/sp-spec.toml +54 -0
- specpulse/resources/commands/gemini/sp-status.toml +61 -0
- specpulse/resources/commands/gemini/sp-task.toml +79 -0
- specpulse/resources/memory/constitution.md +5 -5
- specpulse/resources/memory/context.md +12 -1
- specpulse/resources/scripts/{pulse-init.py → sp-pulse-init.py} +6 -6
- specpulse/resources/scripts/{pulse-init.sh → sp-pulse-init.sh} +95 -95
- specpulse/resources/scripts/{pulse-plan.py → sp-pulse-plan.py} +32 -7
- specpulse/resources/scripts/{pulse-plan.sh → sp-pulse-plan.sh} +136 -126
- specpulse/resources/scripts/{pulse-spec.py → sp-pulse-spec.py} +26 -6
- specpulse/resources/scripts/{pulse-spec.sh → sp-pulse-spec.sh} +126 -103
- specpulse/resources/scripts/{pulse-task.py → sp-pulse-task.py} +42 -6
- specpulse/resources/scripts/{pulse-task.sh → sp-pulse-task.sh} +32 -16
- specpulse/resources/templates/plan.md +206 -206
- specpulse/resources/templates/spec.md +125 -125
- specpulse/resources/templates/task.md +164 -163
- {specpulse-1.0.6.dist-info → specpulse-1.1.0.dist-info}/METADATA +35 -35
- specpulse-1.1.0.dist-info/RECORD +41 -0
- specpulse/resources/commands/claude/pulse.md +0 -91
- specpulse/resources/commands/gemini/plan.toml +0 -59
- specpulse/resources/commands/gemini/spec.toml +0 -45
- specpulse/resources/commands/gemini/task.toml +0 -69
- specpulse/resources/scripts/pulse-init.ps1 +0 -186
- specpulse/resources/scripts/pulse-plan.ps1 +0 -251
- specpulse/resources/scripts/pulse-spec.ps1 +0 -185
- specpulse/resources/scripts/pulse-task.ps1 +0 -263
- specpulse-1.0.6.dist-info/RECORD +0 -41
- {specpulse-1.0.6.dist-info → specpulse-1.1.0.dist-info}/WHEEL +0 -0
- {specpulse-1.0.6.dist-info → specpulse-1.1.0.dist-info}/entry_points.txt +0 -0
- {specpulse-1.0.6.dist-info → specpulse-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {specpulse-1.0.6.dist-info → specpulse-1.1.0.dist-info}/top_level.txt +0 -0
specpulse/core/specpulse.py
CHANGED
@@ -1,1106 +1,1111 @@
|
|
1
|
-
"""
|
2
|
-
SpecPulse Core Implementation
|
3
|
-
"""
|
4
|
-
|
5
|
-
from pathlib import Path
|
6
|
-
from datetime import datetime
|
7
|
-
from typing import Dict, List, Optional
|
8
|
-
import yaml
|
9
|
-
import json
|
10
|
-
import os
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
class SpecPulse:
|
15
|
-
"""Core SpecPulse functionality"""
|
16
|
-
|
17
|
-
def __init__(self, project_path: Optional[Path] = None):
|
18
|
-
self.project_path = project_path or Path.cwd()
|
19
|
-
self.config = self._load_config()
|
20
|
-
# Get resource directory path using package data
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
self.resources_dir = Path(
|
25
|
-
except:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
-
|
78
|
-
|
79
|
-
-
|
80
|
-
|
81
|
-
####
|
82
|
-
-
|
83
|
-
-
|
84
|
-
-
|
85
|
-
|
86
|
-
####
|
87
|
-
-
|
88
|
-
-
|
89
|
-
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
##
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
##
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
- **
|
153
|
-
- **
|
154
|
-
- **
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
**
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
**
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
**
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
**
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
├──
|
232
|
-
│ ├──
|
233
|
-
│ ├──
|
234
|
-
│
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
```
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
```
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
###
|
283
|
-
-
|
284
|
-
-
|
285
|
-
-
|
286
|
-
|
287
|
-
###
|
288
|
-
-
|
289
|
-
-
|
290
|
-
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
###
|
309
|
-
| Risk | Probability | Impact | Mitigation |
|
310
|
-
|------|------------|--------|------------|
|
311
|
-
| [Risk] | [H/M/L] | [H/M/L] | [Strategy] |
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
-
|
350
|
-
- **
|
351
|
-
- **
|
352
|
-
|
353
|
-
|
354
|
-
[
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
###
|
377
|
-
- [ ] TASK-XXX:
|
378
|
-
- [ ] TASK-XXX: Create
|
379
|
-
- [ ] TASK-XXX:
|
380
|
-
|
381
|
-
###
|
382
|
-
- [ ] TASK-XXX:
|
383
|
-
- [ ] TASK-XXX: Create
|
384
|
-
- [ ] TASK-XXX:
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
###
|
450
|
-
-
|
451
|
-
-
|
452
|
-
-
|
453
|
-
|
454
|
-
###
|
455
|
-
-
|
456
|
-
-
|
457
|
-
-
|
458
|
-
|
459
|
-
###
|
460
|
-
-
|
461
|
-
-
|
462
|
-
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
###
|
473
|
-
-
|
474
|
-
-
|
475
|
-
-
|
476
|
-
|
477
|
-
###
|
478
|
-
-
|
479
|
-
-
|
480
|
-
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
- [
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
###
|
518
|
-
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
- [
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
###
|
529
|
-
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
**
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
[
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
# Create
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
#
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
echo "
|
611
|
-
echo "
|
612
|
-
"""
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
echo "
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
echo "
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
echo "
|
697
|
-
|
698
|
-
echo "
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
echo "
|
730
|
-
echo "
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
echo "
|
746
|
-
echo "
|
747
|
-
|
748
|
-
echo "
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
if ! grep -q "##
|
772
|
-
echo " ❌ Missing
|
773
|
-
((errors++))
|
774
|
-
fi
|
775
|
-
|
776
|
-
if ! grep -q "##
|
777
|
-
echo " ❌ Missing
|
778
|
-
((errors++))
|
779
|
-
fi
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
fi
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
"""
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
"""
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
-
|
851
|
-
-
|
852
|
-
|
853
|
-
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
-
|
858
|
-
-
|
859
|
-
|
860
|
-
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
-
|
865
|
-
-
|
866
|
-
|
867
|
-
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
-
|
872
|
-
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
-
|
1061
|
-
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
- Run: `/
|
1065
|
-
-
|
1066
|
-
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
- Run: `/
|
1070
|
-
-
|
1071
|
-
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
- Run: `/
|
1075
|
-
-
|
1076
|
-
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1
|
+
"""
|
2
|
+
SpecPulse Core Implementation
|
3
|
+
"""
|
4
|
+
|
5
|
+
from pathlib import Path
|
6
|
+
from datetime import datetime
|
7
|
+
from typing import Dict, List, Optional
|
8
|
+
import yaml
|
9
|
+
import json
|
10
|
+
import os
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
class SpecPulse:
|
15
|
+
"""Core SpecPulse functionality"""
|
16
|
+
|
17
|
+
def __init__(self, project_path: Optional[Path] = None):
|
18
|
+
self.project_path = project_path or Path.cwd()
|
19
|
+
self.config = self._load_config()
|
20
|
+
# Get resource directory path using package data
|
21
|
+
try:
|
22
|
+
# Use modern importlib.resources (Python 3.9+)
|
23
|
+
from importlib import resources
|
24
|
+
self.resources_dir = Path(resources.files('specpulse').joinpath('resources'))
|
25
|
+
except:
|
26
|
+
try:
|
27
|
+
# Fallback to pkg_resources for older Python versions
|
28
|
+
import pkg_resources
|
29
|
+
self.resources_dir = Path(pkg_resources.resource_filename('specpulse', 'resources'))
|
30
|
+
except:
|
31
|
+
# Final fallback to development path
|
32
|
+
self.resources_dir = Path(__file__).parent.parent / "resources"
|
33
|
+
|
34
|
+
def _load_config(self) -> Dict:
|
35
|
+
"""Load project configuration"""
|
36
|
+
config_path = self.project_path / ".specpulse" / "config.yaml"
|
37
|
+
if config_path.exists():
|
38
|
+
with open(config_path, 'r') as f:
|
39
|
+
return yaml.safe_load(f)
|
40
|
+
return {}
|
41
|
+
|
42
|
+
def get_spec_template(self) -> str:
|
43
|
+
"""Get specification template from file"""
|
44
|
+
template_path = self.resources_dir / "templates" / "spec-001.md"
|
45
|
+
if template_path.exists():
|
46
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
47
|
+
return f.read()
|
48
|
+
# Fallback to embedded template if file not found
|
49
|
+
return """<!-- SpecPulse Specification Template v1.0 -->
|
50
|
+
<!-- AI Instructions: Fill this template based on user description -->
|
51
|
+
|
52
|
+
# Specification: [FEATURE_NAME]
|
53
|
+
|
54
|
+
## Metadata
|
55
|
+
- **ID**: SPEC-[XXX]
|
56
|
+
- **Created**: [DATE]
|
57
|
+
- **Author**: [USER]
|
58
|
+
- **AI Assistant**: [CLAUDE|GEMINI]
|
59
|
+
- **Version**: 1.0.0
|
60
|
+
|
61
|
+
## Executive Summary
|
62
|
+
[One paragraph description of what this feature does and why it's needed]
|
63
|
+
|
64
|
+
## Problem Statement
|
65
|
+
[Detailed description of the problem being solved]
|
66
|
+
|
67
|
+
## Proposed Solution
|
68
|
+
[High-level approach to solving the problem]
|
69
|
+
|
70
|
+
## Detailed Requirements
|
71
|
+
|
72
|
+
### Functional Requirements
|
73
|
+
<!-- AI: Generate numbered list of specific, testable requirements -->
|
74
|
+
|
75
|
+
FR-001: [Requirement]
|
76
|
+
- Acceptance: [How to verify this requirement is met]
|
77
|
+
- Priority: [MUST|SHOULD|COULD]
|
78
|
+
|
79
|
+
### Non-Functional Requirements
|
80
|
+
|
81
|
+
#### Performance
|
82
|
+
- Response Time: [Target]
|
83
|
+
- Throughput: [Target]
|
84
|
+
- Resource Usage: [Limits]
|
85
|
+
|
86
|
+
#### Security
|
87
|
+
- Authentication: [Method]
|
88
|
+
- Authorization: [Model]
|
89
|
+
- Data Protection: [Requirements]
|
90
|
+
|
91
|
+
#### Scalability
|
92
|
+
- User Load: [Target]
|
93
|
+
- Data Volume: [Target]
|
94
|
+
- Geographic Distribution: [Requirements]
|
95
|
+
|
96
|
+
## User Stories
|
97
|
+
|
98
|
+
<!-- AI: Generate user stories in standard format -->
|
99
|
+
|
100
|
+
### Story 1: [Title]
|
101
|
+
**As a** [user type]
|
102
|
+
**I want** [action/feature]
|
103
|
+
**So that** [benefit/value]
|
104
|
+
|
105
|
+
**Acceptance Criteria:**
|
106
|
+
- [ ] [Criterion 1]
|
107
|
+
- [ ] [Criterion 2]
|
108
|
+
- [ ] [Criterion 3]
|
109
|
+
|
110
|
+
## Technical Constraints
|
111
|
+
<!-- List any technical limitations or requirements -->
|
112
|
+
|
113
|
+
## Dependencies
|
114
|
+
<!-- External services, libraries, or other features required -->
|
115
|
+
|
116
|
+
## Risks and Mitigations
|
117
|
+
<!-- Identify potential risks and how to address them -->
|
118
|
+
|
119
|
+
## Open Questions
|
120
|
+
<!-- Mark with [NEEDS CLARIFICATION] for items requiring user input -->
|
121
|
+
|
122
|
+
## Appendix
|
123
|
+
<!-- Additional diagrams, mockups, or references -->
|
124
|
+
"""
|
125
|
+
|
126
|
+
def get_plan_template(self) -> str:
|
127
|
+
"""Get implementation plan template from file"""
|
128
|
+
template_path = self.resources_dir / "templates" / "plan-001.md"
|
129
|
+
if template_path.exists():
|
130
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
131
|
+
return f.read()
|
132
|
+
# Fallback to embedded template if file not found
|
133
|
+
return """<!-- SpecPulse Implementation Plan Template v1.0 -->
|
134
|
+
<!-- AI Instructions: Generate plan from specification -->
|
135
|
+
|
136
|
+
# Implementation Plan: [FEATURE_NAME]
|
137
|
+
|
138
|
+
## Specification Reference
|
139
|
+
- **Spec ID**: SPEC-[XXX]
|
140
|
+
- **Generated**: [DATE]
|
141
|
+
- **Optimization Focus**: [PERFORMANCE|SECURITY|SIMPLICITY|COST]
|
142
|
+
|
143
|
+
## Architecture Overview
|
144
|
+
```mermaid
|
145
|
+
<!-- AI: Generate architecture diagram -->
|
146
|
+
```
|
147
|
+
|
148
|
+
## Technology Stack
|
149
|
+
|
150
|
+
### Core Technologies
|
151
|
+
- **Language**: [Choice with rationale]
|
152
|
+
- **Framework**: [Choice with rationale]
|
153
|
+
- **Database**: [Choice with rationale]
|
154
|
+
- **Cache**: [Choice with rationale]
|
155
|
+
|
156
|
+
### Supporting Tools
|
157
|
+
- **Testing**: [Framework choice]
|
158
|
+
- **CI/CD**: [Platform choice]
|
159
|
+
- **Monitoring**: [Solution choice]
|
160
|
+
|
161
|
+
## Implementation Phases
|
162
|
+
|
163
|
+
### Phase 0: Setup and Prerequisites
|
164
|
+
**Duration**: [Estimate]
|
165
|
+
**Tasks**:
|
166
|
+
1. Environment setup
|
167
|
+
2. Repository initialization
|
168
|
+
3. Dependency installation
|
169
|
+
4. Configuration
|
170
|
+
|
171
|
+
### Phase 1: Data Layer
|
172
|
+
**Duration**: [Estimate]
|
173
|
+
**Deliverables**:
|
174
|
+
- Database schema
|
175
|
+
- Migration scripts
|
176
|
+
- Data models
|
177
|
+
- Repository pattern implementation
|
178
|
+
|
179
|
+
**Tasks**:
|
180
|
+
1. Design database schema
|
181
|
+
2. Create migration scripts
|
182
|
+
3. Implement data models
|
183
|
+
4. Create repository interfaces
|
184
|
+
5. Write data layer tests
|
185
|
+
|
186
|
+
### Phase 2: Business Logic
|
187
|
+
**Duration**: [Estimate]
|
188
|
+
**Deliverables**:
|
189
|
+
- Service layer
|
190
|
+
- Business rules implementation
|
191
|
+
- Validation logic
|
192
|
+
|
193
|
+
**Tasks**:
|
194
|
+
1. Implement service interfaces
|
195
|
+
2. Create business logic modules
|
196
|
+
3. Add validation rules
|
197
|
+
4. Implement error handling
|
198
|
+
5. Write unit tests
|
199
|
+
|
200
|
+
### Phase 3: API Layer
|
201
|
+
**Duration**: [Estimate]
|
202
|
+
**Deliverables**:
|
203
|
+
- REST/GraphQL endpoints
|
204
|
+
- API documentation
|
205
|
+
- Authentication/Authorization
|
206
|
+
|
207
|
+
**Tasks**:
|
208
|
+
1. Design API contracts
|
209
|
+
2. Implement endpoints
|
210
|
+
3. Add authentication
|
211
|
+
4. Create API documentation
|
212
|
+
5. Write integration tests
|
213
|
+
|
214
|
+
### Phase 4: Testing and Optimization
|
215
|
+
**Duration**: [Estimate]
|
216
|
+
**Deliverables**:
|
217
|
+
- Complete test suite
|
218
|
+
- Performance optimization
|
219
|
+
- Security hardening
|
220
|
+
|
221
|
+
**Tasks**:
|
222
|
+
1. Complete test coverage
|
223
|
+
2. Performance testing
|
224
|
+
3. Security audit
|
225
|
+
4. Load testing
|
226
|
+
5. Documentation
|
227
|
+
|
228
|
+
## File Structure
|
229
|
+
```
|
230
|
+
[feature-name]/
|
231
|
+
├── src/
|
232
|
+
│ ├── models/
|
233
|
+
│ ├── services/
|
234
|
+
│ ├── controllers/
|
235
|
+
│ └── utils/
|
236
|
+
├── tests/
|
237
|
+
│ ├── unit/
|
238
|
+
│ ├── integration/
|
239
|
+
│ └── e2e/
|
240
|
+
├── docs/
|
241
|
+
└── config/
|
242
|
+
```
|
243
|
+
|
244
|
+
## API Contracts
|
245
|
+
|
246
|
+
### Endpoint: [ENDPOINT_NAME]
|
247
|
+
```yaml
|
248
|
+
method: POST
|
249
|
+
path: /api/v1/[resource]
|
250
|
+
request:
|
251
|
+
headers:
|
252
|
+
Content-Type: application/json
|
253
|
+
Authorization: Bearer {token}
|
254
|
+
body:
|
255
|
+
field1: string
|
256
|
+
field2: number
|
257
|
+
response:
|
258
|
+
200:
|
259
|
+
success: true
|
260
|
+
data: object
|
261
|
+
400:
|
262
|
+
error: string
|
263
|
+
```
|
264
|
+
|
265
|
+
## Data Models
|
266
|
+
|
267
|
+
### Entity: [ENTITY_NAME]
|
268
|
+
```yaml
|
269
|
+
fields:
|
270
|
+
id: uuid
|
271
|
+
created_at: timestamp
|
272
|
+
updated_at: timestamp
|
273
|
+
[field_name]: [type]
|
274
|
+
relations:
|
275
|
+
[relation_name]: [type]
|
276
|
+
indexes:
|
277
|
+
- [field_name]
|
278
|
+
```
|
279
|
+
|
280
|
+
## Testing Strategy
|
281
|
+
|
282
|
+
### Unit Tests
|
283
|
+
- Coverage Target: 80%
|
284
|
+
- Framework: [Choice]
|
285
|
+
- Mock Strategy: [Approach]
|
286
|
+
|
287
|
+
### Integration Tests
|
288
|
+
- API Contract Tests
|
289
|
+
- Database Integration Tests
|
290
|
+
- External Service Tests
|
291
|
+
|
292
|
+
### E2E Tests
|
293
|
+
- Critical User Journeys
|
294
|
+
- Performance Benchmarks
|
295
|
+
- Security Scenarios
|
296
|
+
|
297
|
+
## Constitution Compliance
|
298
|
+
|
299
|
+
### Principle Validation
|
300
|
+
- [ ] Single Responsibility: Each component has one purpose
|
301
|
+
- [ ] Test-First: Tests written before implementation
|
302
|
+
- [ ] Documentation: All code is documented
|
303
|
+
- [ ] Security: Security considered by design
|
304
|
+
- [ ] Performance: Meets performance targets
|
305
|
+
|
306
|
+
## Risk Assessment
|
307
|
+
|
308
|
+
### Technical Risks
|
309
|
+
| Risk | Probability | Impact | Mitigation |
|
310
|
+
|------|------------|--------|------------|
|
311
|
+
| [Risk] | [H/M/L] | [H/M/L] | [Strategy] |
|
312
|
+
|
313
|
+
### Timeline Risks
|
314
|
+
| Risk | Probability | Impact | Mitigation |
|
315
|
+
|------|------------|--------|------------|
|
316
|
+
| [Risk] | [H/M/L] | [H/M/L] | [Strategy] |
|
317
|
+
|
318
|
+
## Success Criteria
|
319
|
+
- [ ] All functional requirements implemented
|
320
|
+
- [ ] Test coverage > 80%
|
321
|
+
- [ ] Performance targets met
|
322
|
+
- [ ] Security audit passed
|
323
|
+
- [ ] Documentation complete
|
324
|
+
"""
|
325
|
+
|
326
|
+
def get_task_template(self) -> str:
|
327
|
+
"""Get task list template from file"""
|
328
|
+
template_path = self.resources_dir / "templates" / "task.md"
|
329
|
+
if template_path.exists():
|
330
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
331
|
+
return f.read()
|
332
|
+
# Fallback to embedded template if file not found
|
333
|
+
return """<!-- SpecPulse Task List Template v1.0 -->
|
334
|
+
<!-- AI Instructions: Generate from implementation plan -->
|
335
|
+
|
336
|
+
# Task List: [FEATURE_NAME]
|
337
|
+
|
338
|
+
## Metadata
|
339
|
+
- **Plan Reference**: [PLAN_ID]
|
340
|
+
- **Total Tasks**: [COUNT]
|
341
|
+
- **Estimated Duration**: [TOTAL_HOURS]
|
342
|
+
- **Parallel Groups**: [COUNT]
|
343
|
+
|
344
|
+
## Task Organization
|
345
|
+
|
346
|
+
### 🔄 Parallel Group A
|
347
|
+
*These tasks can be executed simultaneously*
|
348
|
+
|
349
|
+
#### TASK-001: [Task Name]
|
350
|
+
- **Type**: [setup|development|testing|documentation]
|
351
|
+
- **Priority**: [HIGH|MEDIUM|LOW]
|
352
|
+
- **Estimate**: [hours]
|
353
|
+
- **Dependencies**: None
|
354
|
+
- **Description**: [What needs to be done]
|
355
|
+
- **Acceptance**: [How to verify completion]
|
356
|
+
- **Assignable**: [role/skill required]
|
357
|
+
|
358
|
+
#### TASK-002: [Task Name]
|
359
|
+
[Same structure as above]
|
360
|
+
|
361
|
+
### 📝 Sequential Tasks
|
362
|
+
*These tasks must be completed in order*
|
363
|
+
|
364
|
+
#### TASK-003: [Task Name]
|
365
|
+
- **Dependencies**: TASK-001
|
366
|
+
[Rest of structure]
|
367
|
+
|
368
|
+
### 🎯 Critical Path
|
369
|
+
*Tasks that directly impact timeline*
|
370
|
+
|
371
|
+
1. TASK-001 → TASK-003 → TASK-007
|
372
|
+
2. Estimated critical path duration: [hours]
|
373
|
+
|
374
|
+
## Task Details
|
375
|
+
|
376
|
+
### Development Tasks
|
377
|
+
- [ ] TASK-XXX: Implement [component]
|
378
|
+
- [ ] TASK-XXX: Create [feature]
|
379
|
+
- [ ] TASK-XXX: Integrate [service]
|
380
|
+
|
381
|
+
### Testing Tasks
|
382
|
+
- [ ] TASK-XXX: Write unit tests for [component]
|
383
|
+
- [ ] TASK-XXX: Create integration tests
|
384
|
+
- [ ] TASK-XXX: Perform security testing
|
385
|
+
|
386
|
+
### Documentation Tasks
|
387
|
+
- [ ] TASK-XXX: Document API endpoints
|
388
|
+
- [ ] TASK-XXX: Create user guide
|
389
|
+
- [ ] TASK-XXX: Update README
|
390
|
+
|
391
|
+
## Execution Schedule
|
392
|
+
|
393
|
+
### Day 1-2
|
394
|
+
- Morning: TASK-001, TASK-002 (parallel)
|
395
|
+
- Afternoon: TASK-003
|
396
|
+
|
397
|
+
### Day 3-4
|
398
|
+
- Morning: TASK-004
|
399
|
+
- Afternoon: TASK-005, TASK-006
|
400
|
+
|
401
|
+
## Progress Tracking
|
402
|
+
```yaml
|
403
|
+
status:
|
404
|
+
total: [count]
|
405
|
+
completed: 0
|
406
|
+
in_progress: 0
|
407
|
+
blocked: 0
|
408
|
+
|
409
|
+
metrics:
|
410
|
+
velocity: [tasks/day]
|
411
|
+
estimated_completion: [date]
|
412
|
+
blockers: []
|
413
|
+
```
|
414
|
+
"""
|
415
|
+
|
416
|
+
def get_constitution_template(self) -> str:
|
417
|
+
"""Get constitution template from file"""
|
418
|
+
template_path = self.resources_dir / "memory" / "constitution.md"
|
419
|
+
if template_path.exists():
|
420
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
421
|
+
return f.read()
|
422
|
+
# Fallback to embedded template if file not found
|
423
|
+
return """# Project Constitution
|
424
|
+
|
425
|
+
## Immutable Principles
|
426
|
+
|
427
|
+
### Principle 1: Simplicity First
|
428
|
+
Every solution must start with the simplest approach that could work.
|
429
|
+
Complexity is added only when proven necessary.
|
430
|
+
|
431
|
+
### Principle 2: Test-Driven Development
|
432
|
+
No production code without tests.
|
433
|
+
Tests are written first, implementation follows.
|
434
|
+
|
435
|
+
### Principle 3: Single Responsibility
|
436
|
+
Each module, function, and component does one thing well.
|
437
|
+
If you need "and" to describe it, split it.
|
438
|
+
|
439
|
+
### Principle 4: Documentation as Code
|
440
|
+
Documentation lives with code.
|
441
|
+
If it's not documented, it doesn't exist.
|
442
|
+
|
443
|
+
### Principle 5: Security by Design
|
444
|
+
Security is not an afterthought.
|
445
|
+
Every feature considers security implications from the start.
|
446
|
+
|
447
|
+
## Technical Standards
|
448
|
+
|
449
|
+
### Code Style
|
450
|
+
- Python: PEP 8 with type hints
|
451
|
+
- JavaScript: StandardJS
|
452
|
+
- Go: Official Go formatting
|
453
|
+
|
454
|
+
### Testing Requirements
|
455
|
+
- Minimum 80% code coverage
|
456
|
+
- All API endpoints must have contract tests
|
457
|
+
- Critical paths require E2E tests
|
458
|
+
|
459
|
+
### Performance Targets
|
460
|
+
- API response time: < 200ms (p95)
|
461
|
+
- Page load time: < 2 seconds
|
462
|
+
- Database queries: < 50ms
|
463
|
+
|
464
|
+
### Security Requirements
|
465
|
+
- All data encrypted in transit (TLS 1.3+)
|
466
|
+
- Sensitive data encrypted at rest
|
467
|
+
- Authentication: OAuth 2.0 / JWT
|
468
|
+
- Authorization: RBAC with least privilege
|
469
|
+
|
470
|
+
## Architecture Rules
|
471
|
+
|
472
|
+
### Service Boundaries
|
473
|
+
- Services communicate only through defined APIs
|
474
|
+
- No shared databases between services
|
475
|
+
- Each service owns its data
|
476
|
+
|
477
|
+
### Data Management
|
478
|
+
- Single source of truth for each data type
|
479
|
+
- Event sourcing for audit requirements
|
480
|
+
- CQRS where read/write patterns differ
|
481
|
+
|
482
|
+
### Error Handling
|
483
|
+
- All errors are handled explicitly
|
484
|
+
- User-facing errors are helpful and actionable
|
485
|
+
- System errors are logged with context
|
486
|
+
|
487
|
+
## Amendment Process
|
488
|
+
|
489
|
+
Changes to this constitution require:
|
490
|
+
1. Documented rationale
|
491
|
+
2. Team consensus
|
492
|
+
3. Gradual migration plan
|
493
|
+
4. Update to all affected documentation
|
494
|
+
"""
|
495
|
+
|
496
|
+
def get_context_template(self) -> str:
|
497
|
+
"""Get context template from file"""
|
498
|
+
template_path = self.resources_dir / "memory" / "context.md"
|
499
|
+
if template_path.exists():
|
500
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
501
|
+
return f.read()
|
502
|
+
# Fallback to embedded template if file not found
|
503
|
+
return """# Project Context
|
504
|
+
|
505
|
+
## Current State
|
506
|
+
Last Updated: [AI updates this automatically]
|
507
|
+
|
508
|
+
### Active Features
|
509
|
+
1. **[feature-name]** (SPEC-XXX)
|
510
|
+
- Status: [Phase]
|
511
|
+
- Branch: [branch-name]
|
512
|
+
- Blockers: [None|List]
|
513
|
+
|
514
|
+
### Recent Decisions
|
515
|
+
- [Decision with rationale]
|
516
|
+
|
517
|
+
### Known Issues
|
518
|
+
- [Issue description]
|
519
|
+
|
520
|
+
## Team Preferences
|
521
|
+
|
522
|
+
### Technology Choices
|
523
|
+
- **Preferred Stack**: [Stack]
|
524
|
+
- **Testing**: [Framework]
|
525
|
+
- **CI/CD**: [Platform]
|
526
|
+
- **Deployment**: [Method]
|
527
|
+
|
528
|
+
### Coding Patterns
|
529
|
+
- [Pattern preference]
|
530
|
+
|
531
|
+
## Project Glossary
|
532
|
+
|
533
|
+
### Domain Terms
|
534
|
+
- **[Term]**: [Definition]
|
535
|
+
|
536
|
+
### Technical Terms
|
537
|
+
- **[Term]**: [Definition]
|
538
|
+
"""
|
539
|
+
|
540
|
+
def get_decisions_template(self) -> str:
|
541
|
+
"""Get architectural decisions template from file"""
|
542
|
+
template_path = self.resources_dir / "memory" / "decisions.md"
|
543
|
+
if template_path.exists():
|
544
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
545
|
+
return f.read()
|
546
|
+
# Fallback to embedded template if file not found
|
547
|
+
return """# Architectural Decisions
|
548
|
+
|
549
|
+
## Decision Log
|
550
|
+
|
551
|
+
### ADR-001: [Title]
|
552
|
+
**Date**: [DATE]
|
553
|
+
**Status**: [PROPOSED|ACCEPTED|DEPRECATED]
|
554
|
+
**Context**: [Why this decision was needed]
|
555
|
+
**Decision**: [What was decided]
|
556
|
+
**Consequences**: [What happens as a result]
|
557
|
+
**Alternatives Considered**: [Other options that were evaluated]
|
558
|
+
|
559
|
+
---
|
560
|
+
|
561
|
+
### ADR-002: [Title]
|
562
|
+
[Same structure as above]
|
563
|
+
"""
|
564
|
+
|
565
|
+
def get_setup_script(self) -> str:
|
566
|
+
"""Get pulse-init script for feature initialization from file"""
|
567
|
+
script_path = self.resources_dir / "scripts" / "pulse-init.sh"
|
568
|
+
if script_path.exists():
|
569
|
+
with open(script_path, 'r', encoding='utf-8') as f:
|
570
|
+
return f.read()
|
571
|
+
# Fallback to embedded script if file not found
|
572
|
+
return """#!/bin/bash
|
573
|
+
# SpecPulse Feature Initialization Script
|
574
|
+
|
575
|
+
set -e
|
576
|
+
|
577
|
+
# Get feature name from argument
|
578
|
+
FEATURE_NAME="$1"
|
579
|
+
if [ -z "$FEATURE_NAME" ]; then
|
580
|
+
echo "Error: Feature name required"
|
581
|
+
exit 1
|
582
|
+
fi
|
583
|
+
|
584
|
+
# Clean feature name (replace spaces with hyphens, lowercase)
|
585
|
+
CLEAN_NAME=$(echo "$FEATURE_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr '_' '-')
|
586
|
+
|
587
|
+
# Get next feature number
|
588
|
+
if [ -d "specs" ]; then
|
589
|
+
FEATURE_NUM=$(find specs -maxdepth 1 -type d -name "[0-9][0-9][0-9]-*" | wc -l)
|
590
|
+
FEATURE_NUM=$((FEATURE_NUM + 1))
|
591
|
+
else
|
592
|
+
FEATURE_NUM=1
|
593
|
+
fi
|
594
|
+
|
595
|
+
# Format with leading zeros
|
596
|
+
FEATURE_ID=$(printf "%03d" $FEATURE_NUM)
|
597
|
+
BRANCH_NAME="${FEATURE_ID}-${CLEAN_NAME}"
|
598
|
+
|
599
|
+
# Create directories
|
600
|
+
mkdir -p "specs/${BRANCH_NAME}"
|
601
|
+
mkdir -p "plans/${BRANCH_NAME}"
|
602
|
+
mkdir -p "tasks/${BRANCH_NAME}"
|
603
|
+
|
604
|
+
# Create feature branch if git is available
|
605
|
+
if command -v git &> /dev/null && [ -d ".git" ]; then
|
606
|
+
git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
|
607
|
+
fi
|
608
|
+
|
609
|
+
# Output JSON result
|
610
|
+
echo "{"
|
611
|
+
echo " \\"branch_name\\": \\"$BRANCH_NAME\\","
|
612
|
+
echo " \\"feature_id\\": \\"$FEATURE_ID\\","
|
613
|
+
echo " \\"spec_dir\\": \\"specs/$BRANCH_NAME\\","
|
614
|
+
echo " \\"plan_dir\\": \\"plans/$BRANCH_NAME\\","
|
615
|
+
echo " \\"task_dir\\": \\"tasks/$BRANCH_NAME\\""
|
616
|
+
echo "}"
|
617
|
+
"""
|
618
|
+
|
619
|
+
def get_spec_script(self) -> str:
|
620
|
+
"""Get pulse-spec script for getting current feature context from file"""
|
621
|
+
script_path = self.resources_dir / "scripts" / "pulse-spec.sh"
|
622
|
+
if script_path.exists():
|
623
|
+
with open(script_path, 'r', encoding='utf-8') as f:
|
624
|
+
return f.read()
|
625
|
+
# Fallback to embedded script if file not found
|
626
|
+
return """#!/bin/bash
|
627
|
+
# SpecPulse Spec Context Script
|
628
|
+
|
629
|
+
# Check for --current flag
|
630
|
+
if [ "$1" == "--current" ]; then
|
631
|
+
# Find the current feature branch
|
632
|
+
if command -v git &> /dev/null && [ -d ".git" ]; then
|
633
|
+
BRANCH=$(git branch --show-current)
|
634
|
+
if [[ "$BRANCH" =~ ^[0-9]{3}-.* ]]; then
|
635
|
+
FEATURE_DIR="specs/$BRANCH"
|
636
|
+
if [ -d "$FEATURE_DIR" ]; then
|
637
|
+
echo "{"
|
638
|
+
echo " \\"branch\\": \\"$BRANCH\\","
|
639
|
+
echo " \\"spec_file\\": \\"$FEATURE_DIR/spec-001.md\\","
|
640
|
+
echo " \\"spec_dir\\": \\"$FEATURE_DIR\\""
|
641
|
+
echo "}"
|
642
|
+
exit 0
|
643
|
+
fi
|
644
|
+
fi
|
645
|
+
fi
|
646
|
+
|
647
|
+
# Fallback: find latest spec directory
|
648
|
+
LATEST=$(find specs -maxdepth 1 -type d -name "[0-9][0-9][0-9]-*" | sort -r | head -1)
|
649
|
+
if [ -n "$LATEST" ]; then
|
650
|
+
echo "{"
|
651
|
+
echo " \\"branch\\": \\"$(basename $LATEST)\\","
|
652
|
+
echo " \\"spec_file\\": \\"$LATEST/spec-001.md\\","
|
653
|
+
echo " \\"spec_dir\\": \\"$LATEST\\""
|
654
|
+
echo "}"
|
655
|
+
else
|
656
|
+
echo "{\\"error\\": \\"No active feature found\\"}"
|
657
|
+
exit 1
|
658
|
+
fi
|
659
|
+
fi
|
660
|
+
"""
|
661
|
+
|
662
|
+
def get_plan_script(self) -> str:
|
663
|
+
"""Get pulse-plan script for plan context from file"""
|
664
|
+
script_path = self.resources_dir / "scripts" / "pulse-plan.sh"
|
665
|
+
if script_path.exists():
|
666
|
+
with open(script_path, 'r', encoding='utf-8') as f:
|
667
|
+
return f.read()
|
668
|
+
# Fallback to embedded script if file not found
|
669
|
+
return """#!/bin/bash
|
670
|
+
# SpecPulse Plan Context Script
|
671
|
+
|
672
|
+
# Check for --current flag
|
673
|
+
if [ "$1" == "--current" ]; then
|
674
|
+
# Find the current feature branch
|
675
|
+
if command -v git &> /dev/null && [ -d ".git" ]; then
|
676
|
+
BRANCH=$(git branch --show-current)
|
677
|
+
if [[ "$BRANCH" =~ ^[0-9]{3}-.* ]]; then
|
678
|
+
SPEC_DIR="specs/$BRANCH"
|
679
|
+
PLAN_DIR="plans/$BRANCH"
|
680
|
+
if [ -d "$SPEC_DIR" ]; then
|
681
|
+
echo "{"
|
682
|
+
echo " \\"branch\\": \\"$BRANCH\\","
|
683
|
+
echo " \\"spec_file\\": \\"$SPEC_DIR/spec-001.md\\","
|
684
|
+
echo " \\"plan_file\\": \\"$PLAN_DIR/plan-001.md\\","
|
685
|
+
echo " \\"plan_dir\\": \\"$PLAN_DIR\\""
|
686
|
+
echo "}"
|
687
|
+
exit 0
|
688
|
+
fi
|
689
|
+
fi
|
690
|
+
fi
|
691
|
+
|
692
|
+
# Fallback: find latest directories
|
693
|
+
LATEST=$(find specs -maxdepth 1 -type d -name "[0-9][0-9][0-9]-*" | sort -r | head -1)
|
694
|
+
if [ -n "$LATEST" ]; then
|
695
|
+
BRANCH=$(basename "$LATEST")
|
696
|
+
echo "{"
|
697
|
+
echo " \\"branch\\": \\"$BRANCH\\","
|
698
|
+
echo " \\"spec_file\\": \\"specs/$BRANCH/spec-001.md\\","
|
699
|
+
echo " \\"plan_file\\": \\"plans/$BRANCH/plan-001.md\\","
|
700
|
+
echo " \\"plan_dir\\": \\"plans/$BRANCH\\""
|
701
|
+
echo "}"
|
702
|
+
else
|
703
|
+
echo "{\\"error\\": \\"No active feature found\\"}"
|
704
|
+
exit 1
|
705
|
+
fi
|
706
|
+
fi
|
707
|
+
"""
|
708
|
+
|
709
|
+
def get_task_script(self) -> str:
|
710
|
+
"""Get pulse-task script for task context from file"""
|
711
|
+
script_path = self.resources_dir / "scripts" / "pulse-task.sh"
|
712
|
+
if script_path.exists():
|
713
|
+
with open(script_path, 'r', encoding='utf-8') as f:
|
714
|
+
return f.read()
|
715
|
+
# Fallback to embedded script if file not found
|
716
|
+
return """#!/bin/bash
|
717
|
+
# SpecPulse Task Context Script
|
718
|
+
|
719
|
+
# Check for --current flag
|
720
|
+
if [ "$1" == "--current" ]; then
|
721
|
+
# Find the current feature branch
|
722
|
+
if command -v git &> /dev/null && [ -d ".git" ]; then
|
723
|
+
BRANCH=$(git branch --show-current)
|
724
|
+
if [[ "$BRANCH" =~ ^[0-9]{3}-.* ]]; then
|
725
|
+
SPEC_DIR="specs/$BRANCH"
|
726
|
+
PLAN_DIR="plans/$BRANCH"
|
727
|
+
TASK_DIR="tasks/$BRANCH"
|
728
|
+
if [ -d "$SPEC_DIR" ]; then
|
729
|
+
echo "{"
|
730
|
+
echo " \\"branch\\": \\"$BRANCH\\","
|
731
|
+
echo " \\"spec_file\\": \\"$SPEC_DIR/spec-001.md\\","
|
732
|
+
echo " \\"plan_file\\": \\"$PLAN_DIR/plan-001.md\\","
|
733
|
+
echo " \\"task_file\\": \\"$TASK_DIR/task-001.md\\","
|
734
|
+
echo " \\"task_dir\\": \\"$TASK_DIR\\""
|
735
|
+
echo "}"
|
736
|
+
exit 0
|
737
|
+
fi
|
738
|
+
fi
|
739
|
+
fi
|
740
|
+
|
741
|
+
# Fallback: find latest directories
|
742
|
+
LATEST=$(find specs -maxdepth 1 -type d -name "[0-9][0-9][0-9]-*" | sort -r | head -1)
|
743
|
+
if [ -n "$LATEST" ]; then
|
744
|
+
BRANCH=$(basename "$LATEST")
|
745
|
+
echo "{"
|
746
|
+
echo " \\"branch\\": \\"$BRANCH\\","
|
747
|
+
echo " \\"spec_file\\": \\"specs/$BRANCH/spec-001.md\\","
|
748
|
+
echo " \\"plan_file\\": \\"plans/$BRANCH/plan-001.md\\","
|
749
|
+
echo " \\"task_file\\": \\"tasks/$BRANCH/task-001.md\\","
|
750
|
+
echo " \\"task_dir\\": \\"tasks/$BRANCH\\""
|
751
|
+
echo "}"
|
752
|
+
else
|
753
|
+
echo "{\\"error\\": \\"No active feature found\\"}"
|
754
|
+
exit 1
|
755
|
+
fi
|
756
|
+
fi
|
757
|
+
"""
|
758
|
+
|
759
|
+
def get_validate_script(self) -> str:
|
760
|
+
"""Get validation script"""
|
761
|
+
return """#!/bin/bash
|
762
|
+
# SpecPulse Validation Script
|
763
|
+
|
764
|
+
validate_spec() {
|
765
|
+
local spec_file=$1
|
766
|
+
local errors=0
|
767
|
+
|
768
|
+
echo "Validating: $spec_file"
|
769
|
+
|
770
|
+
# Check required sections
|
771
|
+
if ! grep -q "## Requirements" $spec_file; then
|
772
|
+
echo " ❌ Missing Requirements section"
|
773
|
+
((errors++))
|
774
|
+
fi
|
775
|
+
|
776
|
+
if ! grep -q "## User Stories" $spec_file; then
|
777
|
+
echo " ❌ Missing User Stories section"
|
778
|
+
((errors++))
|
779
|
+
fi
|
780
|
+
|
781
|
+
if ! grep -q "## Acceptance Criteria" $spec_file; then
|
782
|
+
echo " ❌ Missing Acceptance Criteria section"
|
783
|
+
((errors++))
|
784
|
+
fi
|
785
|
+
|
786
|
+
# Check for clarification markers
|
787
|
+
if grep -q "\\[NEEDS CLARIFICATION\\]" $spec_file; then
|
788
|
+
echo " ⚠️ Contains items needing clarification"
|
789
|
+
fi
|
790
|
+
|
791
|
+
if [ $errors -eq 0 ]; then
|
792
|
+
echo " ✅ Specification valid"
|
793
|
+
return 0
|
794
|
+
else
|
795
|
+
echo " ❌ Specification has $errors errors"
|
796
|
+
return 1
|
797
|
+
fi
|
798
|
+
}
|
799
|
+
|
800
|
+
# Main
|
801
|
+
if [ "$1" == "spec" ]; then
|
802
|
+
validate_spec $2
|
803
|
+
elif [ "$1" == "all" ]; then
|
804
|
+
for spec in specs/*/spec-001.md; do
|
805
|
+
validate_spec $spec
|
806
|
+
done
|
807
|
+
fi
|
808
|
+
"""
|
809
|
+
|
810
|
+
def get_generate_script(self) -> str:
|
811
|
+
"""Get generation script"""
|
812
|
+
return """#!/bin/bash
|
813
|
+
# SpecPulse Generation Script
|
814
|
+
|
815
|
+
generate_from_template() {
|
816
|
+
local template=$1
|
817
|
+
local output=$2
|
818
|
+
local feature_name=$3
|
819
|
+
|
820
|
+
# Replace placeholders
|
821
|
+
sed "s/\\[FEATURE_NAME\\]/$feature_name/g" $template > $output
|
822
|
+
sed -i "s/\\[DATE\\]/$(date +%Y-%m-%d)/g" $output
|
823
|
+
sed -i "s/\\[XXX\\]/$(printf '%03d' $RANDOM)/g" $output
|
824
|
+
|
825
|
+
echo "Generated: $output"
|
826
|
+
}
|
827
|
+
|
828
|
+
# Main
|
829
|
+
if [ "$1" == "spec" ]; then
|
830
|
+
generate_from_template templates/spec-001.md $2 $3
|
831
|
+
elif [ "$1" == "plan" ]; then
|
832
|
+
generate_from_template templates/plan-001.md $2 $3
|
833
|
+
elif [ "$1" == "task" ]; then
|
834
|
+
generate_from_template templates/task.md $2 $3
|
835
|
+
fi
|
836
|
+
"""
|
837
|
+
|
838
|
+
def get_claude_instructions(self) -> str:
|
839
|
+
"""Get Claude instructions"""
|
840
|
+
return """# SpecPulse Commands for Claude
|
841
|
+
|
842
|
+
You have access to SpecPulse commands for specification-driven development.
|
843
|
+
|
844
|
+
## Available Commands
|
845
|
+
|
846
|
+
### /sp-pulse <feature-name>
|
847
|
+
Initializes a new feature with proper structure.
|
848
|
+
- Creates feature branch
|
849
|
+
- Sets up specification directory
|
850
|
+
- Loads templates
|
851
|
+
- Updates context
|
852
|
+
|
853
|
+
### /sp-spec create <description>
|
854
|
+
Creates a detailed specification from description.
|
855
|
+
- Use the template in templates/spec-001.md
|
856
|
+
- Mark uncertainties with [NEEDS CLARIFICATION]
|
857
|
+
- Ensure all sections are complete
|
858
|
+
- Validate against constitution
|
859
|
+
|
860
|
+
### /sp-plan generate
|
861
|
+
Generates implementation plan from current specification.
|
862
|
+
- Read the active specification
|
863
|
+
- Create detailed phases
|
864
|
+
- Include technology decisions
|
865
|
+
- Add time estimates
|
866
|
+
|
867
|
+
### /sp-task breakdown
|
868
|
+
Creates task list from implementation plan.
|
869
|
+
- Identify dependencies
|
870
|
+
- Mark parallel tasks with [P]
|
871
|
+
- Add time estimates
|
872
|
+
- Create critical path
|
873
|
+
|
874
|
+
### /validate <component>
|
875
|
+
Validates specifications, plans, or project.
|
876
|
+
- Check completeness
|
877
|
+
- Verify consistency
|
878
|
+
- Ensure constitution compliance
|
879
|
+
|
880
|
+
## Workflow
|
881
|
+
|
882
|
+
1. User requests feature → Use `/sp-pulse`
|
883
|
+
2. User describes requirements → Use `/sp-spec create`
|
884
|
+
3. Specification complete → Use `/sp-plan generate`
|
885
|
+
4. Plan approved → Use `/sp-task breakdown`
|
886
|
+
5. Before implementation → Use `/validate all`
|
887
|
+
|
888
|
+
## Constitution Rules
|
889
|
+
|
890
|
+
Always enforce these principles:
|
891
|
+
1. Simplicity first
|
892
|
+
2. Test-driven development
|
893
|
+
3. Single responsibility
|
894
|
+
4. Documentation as code
|
895
|
+
5. Security by design
|
896
|
+
|
897
|
+
## Context Management
|
898
|
+
|
899
|
+
- Read `memory/context.md` for project state
|
900
|
+
- Update context after major decisions
|
901
|
+
- Check `memory/constitution.md` for principles
|
902
|
+
- Reference previous specs for consistency
|
903
|
+
|
904
|
+
## Templates
|
905
|
+
|
906
|
+
Always use templates from `templates/` directory:
|
907
|
+
- `spec-001.md` for specifications
|
908
|
+
- `plan-001.md` for implementation plans
|
909
|
+
- `task.md` for task lists
|
910
|
+
|
911
|
+
## Best Practices
|
912
|
+
|
913
|
+
1. Always validate before moving to next phase
|
914
|
+
2. Keep specifications testable and measurable
|
915
|
+
3. Update context.md with decisions
|
916
|
+
4. Create atomic, focused commits
|
917
|
+
5. Document rationale for technology choices
|
918
|
+
"""
|
919
|
+
|
920
|
+
# Claude command getters
|
921
|
+
def get_claude_pulse_command(self) -> str:
|
922
|
+
"""Get Claude pulse command"""
|
923
|
+
command_path = self.resources_dir / "commands" / "claude" / "pulse.md"
|
924
|
+
if command_path.exists():
|
925
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
926
|
+
return f.read()
|
927
|
+
return "# /sp-pulse command not found"
|
928
|
+
|
929
|
+
def get_claude_spec_command(self) -> str:
|
930
|
+
"""Get Claude spec command"""
|
931
|
+
command_path = self.resources_dir / "commands" / "claude" / "spec-001.md"
|
932
|
+
if command_path.exists():
|
933
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
934
|
+
return f.read()
|
935
|
+
return "# /sp-spec command not found"
|
936
|
+
|
937
|
+
def get_claude_plan_command(self) -> str:
|
938
|
+
"""Get Claude plan command"""
|
939
|
+
command_path = self.resources_dir / "commands" / "claude" / "plan-001.md"
|
940
|
+
if command_path.exists():
|
941
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
942
|
+
return f.read()
|
943
|
+
return "# /sp-plan command not found"
|
944
|
+
|
945
|
+
def get_claude_task_command(self) -> str:
|
946
|
+
"""Get Claude task command"""
|
947
|
+
command_path = self.resources_dir / "commands" / "claude" / "task.md"
|
948
|
+
if command_path.exists():
|
949
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
950
|
+
return f.read()
|
951
|
+
return "# /sp-task command not found"
|
952
|
+
|
953
|
+
# Gemini command getters
|
954
|
+
def get_gemini_pulse_command(self) -> str:
|
955
|
+
"""Get Gemini pulse command"""
|
956
|
+
command_path = self.resources_dir / "commands" / "gemini" / "pulse.toml"
|
957
|
+
if command_path.exists():
|
958
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
959
|
+
return f.read()
|
960
|
+
return "# Gemini pulse command not found"
|
961
|
+
|
962
|
+
def get_gemini_spec_command(self) -> str:
|
963
|
+
"""Get Gemini spec command"""
|
964
|
+
command_path = self.resources_dir / "commands" / "gemini" / "spec.toml"
|
965
|
+
if command_path.exists():
|
966
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
967
|
+
return f.read()
|
968
|
+
return "# Gemini spec command not found"
|
969
|
+
|
970
|
+
def get_gemini_plan_command(self) -> str:
|
971
|
+
"""Get Gemini plan command"""
|
972
|
+
command_path = self.resources_dir / "commands" / "gemini" / "plan.toml"
|
973
|
+
if command_path.exists():
|
974
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
975
|
+
return f.read()
|
976
|
+
return "# Gemini plan command not found"
|
977
|
+
|
978
|
+
def get_gemini_task_command(self) -> str:
|
979
|
+
"""Get Gemini task command"""
|
980
|
+
command_path = self.resources_dir / "commands" / "gemini" / "task.toml"
|
981
|
+
if command_path.exists():
|
982
|
+
with open(command_path, 'r', encoding='utf-8') as f:
|
983
|
+
return f.read()
|
984
|
+
return "# Gemini task command not found"
|
985
|
+
|
986
|
+
def get_gemini_instructions(self) -> str:
|
987
|
+
"""Get Gemini instructions"""
|
988
|
+
return """# SpecPulse Commands for Gemini CLI
|
989
|
+
|
990
|
+
This project uses SpecPulse for specification-driven development.
|
991
|
+
|
992
|
+
## Command Reference
|
993
|
+
|
994
|
+
### Initialization
|
995
|
+
```
|
996
|
+
/sp-pulse <feature-name>
|
997
|
+
```
|
998
|
+
Creates new feature structure and branch.
|
999
|
+
|
1000
|
+
### Specification Creation
|
1001
|
+
```
|
1002
|
+
/sp-spec create <description>
|
1003
|
+
```
|
1004
|
+
Generates detailed specification from natural language.
|
1005
|
+
|
1006
|
+
Required sections:
|
1007
|
+
- Requirements (functional and non-functional)
|
1008
|
+
- User stories with acceptance criteria
|
1009
|
+
- Technical constraints
|
1010
|
+
- Dependencies
|
1011
|
+
- Risks and mitigations
|
1012
|
+
|
1013
|
+
### Plan Generation
|
1014
|
+
```
|
1015
|
+
/sp-plan generate [--optimize <focus>]
|
1016
|
+
```
|
1017
|
+
Creates implementation plan from specification.
|
1018
|
+
|
1019
|
+
Optimization options:
|
1020
|
+
- performance: Speed and efficiency focus
|
1021
|
+
- security: Security-first approach
|
1022
|
+
- simplicity: Maintainable solution
|
1023
|
+
- cost: Resource optimization
|
1024
|
+
|
1025
|
+
### Task Breakdown
|
1026
|
+
```
|
1027
|
+
/sp-task breakdown [--parallel]
|
1028
|
+
```
|
1029
|
+
Generates actionable task list.
|
1030
|
+
|
1031
|
+
Features:
|
1032
|
+
- Dependency detection
|
1033
|
+
- Parallel task identification
|
1034
|
+
- Time estimation
|
1035
|
+
- Critical path analysis
|
1036
|
+
|
1037
|
+
### Validation
|
1038
|
+
```
|
1039
|
+
/validate [all|spec|plan|constitution]
|
1040
|
+
```
|
1041
|
+
Validates project components.
|
1042
|
+
|
1043
|
+
## Templates Location
|
1044
|
+
|
1045
|
+
Use templates from `templates/` directory:
|
1046
|
+
- Specification: templates/spec-001.md
|
1047
|
+
- Implementation: templates/plan-001.md
|
1048
|
+
- Tasks: templates/task.md
|
1049
|
+
|
1050
|
+
## Memory System
|
1051
|
+
|
1052
|
+
Project memory in `memory/` directory:
|
1053
|
+
- constitution.md: Immutable principles
|
1054
|
+
- context.md: Current project state
|
1055
|
+
- decisions.md: Architectural decisions
|
1056
|
+
|
1057
|
+
## Workflow Process
|
1058
|
+
|
1059
|
+
1. **Initialize Feature**
|
1060
|
+
- Run: `/sp-pulse feature-name`
|
1061
|
+
- Creates branch and structure
|
1062
|
+
|
1063
|
+
2. **Create Specification**
|
1064
|
+
- Run: `/sp-spec create "description"`
|
1065
|
+
- Fill template completely
|
1066
|
+
- Mark unclear items: [NEEDS CLARIFICATION]
|
1067
|
+
|
1068
|
+
3. **Generate Plan**
|
1069
|
+
- Run: `/sp-plan generate`
|
1070
|
+
- Choose optimization focus
|
1071
|
+
- Review technology choices
|
1072
|
+
|
1073
|
+
4. **Create Tasks**
|
1074
|
+
- Run: `/sp-task breakdown`
|
1075
|
+
- Review dependencies
|
1076
|
+
- Check time estimates
|
1077
|
+
|
1078
|
+
5. **Validate**
|
1079
|
+
- Run: `/validate all`
|
1080
|
+
- Fix any issues
|
1081
|
+
- Proceed to implementation
|
1082
|
+
|
1083
|
+
## Constitution Principles
|
1084
|
+
|
1085
|
+
Enforce these rules:
|
1086
|
+
1. Start simple, add complexity only when needed
|
1087
|
+
2. Write tests before code
|
1088
|
+
3. One responsibility per component
|
1089
|
+
4. Document everything
|
1090
|
+
5. Consider security from start
|
1091
|
+
|
1092
|
+
## Project Structure
|
1093
|
+
|
1094
|
+
```
|
1095
|
+
project/
|
1096
|
+
├── specs/ # Specifications
|
1097
|
+
├── plans/ # Implementation plans
|
1098
|
+
├── tasks/ # Task lists
|
1099
|
+
├── memory/ # Project memory
|
1100
|
+
├── scripts/ # Automation
|
1101
|
+
└── templates/ # Templates
|
1102
|
+
```
|
1103
|
+
|
1104
|
+
## Important Notes
|
1105
|
+
|
1106
|
+
- Always update context.md after decisions
|
1107
|
+
- Validate specifications before planning
|
1108
|
+
- Use [P] marker for parallel tasks
|
1109
|
+
- Keep commits atomic and focused
|
1110
|
+
- Reference constitution for all decisions
|
1106
1111
|
"""
|