specpulse 1.4.3__py3-none-any.whl → 1.4.4__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.
@@ -82,15 +82,34 @@ if ($taskContent -match "AUTH-T[0-9]|USER-T[0-9]|INT-T[0-9]") {
82
82
  Log-Message "Detected decomposed architecture with service-specific tasks"
83
83
  }
84
84
 
85
- # Count task status using regex
86
- $taskPattern = '^- \[.\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})'
87
- $allTasks = [regex]::Matches($taskContent, $taskPattern, [System.Text.RegularExpressions.RegexOptions]::Multiline)
88
- $TotalTasks = $allTasks.Count
89
-
90
- $CompletedTasks = ([regex]::Matches($taskContent, '^- \[x\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})', [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
91
- $PendingTasks = ([regex]::Matches($taskContent, '^- \[ \] (T[0-9]{3}|[A-Z]+-T[0-9]{3})', [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
92
- $InProgressTasks = ([regex]::Matches($taskContent, '^- \[>\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})', [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
93
- $BlockedTasks = ([regex]::Matches($taskContent, '^- \[!\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})', [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
85
+ # Count task status using the actual format used in task files
86
+ # Format is: ### T001: Task Name
87
+ # **Status**: [x] Completed
88
+ $TotalTasks = ([regex]::Matches($taskContent, '^### T[0-9]{3}:', [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
89
+
90
+ # Count completed tasks by finding task headers followed by status within next few lines
91
+ $CompletedTasks = 0
92
+ $PendingTasks = 0
93
+ $InProgressTasks = 0
94
+ $BlockedTasks = 0
95
+
96
+ $taskHeaders = [regex]::Matches($taskContent, '^### (T[0-9]{3}):', [System.Text.RegularExpressions.RegexOptions]::Multiline)
97
+ foreach ($header in $taskHeaders) {
98
+ $taskId = $header.Groups[1].Value
99
+ $startIndex = $header.Index
100
+ $endIndex = if ($header.Index + 500 -lt $taskContent.Length) { $header.Index + 500 } else { $taskContent.Length }
101
+ $taskSection = $taskContent.Substring($startIndex, $endIndex - $startIndex)
102
+
103
+ if ($taskSection -match '\*\*Status\*\*:\s*\[x\]') {
104
+ $CompletedTasks++
105
+ } elseif ($taskSection -match '\*\*Status\*\*:\s*\[ \]') {
106
+ $PendingTasks++
107
+ } elseif ($taskSection -match '\*\*Status\*\*:\s*\[>\]') {
108
+ $InProgressTasks++
109
+ } elseif ($taskSection -match '\*\*Status\*\*:\s*\[!\]') {
110
+ $BlockedTasks++
111
+ }
112
+ }
94
113
 
95
114
  # Find next task to execute
96
115
  $NextTask = ""
@@ -98,17 +117,34 @@ $TaskDetails = ""
98
117
 
99
118
  switch ($Command) {
100
119
  { $_ -in "next", "continue" } {
101
- # Find first in-progress task
102
- $inProgressMatch = [regex]::Match($taskContent, '^- \[>\] ((T[0-9]{3}|[A-Z]+-T[0-9]{3}): .+)$', [System.Text.RegularExpressions.RegexOptions]::Multiline)
103
- if ($inProgressMatch.Success) {
104
- $NextTask = $inProgressMatch.Groups[1].Value
105
- $TaskDetails = "RESUMING IN-PROGRESS TASK"
106
- } else {
107
- # Find first pending task
108
- $pendingMatch = [regex]::Match($taskContent, '^- \[ \] ((T[0-9]{3}|[A-Z]+-T[0-9]{3}): .+)$', [System.Text.RegularExpressions.RegexOptions]::Multiline)
109
- if ($pendingMatch.Success) {
110
- $NextTask = $pendingMatch.Groups[1].Value
111
- $TaskDetails = "STARTING NEW TASK"
120
+ # Find first in-progress or pending task
121
+ foreach ($header in $taskHeaders) {
122
+ $taskId = $header.Groups[1].Value
123
+ $startIndex = $header.Index
124
+ $endIndex = if ($header.Index + 500 -lt $taskContent.Length) { $header.Index + 500 } else { $taskContent.Length }
125
+ $taskSection = $taskContent.Substring($startIndex, $endIndex - $startIndex)
126
+
127
+ # Check for in-progress task first
128
+ if ($taskSection -match '\*\*Status\*\*:\s*\[>\]') {
129
+ $NextTask = $taskId
130
+ $TaskDetails = "RESUMING IN-PROGRESS TASK"
131
+ break
132
+ }
133
+ }
134
+
135
+ # If no in-progress task found, find first pending
136
+ if (-not $NextTask) {
137
+ foreach ($header in $taskHeaders) {
138
+ $taskId = $header.Groups[1].Value
139
+ $startIndex = $header.Index
140
+ $endIndex = if ($header.Index + 500 -lt $taskContent.Length) { $header.Index + 500 } else { $taskContent.Length }
141
+ $taskSection = $taskContent.Substring($startIndex, $endIndex - $startIndex)
142
+
143
+ if ($taskSection -match '\*\*Status\*\*:\s*\[ \]') {
144
+ $NextTask = $taskId
145
+ $TaskDetails = "STARTING NEW TASK"
146
+ break
147
+ }
112
148
  }
113
149
  }
114
150
  }
@@ -120,9 +156,8 @@ switch ($Command) {
120
156
  }
121
157
  default {
122
158
  # Specific task requested
123
- $specificMatch = [regex]::Match($taskContent, "^- \[.\] (($Command): .+)$", [System.Text.RegularExpressions.RegexOptions]::Multiline)
124
- if ($specificMatch.Success) {
125
- $NextTask = $specificMatch.Groups[1].Value
159
+ if ($taskContent -match "^### ($Command):" ) {
160
+ $NextTask = $Command
126
161
  $TaskDetails = "EXECUTE SPECIFIC TASK"
127
162
  }
128
163
  }
@@ -67,23 +67,23 @@ if grep -qE "AUTH-T[0-9]|USER-T[0-9]|INT-T[0-9]" "$TASK_FILE" 2>/dev/null; then
67
67
  log "Detected decomposed architecture with service-specific tasks"
68
68
  fi
69
69
 
70
- # Count task status
71
- TOTAL_TASKS=$(grep -cE "^- \[.\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" 2>/dev/null || echo "0")
72
- COMPLETED_TASKS=$(grep -cE "^- \[x\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" 2>/dev/null || echo "0")
73
- PENDING_TASKS=$(grep -cE "^- \[ \] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" 2>/dev/null || echo "0")
74
- IN_PROGRESS_TASKS=$(grep -cE "^- \[>\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" 2>/dev/null || echo "0")
75
- BLOCKED_TASKS=$(grep -cE "^- \[!\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" 2>/dev/null || echo "0")
70
+ # Count task status - handle the actual format used in task files
71
+ TOTAL_TASKS=$(grep -cE "^### T[0-9]{3}:" "$TASK_FILE" 2>/dev/null || echo "0")
72
+ COMPLETED_TASKS=$(awk '/^### T[0-9]{3}:/{task=$0; found=0; for(i=0; i<5; i++) {getline; if(/^\*\*Status\*\*: \[x\]/) {found=1; break} if(/^###/) break} if(found) count++} END{print count+0}' "$TASK_FILE" 2>/dev/null || echo "0")
73
+ PENDING_TASKS=$(awk '/^### T[0-9]{3}:/{task=$0; found=0; for(i=0; i<5; i++) {getline; if(/^\*\*Status\*\*: \[ \]/) {found=1; break} if(/^###/) break} if(found) count++} END{print count+0}' "$TASK_FILE" 2>/dev/null || echo "0")
74
+ IN_PROGRESS_TASKS=$(awk '/^### T[0-9]{3}:/{task=$0; found=0; for(i=0; i<5; i++) {getline; if(/^\*\*Status\*\*: \[>\]/) {found=1; break} if(/^###/) break} if(found) count++} END{print count+0}' "$TASK_FILE" 2>/dev/null || echo "0")
75
+ BLOCKED_TASKS=$(awk '/^### T[0-9]{3}:/{task=$0; found=0; for(i=0; i<5; i++) {getline; if(/^\*\*Status\*\*: \[!\]/) {found=1; break} if(/^###/) break} if(found) count++} END{print count+0}' "$TASK_FILE" 2>/dev/null || echo "0")
76
76
 
77
77
  # Find next task to execute
78
78
  case "$COMMAND" in
79
79
  "next"|"continue")
80
80
  # Find first in-progress task
81
81
  if [ "$IN_PROGRESS_TASKS" -gt 0 ]; then
82
- NEXT_TASK=$(grep -E "^- \[>\] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" | head -1 | sed -E 's/.*\[(T[0-9]{3}|[A-Z]+-T[0-9]{3})\].*/\1/')
82
+ NEXT_TASK=$(grep "^\*\*Status\*\*: \[>\]" "$TASK_FILE" -B1 | grep -E "^### T[0-9]{3}:" | head -1 | sed -E 's/^### (T[0-9]{3}):.*/\1/')
83
83
  log "Resuming in-progress task: $NEXT_TASK"
84
84
  # Otherwise find first pending task
85
85
  elif [ "$PENDING_TASKS" -gt 0 ]; then
86
- NEXT_TASK=$(grep -E "^- \[ \] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" | head -1 | sed -E 's/.*\[(T[0-9]{3}|[A-Z]+-T[0-9]{3})\].*/\1/')
86
+ NEXT_TASK=$(grep "^\*\*Status\*\*: \[ \]" "$TASK_FILE" -B1 | grep -E "^### T[0-9]{3}:" | head -1 | sed -E 's/^### (T[0-9]{3}):.*/\1/')
87
87
  log "Starting next pending task: $NEXT_TASK"
88
88
  else
89
89
  if [ "$BLOCKED_TASKS" -gt 0 ]; then
@@ -147,7 +147,7 @@ fi
147
147
  if [ "$PENDING_TASKS" -gt 0 ]; then
148
148
  echo ""
149
149
  echo "NEXT_TASKS_PREVIEW:"
150
- grep -E "^- \[ \] (T[0-9]{3}|[A-Z]+-T[0-9]{3})" "$TASK_FILE" | head -5 | while read -r line; do
150
+ awk '/^### T[0-9]{3}:/{task=$0; found=0; for(i=0; i<5; i++) {getline; if(/^\*\*Status\*\*: \[ \]/) {found=1; break} if(/^###/) break} if(found) {print task; count++; if(count>=5) exit}}' "$TASK_FILE" | while read -r line; do
151
151
  echo " $line"
152
152
  done
153
153
  fi
@@ -78,27 +78,30 @@ try {
78
78
  $specContent = @"
79
79
  # Specification for $FeatureName
80
80
 
81
- <!-- TO BE GENERATED FROM TEMPLATE: $TemplateDir\spec.md -->
82
- <!-- FEATURE: $FeatureName -->
83
- <!-- ID: $FeatureId -->
81
+ <!-- INSTRUCTION: Generate specification content using template: $TemplateDir\spec.md -->
82
+ <!-- FEATURE_DIR: $BranchName -->
83
+ <!-- FEATURE_ID: $FeatureId -->
84
84
  "@
85
85
  Set-Content -Path "$SpecsDir\spec-001.md" -Value $specContent
86
86
 
87
87
  $planContent = @"
88
88
  # Implementation Plan for $FeatureName
89
89
 
90
- <!-- TO BE GENERATED FROM TEMPLATE: $TemplateDir\plan.md -->
91
- <!-- FEATURE: $FeatureName -->
92
- <!-- ID: $FeatureId -->
90
+ <!-- INSTRUCTION: Generate plan using template: $TemplateDir\plan.md -->
91
+ <!-- SPEC_FILE: $SpecsDir\spec-001.md -->
92
+ <!-- FEATURE_DIR: $BranchName -->
93
+ <!-- FEATURE_ID: $FeatureId -->
93
94
  "@
94
95
  Set-Content -Path "$PlansDir\plan-001.md" -Value $planContent
95
96
 
96
97
  $taskContent = @"
97
98
  # Task Breakdown for $FeatureName
98
99
 
99
- <!-- TO BE GENERATED FROM TEMPLATE: $TemplateDir\task.md -->
100
- <!-- FEATURE: $FeatureName -->
101
- <!-- ID: $FeatureId -->
100
+ <!-- INSTRUCTION: Generate tasks using template: $TemplateDir\task.md -->
101
+ <!-- SPEC_FILE: $SpecsDir\spec-001.md -->
102
+ <!-- PLAN_FILE: $PlansDir\plan-001.md -->
103
+ <!-- FEATURE_DIR: $BranchName -->
104
+ <!-- FEATURE_ID: $FeatureId -->
102
105
  "@
103
106
  Set-Content -Path "$TasksDir\task-001.md" -Value $taskContent
104
107
  } catch {
@@ -73,19 +73,22 @@ echo "# Task Breakdown for $FEATURE_NAME" > "$TASKS_DIR/task-001.md"
73
73
 
74
74
  # Add markers indicating these files need AI processing
75
75
  echo "" >> "$SPECS_DIR/spec-001.md"
76
- echo "<!-- TO BE GENERATED FROM TEMPLATE: $TEMPLATE_DIR/spec.md -->" >> "$SPECS_DIR/spec-001.md"
77
- echo "<!-- FEATURE: $FEATURE_NAME -->" >> "$SPECS_DIR/spec-001.md"
78
- echo "<!-- ID: $FEATURE_ID -->" >> "$SPECS_DIR/spec-001.md"
76
+ echo "<!-- INSTRUCTION: Generate specification content using template: $TEMPLATE_DIR/spec.md -->" >> "$SPECS_DIR/spec-001.md"
77
+ echo "<!-- FEATURE_DIR: $BRANCH_NAME -->" >> "$SPECS_DIR/spec-001.md"
78
+ echo "<!-- FEATURE_ID: $FEATURE_ID -->" >> "$SPECS_DIR/spec-001.md"
79
79
 
80
80
  echo "" >> "$PLANS_DIR/plan-001.md"
81
- echo "<!-- TO BE GENERATED FROM TEMPLATE: $TEMPLATE_DIR/plan.md -->" >> "$PLANS_DIR/plan-001.md"
82
- echo "<!-- FEATURE: $FEATURE_NAME -->" >> "$PLANS_DIR/plan-001.md"
83
- echo "<!-- ID: $FEATURE_ID -->" >> "$PLANS_DIR/plan-001.md"
81
+ echo "<!-- INSTRUCTION: Generate plan using template: $TEMPLATE_DIR/plan.md -->" >> "$PLANS_DIR/plan-001.md"
82
+ echo "<!-- SPEC_FILE: $SPECS_DIR/spec-001.md -->" >> "$PLANS_DIR/plan-001.md"
83
+ echo "<!-- FEATURE_DIR: $BRANCH_NAME -->" >> "$PLANS_DIR/plan-001.md"
84
+ echo "<!-- FEATURE_ID: $FEATURE_ID -->" >> "$PLANS_DIR/plan-001.md"
84
85
 
85
86
  echo "" >> "$TASKS_DIR/task-001.md"
86
- echo "<!-- TO BE GENERATED FROM TEMPLATE: $TEMPLATE_DIR/task.md -->" >> "$TASKS_DIR/task-001.md"
87
- echo "<!-- FEATURE: $FEATURE_NAME -->" >> "$TASKS_DIR/task-001.md"
88
- echo "<!-- ID: $FEATURE_ID -->" >> "$TASKS_DIR/task-001.md"
87
+ echo "<!-- INSTRUCTION: Generate tasks using template: $TEMPLATE_DIR/task.md -->" >> "$TASKS_DIR/task-001.md"
88
+ echo "<!-- SPEC_FILE: $SPECS_DIR/spec-001.md -->" >> "$TASKS_DIR/task-001.md"
89
+ echo "<!-- PLAN_FILE: $PLANS_DIR/plan-001.md -->" >> "$TASKS_DIR/task-001.md"
90
+ echo "<!-- FEATURE_DIR: $BRANCH_NAME -->" >> "$TASKS_DIR/task-001.md"
91
+ echo "<!-- FEATURE_ID: $FEATURE_ID -->" >> "$TASKS_DIR/task-001.md"
89
92
 
90
93
  # Update context
91
94
  CONTEXT_FILE="$PROJECT_ROOT/memory/context.md"
@@ -57,9 +57,20 @@ if (Test-Path $SpecDir) {
57
57
  Exit-WithError "Specifications directory not found: $SpecDir. Please create specification first."
58
58
  }
59
59
 
60
- # Find next available plan number or create new one
61
- $existingPlans = Get-ChildItem -Path $PlanDir -Filter "plan-*.md" -ErrorAction SilentlyContinue
62
- $planNumber = if ($existingPlans) { $existingPlans.Count + 1 } else { 1 }
60
+ # Check if plan-001.md exists
61
+ $FirstPlan = Join-Path $PlanDir "plan-001.md"
62
+ if (Test-Path $FirstPlan) {
63
+ # Find next available plan number
64
+ $existingPlans = Get-ChildItem -Path $PlanDir -Filter "plan-*.md" -ErrorAction SilentlyContinue | Sort-Object Name
65
+ if ($existingPlans) {
66
+ $highestPlan = [int]($existingPlans[-1].BaseName -replace 'plan-', '')
67
+ $planNumber = $highestPlan + 1
68
+ } else {
69
+ $planNumber = 2
70
+ }
71
+ } else {
72
+ $planNumber = 1
73
+ }
63
74
  $PlanFile = Join-Path $PlanDir ("plan-{0:D3}.md" -f $planNumber)
64
75
 
65
76
  # Ensure plan template exists
@@ -67,36 +78,50 @@ if (-not (Test-Path $TemplateFile)) {
67
78
  Exit-WithError "Template not found: $TemplateFile"
68
79
  }
69
80
 
70
- # Create plan
71
- Log-Message "Creating implementation plan from template: $PlanFile"
81
+ # Create placeholder file for AI to generate plan
82
+ Log-Message "Creating implementation plan: $PlanFile"
72
83
  try {
73
- Copy-Item -Path $TemplateFile -Destination $PlanFile -Force
84
+ @"
85
+ # Implementation Plan - $FeatureDir
86
+
87
+ <!-- INSTRUCTION: Generate plan using template: $TemplateFile -->
88
+ <!-- SPEC_FILE: $SpecFile -->
89
+ <!-- FEATURE_DIR: $FeatureDir -->
90
+ <!-- FEATURE_ID: $FeatureId -->
91
+ "@ | Set-Content -Path $PlanFile
74
92
  } catch {
75
- Exit-WithError "Failed to copy plan template: $_"
93
+ Exit-WithError "Failed to create plan file: $_"
76
94
  }
77
95
 
78
96
  # Validate plan structure
79
97
  Log-Message "Validating implementation plan..."
80
98
 
81
- # Check for required sections
82
- $RequiredSections = @(
83
- "## Implementation Plan:",
84
- "## Specification Reference",
85
- "## Phase -1: Pre-Implementation Gates",
86
- "## Implementation Phases"
87
- )
88
-
99
+ # Check if file needs AI generation
89
100
  $content = Get-Content -Path $PlanFile -Raw
90
- $MissingSections = @()
91
-
92
- foreach ($section in $RequiredSections) {
93
- if ($content -notmatch [regex]::Escape($section)) {
94
- $MissingSections += $section
101
+ if ($content -match "INSTRUCTION: Generate plan") {
102
+ Log-Message "WARNING: Plan needs to be generated by AI from template"
103
+ $MissingSections = @("ALL - Awaiting AI Generation")
104
+ $GateStatus = "PENDING"
105
+ } else {
106
+ # Check for required sections only if file has been generated
107
+ $RequiredSections = @(
108
+ "## Implementation Plan:",
109
+ "## Specification Reference",
110
+ "## Phase -1: Pre-Implementation Gates",
111
+ "## Implementation Phases"
112
+ )
113
+
114
+ $MissingSections = @()
115
+
116
+ foreach ($section in $RequiredSections) {
117
+ if ($content -notmatch [regex]::Escape($section)) {
118
+ $MissingSections += $section
119
+ }
95
120
  }
96
- }
97
121
 
98
- if ($MissingSections.Count -gt 0) {
99
- Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
122
+ if ($MissingSections.Count -gt 0) {
123
+ Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
124
+ }
100
125
  }
101
126
 
102
127
  # Check SDD Gates
@@ -91,7 +91,7 @@ echo "<!-- FEATURE_ID: $FEATURE_ID -->" >> "$PLAN_FILE"
91
91
  log "Validating implementation plan..."
92
92
 
93
93
  # Check if file needs AI generation
94
- if grep -q "Awaiting AI Generation" "$PLAN_FILE"; then
94
+ if grep -q "INSTRUCTION: Generate plan" "$PLAN_FILE"; then
95
95
  log "WARNING: Plan needs to be generated by AI from template"
96
96
  MISSING_SECTIONS=("ALL - Awaiting AI Generation")
97
97
  GATE_STATUS="PENDING"
@@ -77,12 +77,31 @@ if ($SpecContent) {
77
77
  } else {
78
78
  $specNumber = 2
79
79
  }
80
+ $SpecFile = Join-Path $SpecDir ("spec-{0:D3}.md" -f $specNumber)
81
+ Log-Message "Creating specification file for AI generation: $SpecFile"
82
+ # Create placeholder file for AI to fill
83
+ $placeholderContent = @"
84
+ # Specification - $FeatureDir
85
+
86
+ <!-- INSTRUCTION: Generate specification content using template: $TemplateFile -->
87
+ <!-- FEATURE_DIR: $FeatureDir -->
88
+ <!-- FEATURE_ID: $FeatureId -->
89
+ "@
90
+ Set-Content -Path $SpecFile -Value $placeholderContent
80
91
  } else {
81
- $specNumber = 1
92
+ # Create first spec
93
+ $SpecFile = Join-Path $SpecDir "spec-001.md"
94
+ Log-Message "Creating first specification file for AI generation: $SpecFile"
95
+ # Create placeholder file for AI to fill
96
+ $placeholderContent = @"
97
+ # Specification - $FeatureDir
98
+
99
+ <!-- INSTRUCTION: Generate specification content using template: $TemplateFile -->
100
+ <!-- FEATURE_DIR: $FeatureDir -->
101
+ <!-- FEATURE_ID: $FeatureId -->
102
+ "@
103
+ Set-Content -Path $SpecFile -Value $placeholderContent
82
104
  }
83
- $SpecFile = Join-Path $SpecDir ("spec-{0:D3}.md" -f $specNumber)
84
- Log-Message "Creating specification file for AI generation: $SpecFile"
85
- "INSTRUCTION: Generate specification content using template at $TemplateFile" | Set-Content -Path "$SpecFile.instruction"
86
105
  }
87
106
 
88
107
  # Validate specification
@@ -91,25 +110,31 @@ if (-not (Test-Path $SpecFile)) {
91
110
  Exit-WithError "Specification file does not exist: $SpecFile"
92
111
  }
93
112
 
94
- # Check for required sections
95
- $RequiredSections = @(
96
- "## Specification:",
97
- "## Metadata",
98
- "## Functional Requirements",
99
- "## Acceptance Scenarios"
100
- )
101
-
113
+ # Check if file needs AI generation
102
114
  $content = Get-Content -Path $SpecFile -Raw
103
- $MissingSections = @()
104
-
105
- foreach ($section in $RequiredSections) {
106
- if ($content -notmatch [regex]::Escape($section)) {
107
- $MissingSections += $section
115
+ if ($content -match "INSTRUCTION: Generate specification") {
116
+ Log-Message "WARNING: Specification needs to be generated by AI from template"
117
+ $MissingSections = @("ALL - Awaiting AI Generation")
118
+ } else {
119
+ # Check for required sections only if file has been generated
120
+ $RequiredSections = @(
121
+ "## Specification:",
122
+ "## Metadata",
123
+ "## Functional Requirements",
124
+ "## Acceptance Scenarios"
125
+ )
126
+
127
+ $MissingSections = @()
128
+
129
+ foreach ($section in $RequiredSections) {
130
+ if ($content -notmatch [regex]::Escape($section)) {
131
+ $MissingSections += $section
132
+ }
108
133
  }
109
- }
110
134
 
111
- if ($MissingSections.Count -gt 0) {
112
- Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
135
+ if ($MissingSections.Count -gt 0) {
136
+ Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
137
+ }
113
138
  }
114
139
 
115
140
  # Check for clarifications needed
@@ -107,7 +107,7 @@ if [ ! -f "$SPEC_FILE" ]; then
107
107
  fi
108
108
 
109
109
  # Check if file needs AI generation
110
- if grep -q "Awaiting AI Generation" "$SPEC_FILE"; then
110
+ if grep -q "INSTRUCTION: Generate specification" "$SPEC_FILE"; then
111
111
  log "WARNING: Specification needs to be generated by AI from template"
112
112
  MISSING_SECTIONS=("ALL - Awaiting AI Generation")
113
113
  else
@@ -72,9 +72,20 @@ if (Test-Path $PlanDir) {
72
72
  Exit-WithError "Plans directory not found: $PlanDir. Please create plan first."
73
73
  }
74
74
 
75
- # Find next available task number or create new one
76
- $existingTasks = Get-ChildItem -Path $TaskDir -Filter "task-*.md" -ErrorAction SilentlyContinue
77
- $taskNumber = if ($existingTasks) { $existingTasks.Count + 1 } else { 1 }
75
+ # Check if task-001.md exists
76
+ $FirstTask = Join-Path $TaskDir "task-001.md"
77
+ if (Test-Path $FirstTask) {
78
+ # Find next available task number
79
+ $existingTasks = Get-ChildItem -Path $TaskDir -Filter "task-*.md" -ErrorAction SilentlyContinue | Sort-Object Name
80
+ if ($existingTasks) {
81
+ $highestTask = [int]($existingTasks[-1].BaseName -replace 'task-', '')
82
+ $taskNumber = $highestTask + 1
83
+ } else {
84
+ $taskNumber = 2
85
+ }
86
+ } else {
87
+ $taskNumber = 1
88
+ }
78
89
  $TaskFile = Join-Path $TaskDir ("task-{0:D3}.md" -f $taskNumber)
79
90
 
80
91
  # Ensure task template exists
@@ -82,46 +93,65 @@ if (-not (Test-Path $TemplateFile)) {
82
93
  Exit-WithError "Template not found: $TemplateFile"
83
94
  }
84
95
 
85
- # Create task file
86
- Log-Message "Creating task breakdown from template: $TaskFile"
96
+ # Create placeholder file for AI to generate tasks
97
+ Log-Message "Creating task breakdown: $TaskFile"
87
98
  try {
88
- Copy-Item -Path $TemplateFile -Destination $TaskFile -Force
99
+ @"
100
+ # Task Breakdown - $FeatureDir
101
+
102
+ <!-- INSTRUCTION: Generate tasks using template: $TemplateFile -->
103
+ <!-- SPEC_FILE: $SpecFile -->
104
+ <!-- PLAN_FILE: $PlanFile -->
105
+ <!-- FEATURE_DIR: $FeatureDir -->
106
+ <!-- FEATURE_ID: $FeatureId -->
107
+ "@ | Set-Content -Path $TaskFile
89
108
  } catch {
90
- Exit-WithError "Failed to copy task template: $_"
109
+ Exit-WithError "Failed to create task file: $_"
91
110
  }
92
111
 
93
112
  # Validate task structure
94
113
  Log-Message "Validating task breakdown..."
95
114
 
96
- # Check for required sections
97
- $RequiredSections = @(
98
- "## Task List:",
99
- "## Task Organization",
100
- "## Critical Path",
101
- "## Execution Schedule"
102
- )
103
-
115
+ # Check if file needs AI generation
104
116
  $content = Get-Content -Path $TaskFile -Raw
105
- $MissingSections = @()
106
-
107
- foreach ($section in $RequiredSections) {
108
- if ($content -notmatch [regex]::Escape($section)) {
109
- $MissingSections += $section
117
+ if ($content -match "INSTRUCTION: Generate tasks") {
118
+ Log-Message "WARNING: Tasks need to be generated by AI from template"
119
+ $MissingSections = @("ALL - Awaiting AI Generation")
120
+ $TotalTasks = 0
121
+ $CompletedTasks = 0
122
+ $PendingTasks = 0
123
+ $BlockedTasks = 0
124
+ $ParallelTasks = 0
125
+ } else {
126
+ # Check for required sections only if file has been generated
127
+ $RequiredSections = @(
128
+ "## Task List:",
129
+ "## Task Organization",
130
+ "## Critical Path",
131
+ "## Execution Schedule"
132
+ )
133
+
134
+ $MissingSections = @()
135
+
136
+ foreach ($section in $RequiredSections) {
137
+ if ($content -notmatch [regex]::Escape($section)) {
138
+ $MissingSections += $section
139
+ }
110
140
  }
111
- }
112
141
 
113
- if ($MissingSections.Count -gt 0) {
114
- Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
115
- }
142
+ if ($MissingSections.Count -gt 0) {
143
+ Log-Message "WARNING: Missing required sections: $($MissingSections -join ', ')"
144
+ }
116
145
 
117
- # Count tasks and analyze structure
118
- $TotalTasks = ([regex]::Matches($content, "^- \[.\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
119
- $CompletedTasks = ([regex]::Matches($content, "^- \[x\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
120
- $PendingTasks = ([regex]::Matches($content, "^- \[ \]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
121
- $BlockedTasks = ([regex]::Matches($content, "^- \[!\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
146
+ # Count tasks and analyze structure
147
+ $TotalTasks = ([regex]::Matches($content, "^- \[.\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
148
+ $CompletedTasks = ([regex]::Matches($content, "^- \[x\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
149
+ $PendingTasks = ([regex]::Matches($content, "^- \[ \]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
150
+ $BlockedTasks = ([regex]::Matches($content, "^- \[!\]", [System.Text.RegularExpressions.RegexOptions]::Multiline)).Count
122
151
 
123
- # Check for parallel tasks
124
- $ParallelTasks = ([regex]::Matches($content, "\[P\]")).Count
152
+ # Check for parallel tasks
153
+ $ParallelTasks = ([regex]::Matches($content, "\[P\]")).Count
154
+ }
125
155
 
126
156
  # Check SDD gates compliance
127
157
  $GatesCount = 0
@@ -103,7 +103,7 @@ echo "<!-- FEATURE_ID: $FEATURE_ID -->" >> "$TASK_FILE"
103
103
  log "Validating task breakdown..."
104
104
 
105
105
  # Check if file needs AI generation
106
- if grep -q "Awaiting AI Generation" "$TASK_FILE"; then
106
+ if grep -q "INSTRUCTION: Generate tasks" "$TASK_FILE"; then
107
107
  log "WARNING: Tasks need to be generated by AI from template"
108
108
  MISSING_SECTIONS=("ALL - Awaiting AI Generation")
109
109
  TOTAL_TASKS=0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specpulse
3
- Version: 1.4.3
3
+ Version: 1.4.4
4
4
  Summary: Specification-Driven Development Framework
5
5
  Home-page: https://github.com/specpulse
6
6
  Author: SpecPulse
@@ -67,7 +67,13 @@ Dynamic: requires-python
67
67
 
68
68
  SpecPulse is a universal **Specification-Driven Development (SDD)** framework that works with ANY software project - web apps, mobile apps, desktop software, games, APIs, ML projects, and more. It ensures every feature starts with clear specifications, validated plans, and tracked tasks.
69
69
 
70
- > **Latest Update (v1.4.3)** - Script Numbering Fix:
70
+ > **Latest Update (v1.4.4)** - Critical Workflow Fixes:
71
+ > - 🐛 **Fixed Script Numbering**: Resolved `/sp-pulse` creating empty placeholders while subsequent commands created new files
72
+ > - 🎯 **Fixed Task Detection**: Execute scripts now properly detect task format (`### T001:` with `**Status**:`)
73
+ > - 📝 **Unified Placeholders**: All scripts use consistent `<!-- INSTRUCTION: Generate -->` markers
74
+ > - 🔧 **PowerShell Parity**: PowerShell scripts now match Bash behavior exactly
75
+ >
76
+ > **v1.4.3** - Script Numbering Fix:
71
77
  > - 🔢 **Fixed Numbering Logic**: Spec, plan, and task files now number correctly (001, 002, 003...)
72
78
  > - 📝 **No Empty First Files**: spec-001.md, plan-001.md, task-001.md always contain content
73
79
  > - 🎯 **Proper Interactive Mode**: Scripts create placeholder files for AI to fill
@@ -25,16 +25,16 @@ specpulse/resources/memory/context.md,sha256=B-6m5f4WP8x_VXp0S9fbqm8tHH-2PZ7d9VW
25
25
  specpulse/resources/memory/decisions.md,sha256=ZwzVyOPB2mIzwveWpGmedej7ncI81GALg8WVy6AeZA4,686
26
26
  specpulse/resources/scripts/sp-pulse-decompose.ps1,sha256=KVrcDHYxibCyzY_Z9SKo7gMdM8mfKY7RukUPKVCaJ_A,2376
27
27
  specpulse/resources/scripts/sp-pulse-decompose.sh,sha256=EN8iF02pij4yse3of3fgO8ZI6YKFUV7Z7f4epEmaKXI,1431
28
- specpulse/resources/scripts/sp-pulse-execute.ps1,sha256=k4U5qoVjtEg0S3HD5g1bViZcMrG_1Zj9hNT269Oj_hU,6376
29
- specpulse/resources/scripts/sp-pulse-execute.sh,sha256=696vgsj0NpV-Mr0KMyoJ63NkTqmS1tmQ1X4BzK0kQGA,5493
30
- specpulse/resources/scripts/sp-pulse-init.ps1,sha256=NaQvpjEEfegvr2QQtYw6K_MYzh4EkfUPF7zjf_ffHUg,4799
31
- specpulse/resources/scripts/sp-pulse-init.sh,sha256=WDSRmf-qgcSs2sGpBLe44ObL3dAvJOdnbxsmpspcglI,4368
32
- specpulse/resources/scripts/sp-pulse-plan.ps1,sha256=Aw-XKJfLTkavYSqVD3lVs5JQ9h3K4ZcHzprqDYS8MWo,4369
33
- specpulse/resources/scripts/sp-pulse-plan.sh,sha256=bsrnLNNGnWVRCwhqdnjCaa14VX_owJriCvnGBA6M1L8,4850
34
- specpulse/resources/scripts/sp-pulse-spec.ps1,sha256=uCuSSJ360UW70BxyLgvcaMdNsbyJFsEWkIviTwojRKc,4222
35
- specpulse/resources/scripts/sp-pulse-spec.sh,sha256=g7EAmbg7WaRUiT6O1Qus-2XlveuSnZWV14NFtL1YYs8,5141
36
- specpulse/resources/scripts/sp-pulse-task.ps1,sha256=Uqp6lobaQb4mW5OiQ9LjEtyuYSewcRMjUj1GqHVoh6g,5664
37
- specpulse/resources/scripts/sp-pulse-task.sh,sha256=38KxXIwNpBEokyFwcCbjtZ2cDVOrYPe1SNxYPx45GuQ,5860
28
+ specpulse/resources/scripts/sp-pulse-execute.ps1,sha256=EBhAC91_z_0gu8YdHR24w6pv33DmCPXVeqkwbgVmRVw,7182
29
+ specpulse/resources/scripts/sp-pulse-execute.sh,sha256=M5XE1k4fUd5yhM1h6NdWHUcG9pA319VRovKkmQJMgws,6136
30
+ specpulse/resources/scripts/sp-pulse-init.ps1,sha256=6A0foYeBC-CBQaFb0qXxOx6T-QAzgzFTQbrq5EUiBs4,5015
31
+ specpulse/resources/scripts/sp-pulse-init.sh,sha256=-iGJPQJpJVclEetrpUNxkSDs6pwGmi7bQ7zBswEhlUQ,4692
32
+ specpulse/resources/scripts/sp-pulse-plan.ps1,sha256=a9o167yy0wYZSr4Fg3wCP0p3daZMoDsgpZrwo0wKGM0,5175
33
+ specpulse/resources/scripts/sp-pulse-plan.sh,sha256=hjy37mOC1hF2I__YwNA7bXJ9qV90kiuAPHnVBVvb-yA,4854
34
+ specpulse/resources/scripts/sp-pulse-spec.ps1,sha256=V4pFC9d7OX-x3aPjXrrCW7GTn1eEE5-3wZK1z_xBf0U,5271
35
+ specpulse/resources/scripts/sp-pulse-spec.sh,sha256=WJeAeQdc70ynK8bZNkHuul_d_splurqS5_Oi_2Dw2l8,5154
36
+ specpulse/resources/scripts/sp-pulse-task.ps1,sha256=Q9YQYINkCX9tCXvGlvuA974PRdNPqRaaaH7KzaQvRps,6604
37
+ specpulse/resources/scripts/sp-pulse-task.sh,sha256=LxdiObEakOi01IZq1kVeikDXuhRjYplFvgn4gv97Uts,5865
38
38
  specpulse/resources/templates/plan.md,sha256=ieouqeIhLEfzP-_vytCmKHqxNGh8ITNZ5sub3nufvZ0,3349
39
39
  specpulse/resources/templates/spec.md,sha256=wGXSyD7AWRofeeW5a2rVrSIxeYK5zolQulN1xJRni44,2234
40
40
  specpulse/resources/templates/task.md,sha256=X3_BOYIZ40qMGRxDs-stGh0pAVyZHYkvSNuvXJO981o,4658
@@ -47,9 +47,9 @@ specpulse/utils/__init__.py,sha256=VTGRDsVLl2JIXYyHB9Sidxj5acY_W-LJI2MMtY1pwb0,1
47
47
  specpulse/utils/console.py,sha256=1Dn6m81dZa3XZkeKvGFgQywE9FyQnhlOorNtE0f86VM,14793
48
48
  specpulse/utils/git_utils.py,sha256=jH5RWbC-lx2iPKVm2dWP7Iqqh1_CdmbNi7q4S_c4W8s,7393
49
49
  specpulse/utils/version_check.py,sha256=9Ug0Td1SesRskx2JFy7QS59ikomKRxuSM9OUHrZtEO4,3877
50
- specpulse-1.4.3.dist-info/licenses/LICENSE,sha256=ImSFezK-Phy0oTBqZipcajsJfPZT8mmg8m3jkgNdNhA,1066
51
- specpulse-1.4.3.dist-info/METADATA,sha256=0sxARDERGUL3YHBXjCIdxJbZs-_fux70IWx77SUMuX4,24654
52
- specpulse-1.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
- specpulse-1.4.3.dist-info/entry_points.txt,sha256=GwMaCKWSCFZlJMrTNavEYrnREynIS6dM3B0ILxnaouA,83
54
- specpulse-1.4.3.dist-info/top_level.txt,sha256=pEfkFil5xe38J00OHrBrJ07xpbm6bRnGhI8B07O9KeI,10
55
- specpulse-1.4.3.dist-info/RECORD,,
50
+ specpulse-1.4.4.dist-info/licenses/LICENSE,sha256=ImSFezK-Phy0oTBqZipcajsJfPZT8mmg8m3jkgNdNhA,1066
51
+ specpulse-1.4.4.dist-info/METADATA,sha256=EP9APXO6hQn84PeIuh-8bbBA7n9RwKRfpr6-0jqrJIY,25134
52
+ specpulse-1.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
+ specpulse-1.4.4.dist-info/entry_points.txt,sha256=GwMaCKWSCFZlJMrTNavEYrnREynIS6dM3B0ILxnaouA,83
54
+ specpulse-1.4.4.dist-info/top_level.txt,sha256=pEfkFil5xe38J00OHrBrJ07xpbm6bRnGhI8B07O9KeI,10
55
+ specpulse-1.4.4.dist-info/RECORD,,