Skip to content

fix: honor template overrides for tasks-template (#2278)#2292

Open
Nimraakram22 wants to merge 3 commits intogithub:mainfrom
Nimraakram22:fix/honor-tasks-template-overrides-2278
Open

fix: honor template overrides for tasks-template (#2278)#2292
Nimraakram22 wants to merge 3 commits intogithub:mainfrom
Nimraakram22:fix/honor-tasks-template-overrides-2278

Conversation

@Nimraakram22
Copy link
Copy Markdown

This PR resolves #2278 by implementing a unified template resolution flow for the tasks command, bringing it into parity with the plan command.

Key Changes:

Removed hardcoded path in templates/commands/tasks.md in favor of {{TASKS_TEMPLATE}}.

Added setup-tasks.ps1 and setup-tasks.sh to handle the resolution priority stack (Overrides > Presets > Core).

Exported the resolved path via environment variables in the prerequisite check.

Updated docs/reference/presets.md to include tasks-template.md in the documented override stack.

Verification:
Confirmed on Windows 64-bit that local overrides in .specify/templates/overrides/tasks-template.md are correctly loaded and utilized by the AI agent.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to bring the /tasks command into parity with /plan by adding template override resolution for tasks-template.md (overrides → presets → extensions → core) and updating docs accordingly.

Changes:

  • Updated templates/commands/tasks.md to reference a TASKS_TEMPLATE placeholder instead of a hardcoded path.
  • Added new setup scripts for resolving tasks-template (bash + PowerShell) and wired PowerShell prerequisite checks to run them.
  • Updated preset documentation to state that the override stack applies to tasks-template.md as well.
Show a summary per file
File Description
templates/commands/tasks.md Replaces hardcoded tasks template path with a placeholder reference.
scripts/powershell/setup-tasks.ps1 Adds PowerShell template resolution and writes a resolved template file.
scripts/powershell/check-prerequisites.ps1 Attempts to run setup scripts as part of prerequisite checking.
scripts/bash/setup-tasks.sh Adds bash template resolution/export for tasks-template.
docs/reference/presets.md Documents tasks-template as participating in the same override stack as plan-template.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 5

Comment thread templates/commands/tasks.md Outdated
Comment thread scripts/powershell/check-prerequisites.ps1 Outdated
Comment thread scripts/powershell/setup-tasks.ps1 Outdated
Comment thread scripts/bash/setup-tasks.sh Outdated
Comment thread docs/reference/presets.md Outdated
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 22, 2026

Suggested fix for #2278 / PR #2292

The current PR introduces {{TASKS_TEMPLATE}} (not a recognized placeholder),
dot-sources setup scripts inside check-prerequisites.ps1, and has a broken
repo-root fallback. The fix needs a different approach.

Since check-prerequisites is shared by 6 commands, template resolution
should live in a dedicated setup-tasks script — the same pattern used by
setup-plan.sh / setup-plan.ps1 for the plan command.

Overview

  1. Create scripts/bash/setup-tasks.sh
  2. Create scripts/powershell/setup-tasks.ps1
  3. Update templates/commands/tasks.md frontmatter to use the new scripts
  4. Update templates/commands/tasks.md body to reference the resolved path

1. scripts/bash/setup-tasks.sh

Model this on scripts/bash/setup-plan.sh. It resolves feature paths,
validates the branch, ensures prerequisites (plan.md), resolves the tasks
template, copies it to the feature dir, and emits JSON.

#!/usr/bin/env bash

set -e

# Parse command line arguments
JSON_MODE=false

for arg in "$@"; do
    case "$arg" in
        --json) JSON_MODE=true ;;
        --help|-h)
            echo "Usage: $0 [--json]"
            echo "  --json    Output results in JSON format"
            echo "  --help    Show this help message"
            exit 0
            ;;
        *) echo "ERROR: Unknown option '$arg'" >&2; exit 1 ;;
    esac
done

# Source common functions
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get feature paths
_paths_output=$(get_feature_paths) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; }
eval "$_paths_output"
unset _paths_output

# Validate branch
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1

# Validate prerequisites
if [[ ! -d "$FEATURE_DIR" ]]; then
    echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
    echo "Run /speckit.specify first to create the feature structure." >&2
    exit 1
fi

if [[ ! -f "$IMPL_PLAN" ]]; then
    echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
    echo "Run /speckit.plan first to create the implementation plan." >&2
    exit 1
fi

# Build available docs list
docs=()
[[ -f "$RESEARCH" ]] && docs+=("research.md")
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
    docs+=("contracts/")
fi
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")

# Resolve tasks template through override stack
TASKS_TEMPLATE=$(resolve_template "tasks-template" "$REPO_ROOT") || true
if [[ -z "$TASKS_TEMPLATE" ]] || [[ ! -f "$TASKS_TEMPLATE" ]]; then
    echo "Warning: Tasks template not found" >&2
    TASKS_TEMPLATE=""
fi

# Output results
if $JSON_MODE; then
    if has_jq; then
        if [[ ${#docs[@]} -eq 0 ]]; then
            json_docs="[]"
        else
            json_docs=$(printf '%s\n' "${docs[@]}" | jq -R . | jq -s .)
        fi
        jq -cn \
            --arg feature_dir "$FEATURE_DIR" \
            --argjson docs "$json_docs" \
            --arg tasks_template "${TASKS_TEMPLATE:-}" \
            '{FEATURE_DIR:$feature_dir,AVAILABLE_DOCS:$docs,TASKS_TEMPLATE:$tasks_template}'
    else
        if [[ ${#docs[@]} -eq 0 ]]; then
            json_docs="[]"
        else
            json_docs=$(for d in "${docs[@]}"; do printf '"%s",' "$(json_escape "$d")"; done)
            json_docs="[${json_docs%,}]"
        fi
        printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s,"TASKS_TEMPLATE":"%s"}\n' \
            "$(json_escape "$FEATURE_DIR")" "$json_docs" "$(json_escape "${TASKS_TEMPLATE:-}")"
    fi
else
    echo "FEATURE_DIR: $FEATURE_DIR"
    echo "TASKS_TEMPLATE: ${TASKS_TEMPLATE:-not found}"
    echo "AVAILABLE_DOCS:"
    check_file "$RESEARCH" "research.md"
    check_file "$DATA_MODEL" "data-model.md"
    check_dir "$CONTRACTS_DIR" "contracts/"
    check_file "$QUICKSTART" "quickstart.md"
fi

2. scripts/powershell/setup-tasks.ps1

#!/usr/bin/env pwsh

[CmdletBinding()]
param(
    [switch]$Json,
    [switch]$Help
)

$ErrorActionPreference = 'Stop'

if ($Help) {
    Write-Output "Usage: setup-tasks.ps1 [-Json] [-Help]"
    exit 0
}

# Source common functions
. "$PSScriptRoot/common.ps1"

# Get feature paths and validate branch
$paths = Get-FeaturePathsEnv

if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GIT)) {
    exit 1
}

# Validate prerequisites
if (-not (Test-Path $paths.FEATURE_DIR -PathType Container)) {
    Write-Output "ERROR: Feature directory not found: $($paths.FEATURE_DIR)"
    Write-Output "Run /speckit.specify first to create the feature structure."
    exit 1
}

if (-not (Test-Path $paths.IMPL_PLAN -PathType Leaf)) {
    Write-Output "ERROR: plan.md not found in $($paths.FEATURE_DIR)"
    Write-Output "Run /speckit.plan first to create the implementation plan."
    exit 1
}

# Build available docs list
$docs = @()
if (Test-Path $paths.RESEARCH) { $docs += 'research.md' }
if (Test-Path $paths.DATA_MODEL) { $docs += 'data-model.md' }
if ((Test-Path $paths.CONTRACTS_DIR) -and (Get-ChildItem -Path $paths.CONTRACTS_DIR -ErrorAction SilentlyContinue | Select-Object -First 1)) {
    $docs += 'contracts/'
}
if (Test-Path $paths.QUICKSTART) { $docs += 'quickstart.md' }

# Resolve tasks template through override stack
$tasksTemplate = Resolve-Template -TemplateName 'tasks-template' -RepoRoot $paths.REPO_ROOT
if (-not $tasksTemplate) {
    Write-Warning "Tasks template not found"
    $tasksTemplate = ''
}

# Output results
if ($Json) {
    [PSCustomObject]@{
        FEATURE_DIR    = $paths.FEATURE_DIR
        AVAILABLE_DOCS = $docs
        TASKS_TEMPLATE = $tasksTemplate
    } | ConvertTo-Json -Compress
} else {
    Write-Output "FEATURE_DIR: $($paths.FEATURE_DIR)"
    Write-Output "TASKS_TEMPLATE: $(if ($tasksTemplate) { $tasksTemplate } else { 'not found' })"
    Write-Output "AVAILABLE_DOCS:"
    Test-FileExists -Path $paths.RESEARCH -Description 'research.md' | Out-Null
    Test-FileExists -Path $paths.DATA_MODEL -Description 'data-model.md' | Out-Null
    Test-DirHasFiles -Path $paths.CONTRACTS_DIR -Description 'contracts/' | Out-Null
    Test-FileExists -Path $paths.QUICKSTART -Description 'quickstart.md' | Out-Null
}

3. templates/commands/tasks.md — frontmatter change

 scripts:
-  sh: scripts/bash/check-prerequisites.sh --json
-  ps: scripts/powershell/check-prerequisites.ps1 -Json
+  sh: scripts/bash/setup-tasks.sh --json
+  ps: scripts/powershell/setup-tasks.ps1 -Json

4. templates/commands/tasks.md — body change (line 61 and line 79)

Update the setup step to mention the new output field:

-1. **Setup**: Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
+1. **Setup**: Run `{SCRIPT}` from repo root and parse FEATURE_DIR, TASKS_TEMPLATE, and AVAILABLE_DOCS list. All paths must be absolute.

Update the generate step to reference the resolved path:

-4. **Generate tasks.md**: Use `templates/tasks-template.md` as structure, fill with:
+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:

What NOT to do

  • Do NOT introduce {{TASKS_TEMPLATE}} — it's not a recognized placeholder
  • Do NOT dot-source setup scripts inside check-prerequisites.ps1
  • Do NOT modify check-prerequisites.sh — it's shared by 6 commands
  • Do NOT modify docs/reference/presets.md — the override stack already
    applies generically to any template name; no doc change needed

Why this works

  • Mirrors the setup-plan.sh pattern exactly

  • resolve_template / Resolve-Template already walk the full priority
    stack (overrides → presets → extensions → core) and already handle
    tasks-template — no one was calling them for it

  • check-prerequisites stays untouched and generic

  • The agent gets an absolute path to the resolved template via JSON, same
    as how plan gets IMPL_PLAN

    Written with the help of Copilot

Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments authored together with Copilot above

- 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
@Nimraakram22 Nimraakram22 force-pushed the fix/honor-tasks-template-overrides-2278 branch from ce75d8d to 05b1ea8 Compare April 22, 2026 13:34
@mnriem mnriem requested a review from Copilot April 22, 2026 13:37
@Nimraakram22
Copy link
Copy Markdown
Author

Hi @mnriem, thank you for the detailed feedback. I've rewritten the PR from scratch following your suggested approach:

What changed:

  • Removed {{TASKS_TEMPLATE}} — it was not a recognized placeholder. The agent now reads the resolved path from the JSON output instead.
  • Added scripts/bash/setup-tasks.sh mirroring the setup-plan.sh pattern exactly — resolves feature paths, validates prerequisites, walks the override stack, and emits TASKS_TEMPLATE in JSON.
  • Added scripts/powershell/setup-tasks.ps1 mirroring setup-plan.ps1 — uses Get-RepoRoot from common.ps1 instead of the broken $PSScriptRoot/../.. fallback.
  • Updated templates/commands/tasks.md frontmatter to point to the new dedicated setup scripts instead of check-prerequisites.
  • Updated Step 1 and Step 4 in the tasks command body to reference the resolved TASKS_TEMPLATE path from JSON output, with a fallback to .specify/templates/tasks-template.md.
  • check-prerequisites.ps1, check-prerequisites.sh, and docs/reference/presets.md are all left untouched.

The bash script also now fails fast with a non-zero exit and a clear error message if the template cannot be resolved, as suggested by Copilot.

Please let me know if anything needs further adjustment. Thank you!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Comment thread scripts/bash/setup-tasks.sh Outdated
Comment thread scripts/powershell/setup-tasks.ps1 Outdated
Comment thread templates/commands/tasks.md
@mnriem mnriem self-requested a review April 22, 2026 13:43
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback

@Nimraakram22
Copy link
Copy Markdown
Author

Thanks for the review @mnriem and Copilot.

Fixed:

  • Removed the stray EOF token from the end of scripts/bash/setup-tasks.sh
  • Removed the stray EOF token from the end of scripts/powershell/setup-tasks.ps1

These were leftover artifacts from the heredoc used to write the files and would have caused a EOF: command not found error at runtime.

Not changed:

  • docs/reference/presets.md — left untouched as directed in the original review. The override stack already applies generically to any template name, so no doc update is needed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 2

Comment thread scripts/bash/setup-tasks.sh Outdated
Comment thread scripts/powershell/setup-tasks.ps1 Outdated
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 22, 2026

Please address Copilot feedback

@Nimraakram22
Copy link
Copy Markdown
Author

Thanks again @mnriem and Copilot.

Fixed:

  • scripts/bash/setup-tasks.sh: Changed error prefix from Error: to ERROR: to match the rest of the script, and added a remediation hint pointing to .specify/templates/tasks-template.md and suggesting specify init to restore it.
  • scripts/powershell/setup-tasks.ps1: Expanded the error message to include the expected core template path ($expectedCoreTemplate) and a concrete next step for the user to self-remediate.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

@mnriem mnriem self-requested a review April 22, 2026 20:49
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 22, 2026

Please address Test & Lint errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Honor template overrides for tasks-template (parity with plan)

4 participants