Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions scripts/bash/check-prerequisites.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,20 @@ check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1

# If paths-only mode, output paths and exit (support JSON + paths-only combined)
if $PATHS_ONLY; then
SPECS_DIR="$(get_specs_dir "$REPO_ROOT")" || exit 1
if $JSON_MODE; then
# Minimal JSON paths payload (no validation performed)
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
"$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s","SPECS_DIR":"%s"}\n' \
"$(json_escape "$REPO_ROOT")" "$(json_escape "$CURRENT_BRANCH")" "$(json_escape "$FEATURE_DIR")" \
"$(json_escape "$FEATURE_SPEC")" "$(json_escape "$IMPL_PLAN")" "$(json_escape "$TASKS")" "$(json_escape "$SPECS_DIR")"
else
echo "REPO_ROOT: $REPO_ROOT"
echo "BRANCH: $CURRENT_BRANCH"
echo "FEATURE_DIR: $FEATURE_DIR"
echo "FEATURE_SPEC: $FEATURE_SPEC"
echo "IMPL_PLAN: $IMPL_PLAN"
echo "TASKS: $TASKS"
echo "SPECS_DIR: $SPECS_DIR"
fi
exit 0
fi
Expand Down Expand Up @@ -148,7 +151,9 @@ if $JSON_MODE; then
json_docs="[${json_docs%,}]"
fi

printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
SPECS_DIR="$(get_specs_dir "$REPO_ROOT")" || exit 1
# Note: $json_docs is not escaped because it is already a pre-formatted JSON array
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s,"SPECS_DIR":"%s"}\n' "$(json_escape "$FEATURE_DIR")" "$json_docs" "$(json_escape "$SPECS_DIR")"
else
# Text output
echo "FEATURE_DIR:$FEATURE_DIR"
Expand Down
41 changes: 38 additions & 3 deletions scripts/bash/common.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
#!/usr/bin/env bash
# Common functions and variables for all scripts

# Escape a string for safe inclusion in JSON (handles all JSON-required escapes)
json_escape() {
local str="$1"
# Escape backslashes first, then quotes, then control characters
str="${str//\\/\\\\}"
str="${str//\"/\\\"}"
str="${str//$'\n'/\\n}"
str="${str//$'\r'/\\r}"
str="${str//$'\t'/\\t}"
str="${str//$'\b'/\\b}"
str="${str//$'\f'/\\f}"
# Remove any remaining control characters (U+0000-U+001F) that are
# not covered above, since they are invalid unescaped in JSON strings.
str="$(printf '%s' "$str" | tr -d '\000-\006\016-\037')"
printf '%s' "$str"
}

# Get repository root, with fallback for non-git repositories
get_repo_root() {
if git rev-parse --show-toplevel >/dev/null 2>&1; then
Expand All @@ -12,6 +29,24 @@ get_repo_root() {
fi
}

# Get specs directory, with support for external location via SPECIFY_SPECS_DIR
get_specs_dir() {
local repo_root="${1:-$(get_repo_root)}"
local specs_dir

if [[ -n "${SPECIFY_SPECS_DIR:-}" ]]; then
specs_dir="$SPECIFY_SPECS_DIR"
# Resolve relative paths against repo root
if [[ "$specs_dir" != /* ]]; then
specs_dir="$repo_root/$specs_dir"
fi
Comment on lines +37 to +42
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

SPECIFY_SPECS_DIR is user-controlled and can now influence values emitted by get_feature_paths (which are later consumed via eval $(get_feature_paths) in multiple scripts). Because get_feature_paths wraps values in single quotes, a SPECIFY_SPECS_DIR containing a ' can break out of quoting and lead to command injection. Consider switching away from eval-based exports, or ensure values are safely shell-escaped (e.g., escape single quotes) before being embedded in the get_feature_paths output.

Copilot uses AI. Check for mistakes.
else
specs_dir="$repo_root/specs"
fi

echo "$specs_dir"
}
Comment on lines +33 to +48
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

get_specs_dir is used as though it can fail (SPECS_DIR="$(get_specs_dir ...)" || exit 1), but the function always exits 0 and just echoes a path. Either remove the || exit 1 patterns, or add validation so get_specs_dir returns non-zero for invalid configurations (e.g., empty repo_root, path exists but is not a directory, or directory cannot be created when required).

Copilot uses AI. Check for mistakes.

# Get current branch, with fallback for non-git repositories
get_current_branch() {
# First check if SPECIFY_FEATURE environment variable is set
Expand All @@ -28,7 +63,7 @@ get_current_branch() {

# For non-git repos, try to find the latest feature directory
local repo_root=$(get_repo_root)
local specs_dir="$repo_root/specs"
local specs_dir="$(get_specs_dir "$repo_root")"

if [[ -d "$specs_dir" ]]; then
local latest_feature=""
Expand Down Expand Up @@ -81,14 +116,14 @@ check_feature_branch() {
return 0
}

get_feature_dir() { echo "$1/specs/$2"; }
get_feature_dir() { echo "$(get_specs_dir "$1")/$2"; }

# Find feature directory by numeric prefix instead of exact branch match
# This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature)
find_feature_dir_by_prefix() {
local repo_root="$1"
local branch_name="$2"
local specs_dir="$repo_root/specs"
local specs_dir="$(get_specs_dir "$repo_root")"

# Extract numeric prefix from branch (e.g., "004" from "004-whatever")
if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then
Expand Down
5 changes: 3 additions & 2 deletions scripts/bash/create-new-feature.sh
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ fi

cd "$REPO_ROOT"

SPECS_DIR="$REPO_ROOT/specs"
SPECS_DIR="$(get_specs_dir "$REPO_ROOT")" || exit 1
mkdir -p "$SPECS_DIR"

# Function to generate branch name with stop word filtering and length filtering
Expand Down Expand Up @@ -288,7 +288,8 @@ if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"
export SPECIFY_FEATURE="$BRANCH_NAME"

if $JSON_MODE; then
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s","SPECS_DIR":"%s"}\n' \
"$(json_escape "$BRANCH_NAME")" "$(json_escape "$SPEC_FILE")" "$(json_escape "$FEATURE_NUM")" "$(json_escape "$SPECS_DIR")"
else
echo "BRANCH_NAME: $BRANCH_NAME"
echo "SPEC_FILE: $SPEC_FILE"
Expand Down
9 changes: 8 additions & 1 deletion scripts/powershell/check-prerequisites.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GI

# If paths-only mode, output paths and exit (support combined -Json -PathsOnly)
if ($PathsOnly) {
$specsDir = Get-SpecsDir -RepoRoot $paths.REPO_ROOT
if (-not $specsDir) { exit 1 }
Comment thread
alanmeadows marked this conversation as resolved.
if ($Json) {
[PSCustomObject]@{
REPO_ROOT = $paths.REPO_ROOT
Expand All @@ -73,6 +75,7 @@ if ($PathsOnly) {
FEATURE_SPEC = $paths.FEATURE_SPEC
IMPL_PLAN = $paths.IMPL_PLAN
TASKS = $paths.TASKS
SPECS_DIR = $specsDir
} | ConvertTo-Json -Compress
} else {
Write-Output "REPO_ROOT: $($paths.REPO_ROOT)"
Expand All @@ -81,6 +84,7 @@ if ($PathsOnly) {
Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
Write-Output "TASKS: $($paths.TASKS)"
Write-Output "SPECS_DIR: $specsDir"
}
exit 0
}
Expand Down Expand Up @@ -127,9 +131,12 @@ if ($IncludeTasks -and (Test-Path $paths.TASKS)) {
# Output results
if ($Json) {
# JSON output
$specsDir = Get-SpecsDir -RepoRoot $paths.REPO_ROOT
if (-not $specsDir) { exit 1 }
Comment thread
alanmeadows marked this conversation as resolved.
[PSCustomObject]@{
FEATURE_DIR = $paths.FEATURE_DIR
AVAILABLE_DOCS = $docs
AVAILABLE_DOCS = $docs
SPECS_DIR = $specsDir
} | ConvertTo-Json -Compress
} else {
# Text output
Expand Down
19 changes: 17 additions & 2 deletions scripts/powershell/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ function Get-RepoRoot {
return (Resolve-Path (Join-Path $PSScriptRoot "../../..")).Path
}

# Get specs directory, with support for external location via SPECIFY_SPECS_DIR
function Get-SpecsDir {
param([string]$RepoRoot = (Get-RepoRoot))

if ($env:SPECIFY_SPECS_DIR) {
$specsDir = $env:SPECIFY_SPECS_DIR
# Resolve relative paths against repo root
if (-not [System.IO.Path]::IsPathRooted($specsDir)) {
$specsDir = Join-Path $RepoRoot $specsDir
}
return $specsDir
}
return Join-Path $RepoRoot "specs"
Comment thread
alanmeadows marked this conversation as resolved.
Comment on lines +22 to +30
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Get-SpecsDir always returns a (possibly relative-resolved) string, so callers' if (-not $specsDir) { exit 1 } checks can never trigger. Either implement real validation here (and return $null for invalid values like an existing non-directory path), or remove the dead checks and adjust the error messaging accordingly.

Suggested change
if ($env:SPECIFY_SPECS_DIR) {
$specsDir = $env:SPECIFY_SPECS_DIR
# Resolve relative paths against repo root
if (-not [System.IO.Path]::IsPathRooted($specsDir)) {
$specsDir = Join-Path $RepoRoot $specsDir
}
return $specsDir
}
return Join-Path $RepoRoot "specs"
$specsDir = $null
if ($env:SPECIFY_SPECS_DIR) {
$specsDir = $env:SPECIFY_SPECS_DIR
# Resolve relative paths against repo root
if (-not [System.IO.Path]::IsPathRooted($specsDir)) {
$specsDir = Join-Path $RepoRoot $specsDir
}
} else {
$specsDir = Join-Path $RepoRoot "specs"
}
# Validate that, if the path exists, it is a directory
if (Test-Path $specsDir) {
if (-not (Test-Path $specsDir -PathType Container)) {
Write-Error "Invalid specs directory path '$specsDir': path exists but is not a directory."
return $null
}
}
return $specsDir

Copilot uses AI. Check for mistakes.
}

function Get-CurrentBranch {
# First check if SPECIFY_FEATURE environment variable is set
if ($env:SPECIFY_FEATURE) {
Expand All @@ -33,7 +48,7 @@ function Get-CurrentBranch {

# For non-git repos, try to find the latest feature directory
$repoRoot = Get-RepoRoot
$specsDir = Join-Path $repoRoot "specs"
$specsDir = Get-SpecsDir -RepoRoot $repoRoot

if (Test-Path $specsDir) {
$latestFeature = ""
Expand Down Expand Up @@ -89,7 +104,7 @@ function Test-FeatureBranch {

function Get-FeatureDir {
param([string]$RepoRoot, [string]$Branch)
Join-Path $RepoRoot "specs/$Branch"
Join-Path (Get-SpecsDir -RepoRoot $RepoRoot) $Branch
}

function Get-FeaturePathsEnv {
Expand Down
7 changes: 6 additions & 1 deletion scripts/powershell/create-new-feature.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ try {

Set-Location $repoRoot

$specsDir = Join-Path $repoRoot 'specs'
$specsDir = Get-SpecsDir -RepoRoot $repoRoot
if (-not $specsDir) {
Write-Host "`n[specify] ERROR: Invalid SPECIFY_SPECS_DIR configuration. Aborting." -ForegroundColor Red
exit 1
}
Comment thread
alanmeadows marked this conversation as resolved.
Comment on lines +161 to +164
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The if (-not $specsDir) branch is currently unreachable because Get-SpecsDir always returns a non-empty string. This makes the new "Invalid SPECIFY_SPECS_DIR configuration" error message misleading. Either add validation/$null return behavior to Get-SpecsDir, or remove this conditional and rely on New-Item/Resolve-Path failures for error handling.

Suggested change
if (-not $specsDir) {
Write-Host "`n[specify] ERROR: Invalid SPECIFY_SPECS_DIR configuration. Aborting." -ForegroundColor Red
exit 1
}

Copilot uses AI. Check for mistakes.
Comment on lines +161 to +164
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The if (-not $specsDir) guard is currently unreachable because Get-SpecsDir (in common.ps1) always returns a non-empty string (either SPECIFY_SPECS_DIR resolved or the default Join-Path $RepoRoot 'specs'). Either remove this check, or add real validation to Get-SpecsDir (e.g., return $null when the path is invalid/uncreatable) so the error message can actually trigger.

Suggested change
if (-not $specsDir) {
Write-Host "`n[specify] ERROR: Invalid SPECIFY_SPECS_DIR configuration. Aborting." -ForegroundColor Red
exit 1
}

Copilot uses AI. Check for mistakes.
New-Item -ItemType Directory -Path $specsDir -Force | Out-Null

Comment thread
alanmeadows marked this conversation as resolved.
# Function to generate branch name with stop word filtering and length filtering
Expand Down Expand Up @@ -271,6 +275,7 @@ if ($Json) {
SPEC_FILE = $specFile
FEATURE_NUM = $featureNum
HAS_GIT = $hasGit
SPECS_DIR = $specsDir
}
$obj | ConvertTo-Json -Compress
} else {
Expand Down
4 changes: 4 additions & 0 deletions templates/commands/analyze.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Load only the minimal necessary context from each artifact:

- Load `/memory/constitution.md` for principle validation

**From shared context (if available):**

- **IF `SPECS_DIR/_shared/` exists**: Read all `.md` files for project-wide standards (architecture decisions, coding conventions, security requirements). Use these as additional validation criteria alongside the constitution.
Comment on lines +70 to +72
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

This adds a shared-context section keyed off SPECS_DIR/_shared, but earlier instructions only say to parse FEATURE_DIR and AVAILABLE_DOCS. Since the script output now includes SPECS_DIR, explicitly include it in the parsed fields (or describe deriving it from FEATURE_DIR) so the shared standards can actually be located.

Copilot uses AI. Check for mistakes.

### 3. Build Semantic Models

Create internal representations (do not include raw artifacts in output):
Expand Down
1 change: 1 addition & 0 deletions templates/commands/checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ You **MUST** consider the user input before proceeding (if not empty).
- spec.md: Feature requirements and scope
- plan.md (if exists): Technical details, dependencies
- tasks.md (if exists): Implementation tasks
- **IF `SPECS_DIR/_shared/` exists**: Read all `.md` files for project-wide standards (security requirements, accessibility standards, coding conventions). Incorporate these into checklist generation to ensure project-wide requirements are validated.

Comment on lines 81 to 86
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Step 1 only instructs parsing FEATURE_DIR/AVAILABLE_DOCS, but step 4 now depends on SPECS_DIR to load shared standards from _shared/. Consider explicitly adding SPECS_DIR to the parsed JSON fields (or explaining how to derive it from FEATURE_DIR) so shared-context loading is reliable.

Copilot uses AI. Check for mistakes.
**Context Loading Strategy**:
- Load only necessary portions relevant to active focus areas (avoid full-file dumping)
Expand Down
18 changes: 11 additions & 7 deletions templates/commands/clarify.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ Execution steps:
- If JSON parsing fails, abort and instruct user to re-run `/speckit.specify` or verify feature branch environment.
- 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").

2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).
2. Load the current spec file from `FEATURE_SPEC`.

3. Load shared project context. **IF `SPECS_DIR/_shared/` exists** (SPECS_DIR is in the JSON output): Read all `.md` files from it for project-wide context (architecture decisions, conventions, standards). Use this shared context to validate spec alignment with project standards and inform ambiguity detection in the next step. If the directory does not exist, proceed without shared context.

Comment on lines +28 to +38
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Step 3 requires SPECS_DIR (to load SPECS_DIR/_shared), but step 1’s “Parse minimal JSON payload fields” list omits SPECS_DIR. Since the script now outputs it, include SPECS_DIR in the fields to parse/capture so the shared-context step is actionable.

Copilot uses AI. Check for mistakes.
4. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).

Functional Scope & Behavior:
- Core user goals & success criteria
Expand Down Expand Up @@ -88,7 +92,7 @@ Execution steps:
- Clarification would not materially change implementation or validation strategy
- Information is better deferred to planning phase (note internally)

3. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
5. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
- Maximum of 10 total questions across the whole session.
- Each question must be answerable with EITHER:
- A short multiple‑choice selection (2–5 distinct, mutually exclusive options), OR
Expand All @@ -99,7 +103,7 @@ Execution steps:
- Favor clarifications that reduce downstream rework risk or prevent misaligned acceptance tests.
- If more than 5 categories remain unresolved, select the top 5 by (Impact * Uncertainty) heuristic.

4. Sequential questioning loop (interactive):
6. Sequential questioning loop (interactive):
- Present EXACTLY ONE question at a time.
- For multiple‑choice questions:
- **Analyze all options** and determine the **most suitable option** based on:
Expand Down Expand Up @@ -135,7 +139,7 @@ Execution steps:
- Never reveal future queued questions in advance.
- If no valid questions exist at start, immediately report no critical ambiguities.

5. Integration after EACH accepted answer (incremental update approach):
7. Integration after EACH accepted answer (incremental update approach):
- Maintain in-memory representation of the spec (loaded once at start) plus the raw file contents.
- For the first integrated answer in this session:
- Ensure a `## Clarifications` section exists (create it just after the highest-level contextual/overview section per the spec template if missing).
Expand All @@ -153,17 +157,17 @@ Execution steps:
- Preserve formatting: do not reorder unrelated sections; keep heading hierarchy intact.
- Keep each inserted clarification minimal and testable (avoid narrative drift).

6. Validation (performed after EACH write plus final pass):
8. Validation (performed after EACH write plus final pass):
- Clarifications session contains exactly one bullet per accepted answer (no duplicates).
- Total asked (accepted) questions ≤ 5.
- Updated sections contain no lingering vague placeholders the new answer was meant to resolve.
- No contradictory earlier statement remains (scan for now-invalid alternative choices removed).
- Markdown structure valid; only allowed new headings: `## Clarifications`, `### Session YYYY-MM-DD`.
- Terminology consistency: same canonical term used across all updated sections.

7. Write the updated spec back to `FEATURE_SPEC`.
9. Write the updated spec back to `FEATURE_SPEC`.

8. Report completion (after questioning loop ends or early termination):
10. Report completion (after questioning loop ends or early termination):
- Number of questions asked & answered.
- Path to updated spec.
- Sections touched (list names).
Expand Down
1 change: 1 addition & 0 deletions templates/commands/implement.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ You **MUST** consider the user input before proceeding (if not empty).
- **IF EXISTS**: Read contracts/ for API specifications and test requirements
- **IF EXISTS**: Read research.md for technical decisions and constraints
- **IF EXISTS**: Read quickstart.md for integration scenarios
- **IF `SPECS_DIR/_shared/` exists**: Read all `.md` files for project-wide context (coding standards, API conventions, security requirements). Use this to guide implementation decisions and ensure alignment with established patterns.
Comment on lines 55 to +58
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The setup step here only mentions parsing FEATURE_DIR and AVAILABLE_DOCS, but this new bullet requires SPECS_DIR for _shared/. To avoid the agent missing the field, update the setup/parsing instructions to capture SPECS_DIR from the script JSON (or derive it from FEATURE_DIR).

Copilot uses AI. Check for mistakes.

4. **Project Setup Verification**:
- **REQUIRED**: Create/verify ignore files based on actual project setup:
Expand Down
2 changes: 1 addition & 1 deletion templates/commands/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ You **MUST** consider the user input before proceeding (if not empty).

1. **Setup**: Run `{SCRIPT}` from repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. 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").

2. **Load context**: Read FEATURE_SPEC and `/memory/constitution.md`. Load IMPL_PLAN template (already copied).
2. **Load context**: Read FEATURE_SPEC and `/memory/constitution.md`. Load IMPL_PLAN template (already copied). **IF `SPECS_DIR/_shared/` exists**: Read all `.md` files from it for project-wide context (architecture decisions, API conventions, coding standards). Use this to inform technical decisions and ensure alignment with established patterns.
Comment on lines 29 to +31
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

This template assumes SPECS_DIR from {SCRIPT} points at the specs root so SPECS_DIR/_shared can be read. But the plan setup scripts (scripts/bash/setup-plan.sh and scripts/powershell/setup-plan.ps1) currently emit SPECS_DIR as the feature directory ($FEATURE_DIR), so this would look for _shared inside the feature folder and never find the shared context. Either update the setup-plan scripts to include the real specs root (and ideally a separate FEATURE_DIR field), or adjust the instruction here to derive the shared dir from the feature dir (e.g., use the parent directory of FEATURE_DIR/SPECS_DIR).

Copilot uses AI. Check for mistakes.

3. **Execute plan workflow**: Follow the structure in IMPL_PLAN template to:
- Fill Technical Context (mark unknowns as "NEEDS CLARIFICATION")
Expand Down
10 changes: 6 additions & 4 deletions templates/commands/specify.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ Given that feature description, do this:

3. Load `templates/spec-template.md` to understand required sections.

4. Follow this execution flow:
4. **Load shared context (if available)**: Check if `SPECS_DIR/_shared/` directory exists (SPECS_DIR is provided in the JSON output from the setup script). If it exists, read all `.md` files from it. These contain project-wide standards (architecture decisions, API conventions, coding standards, security requirements). Use this context to inform spec structure and ensure alignment with established patterns. Do not modify shared files.

5. Follow this execution flow:

1. Parse user description from Input
If empty: ERROR "No feature description provided"
Expand All @@ -99,9 +101,9 @@ Given that feature description, do this:
7. Identify Key Entities (if data involved)
8. Return: SUCCESS (spec ready for planning)

5. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
6. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.

6. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
7. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:

a. **Create Spec Quality Checklist**: Generate a checklist file at `FEATURE_DIR/checklists/requirements.md` using the checklist template structure with these validation items:

Expand Down Expand Up @@ -193,7 +195,7 @@ Given that feature description, do this:

d. **Update Checklist**: After each validation iteration, update the checklist file with current pass/fail status

7. Report completion with branch name, spec file path, checklist results, and readiness for the next phase (`/speckit.clarify` or `/speckit.plan`).
8. Report completion with branch name, spec file path, checklist results, and readiness for the next phase (`/speckit.clarify` or `/speckit.plan`).

**NOTE:** The script creates and checks out the new branch and initializes the spec file before writing.

Expand Down
1 change: 1 addition & 0 deletions templates/commands/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ You **MUST** consider the user input before proceeding (if not empty).
2. **Load design documents**: Read from FEATURE_DIR:
- **Required**: plan.md (tech stack, libraries, structure), spec.md (user stories with priorities)
- **Optional**: data-model.md (entities), contracts/ (API endpoints), research.md (decisions), quickstart.md (test scenarios)
- **IF `SPECS_DIR/_shared/` exists**: Read all `.md` files for project-wide context (coding standards, conventions). Use this to inform task structure and ensure alignment with established patterns.
- Note: Not all projects have all documents. Generate tasks based on what's available.
Comment on lines 27 to 33
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

This outline says to parse only FEATURE_DIR and AVAILABLE_DOCS from the script output, but the next bullet relies on SPECS_DIR to locate _shared/. Since check-prerequisites now emits SPECS_DIR, explicitly include it in the “parse” step (or change the shared-context instruction to derive it from FEATURE_DIR) so the workflow is internally consistent.

Copilot uses AI. Check for mistakes.

3. **Execute task generation workflow**:
Expand Down
Loading