Skip to content

Commit 05b1ea8

Browse files
committed
fix: honor template overrides for tasks-template (#2278)
- Add scripts/bash/setup-tasks.sh mirroring setup-plan.sh pattern - Add scripts/powershell/setup-tasks.ps1 mirroring setup-plan.ps1 pattern - Update tasks.md frontmatter to use dedicated setup-tasks scripts - Resolve tasks template via override stack and emit path as TASKS_TEMPLATE in JSON output - Reference resolved TASKS_TEMPLATE path in generate step instead of hardcoded path
1 parent c118c1c commit 05b1ea8

3 files changed

Lines changed: 169 additions & 4 deletions

File tree

scripts/bash/setup-tasks.sh

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Parse command line arguments
6+
JSON_MODE=false
7+
8+
for arg in "$@"; do
9+
case "$arg" in
10+
--json) JSON_MODE=true ;;
11+
--help|-h)
12+
echo "Usage: $0 [--json]"
13+
echo " --json Output results in JSON format"
14+
echo " --help Show this help message"
15+
exit 0
16+
;;
17+
*) echo "ERROR: Unknown option '$arg'" >&2; exit 1 ;;
18+
esac
19+
done
20+
21+
# Source common functions
22+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23+
source "$SCRIPT_DIR/common.sh"
24+
25+
# Get feature paths
26+
_paths_output=$(get_feature_paths) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; }
27+
eval "$_paths_output"
28+
unset _paths_output
29+
30+
# Validate branch
31+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
32+
33+
# Validate prerequisites
34+
if [[ ! -d "$FEATURE_DIR" ]]; then
35+
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
36+
echo "Run /speckit.specify first to create the feature structure." >&2
37+
exit 1
38+
fi
39+
40+
if [[ ! -f "$IMPL_PLAN" ]]; then
41+
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
42+
echo "Run /speckit.plan first to create the implementation plan." >&2
43+
exit 1
44+
fi
45+
46+
# Build available docs list
47+
docs=()
48+
[[ -f "$RESEARCH" ]] && docs+=("research.md")
49+
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
50+
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
51+
docs+=("contracts/")
52+
fi
53+
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
54+
55+
# Resolve tasks template through override stack
56+
TASKS_TEMPLATE=$(resolve_template "tasks-template" "$REPO_ROOT") || true
57+
if [[ -z "$TASKS_TEMPLATE" ]] || [[ ! -f "$TASKS_TEMPLATE" ]]; then
58+
echo "Error: could not resolve required tasks-template in $REPO_ROOT" >&2
59+
exit 1
60+
fi
61+
62+
# Output results
63+
if $JSON_MODE; then
64+
if has_jq; then
65+
if [[ ${#docs[@]} -eq 0 ]]; then
66+
json_docs="[]"
67+
else
68+
json_docs=$(printf '%s\n' "${docs[@]}" | jq -R . | jq -s .)
69+
fi
70+
jq -cn \
71+
--arg feature_dir "$FEATURE_DIR" \
72+
--argjson docs "$json_docs" \
73+
--arg tasks_template "${TASKS_TEMPLATE:-}" \
74+
'{FEATURE_DIR:$feature_dir,AVAILABLE_DOCS:$docs,TASKS_TEMPLATE:$tasks_template}'
75+
else
76+
if [[ ${#docs[@]} -eq 0 ]]; then
77+
json_docs="[]"
78+
else
79+
json_docs=$(for d in "${docs[@]}"; do printf '"%s",' "$(json_escape "$d")"; done)
80+
json_docs="[${json_docs%,}]"
81+
fi
82+
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s,"TASKS_TEMPLATE":"%s"}\n' \
83+
"$(json_escape "$FEATURE_DIR")" "$json_docs" "$(json_escape "${TASKS_TEMPLATE:-}")"
84+
fi
85+
else
86+
echo "FEATURE_DIR: $FEATURE_DIR"
87+
echo "TASKS_TEMPLATE: ${TASKS_TEMPLATE:-not found}"
88+
echo "AVAILABLE_DOCS:"
89+
check_file "$RESEARCH" "research.md"
90+
check_file "$DATA_MODEL" "data-model.md"
91+
check_dir "$CONTRACTS_DIR" "contracts/"
92+
check_file "$QUICKSTART" "quickstart.md"
93+
fi
94+
EOF

scripts/powershell/setup-tasks.ps1

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env pwsh
2+
3+
[CmdletBinding()]
4+
param(
5+
[switch]$Json,
6+
[switch]$Help
7+
)
8+
9+
$ErrorActionPreference = 'Stop'
10+
11+
if ($Help) {
12+
Write-Output "Usage: setup-tasks.ps1 [-Json] [-Help]"
13+
exit 0
14+
}
15+
16+
# Source common functions
17+
. "$PSScriptRoot/common.ps1"
18+
19+
# Get feature paths and validate branch
20+
$paths = Get-FeaturePathsEnv
21+
22+
if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GIT)) {
23+
exit 1
24+
}
25+
26+
# Validate prerequisites
27+
if (-not (Test-Path $paths.FEATURE_DIR -PathType Container)) {
28+
Write-Output "ERROR: Feature directory not found: $($paths.FEATURE_DIR)"
29+
Write-Output "Run /speckit.specify first to create the feature structure."
30+
exit 1
31+
}
32+
33+
if (-not (Test-Path $paths.IMPL_PLAN -PathType Leaf)) {
34+
Write-Output "ERROR: plan.md not found in $($paths.FEATURE_DIR)"
35+
Write-Output "Run /speckit.plan first to create the implementation plan."
36+
exit 1
37+
}
38+
39+
# Build available docs list
40+
$docs = @()
41+
if (Test-Path $paths.RESEARCH) { $docs += 'research.md' }
42+
if (Test-Path $paths.DATA_MODEL) { $docs += 'data-model.md' }
43+
if ((Test-Path $paths.CONTRACTS_DIR) -and (Get-ChildItem -Path $paths.CONTRACTS_DIR -ErrorAction SilentlyContinue | Select-Object -First 1)) {
44+
$docs += 'contracts/'
45+
}
46+
if (Test-Path $paths.QUICKSTART) { $docs += 'quickstart.md' }
47+
48+
# Resolve tasks template through override stack
49+
$tasksTemplate = Resolve-Template -TemplateName 'tasks-template' -RepoRoot $paths.REPO_ROOT
50+
if (-not $tasksTemplate) {
51+
Write-Error "Tasks template not found in $($paths.REPO_ROOT)"
52+
exit 1
53+
}
54+
55+
# Output results
56+
if ($Json) {
57+
[PSCustomObject]@{
58+
FEATURE_DIR = $paths.FEATURE_DIR
59+
AVAILABLE_DOCS = $docs
60+
TASKS_TEMPLATE = $tasksTemplate
61+
} | ConvertTo-Json -Compress
62+
} else {
63+
Write-Output "FEATURE_DIR: $($paths.FEATURE_DIR)"
64+
Write-Output "TASKS_TEMPLATE: $(if ($tasksTemplate) { $tasksTemplate } else { 'not found' })"
65+
Write-Output "AVAILABLE_DOCS:"
66+
Test-FileExists -Path $paths.RESEARCH -Description 'research.md' | Out-Null
67+
Test-FileExists -Path $paths.DATA_MODEL -Description 'data-model.md' | Out-Null
68+
Test-DirHasFiles -Path $paths.CONTRACTS_DIR -Description 'contracts/' | Out-Null
69+
Test-FileExists -Path $paths.QUICKSTART -Description 'quickstart.md' | Out-Null
70+
}
71+
EOF

templates/commands/tasks.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ handoffs:
1010
prompt: Start the implementation in phases
1111
send: true
1212
scripts:
13-
sh: scripts/bash/check-prerequisites.sh --json
14-
ps: scripts/powershell/check-prerequisites.ps1 -Json
13+
sh: scripts/bash/setup-tasks.sh --json
14+
ps: scripts/powershell/setup-tasks.ps1 -Json
1515
---
1616

1717
## User Input
@@ -58,7 +58,7 @@ You **MUST** consider the user input before proceeding (if not empty).
5858
5959
## Outline
6060
61-
1. **Setup**: Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
61+
1. **Setup**: Run `{SCRIPT}` from repo root and parse FEATURE_DIR, TASKS_TEMPLATE, and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
6262
6363
2. **Load design documents**: Read from FEATURE_DIR:
6464
- **Required**: plan.md (tech stack, libraries, structure), spec.md (user stories with priorities)
@@ -76,7 +76,7 @@ You **MUST** consider the user input before proceeding (if not empty).
7676
- Create parallel execution examples per user story
7777
- Validate task completeness (each user story has all needed tasks, independently testable)
7878
79-
4. **Generate tasks.md**: Use `templates/tasks-template.md` as structure, fill with:
79+
4. **Generate tasks.md**: Read the tasks template from TASKS_TEMPLATE (from the JSON output above) and use it as structure. If TASKS_TEMPLATE is empty, fall back to `.specify/templates/tasks-template.md`. Fill with:
8080
- Correct feature name from plan.md
8181
- Phase 1: Setup tasks (project initialization)
8282
- Phase 2: Foundational tasks (blocking prerequisites for all user stories)

0 commit comments

Comments
 (0)