Skip to content

[Bug]: Missing plan template creates a zero-byte plan.md and reports success #4961

Closed

Description

@KSchlobohm

Bug Description

PowerShell plan setup creates an empty plan.md and exits successfully when no plan template resolves. Prerequisite checks accept that empty file, and restoring the template then rerunning setup does not initialize it.

Steps to Reproduce

  1. In an isolated project, copy the checkout's common.ps1, setup-plan.ps1, and check-prerequisites.ps1 into .specify\scripts\powershell.
  2. Create .specify\feature.json containing {"feature_directory":"specs/001-repro"}, create that feature directory and a nonempty spec.md, and leave all plan-template sources absent.
  3. From the fixture root, run pwsh -NoProfile -NonInteractive -File .\.specify\scripts\powershell\setup-plan.ps1 -Json. Inspect the exit code and plan.md size.
  4. Run pwsh -NoProfile -NonInteractive -File .\.specify\scripts\powershell\check-prerequisites.ps1 -Json -RequireSpec.
  5. Copy the checkout's templates\plan-template.md into the fixture's .specify\templates\plan-template.md and rerun setup and prerequisites.

Run with inherited SPECIFY_* environment variables cleared so feature resolution uses the fixture's state rather than another project.

Expected Behavior

Missing required plan template should cause setup to fail with an actionable diagnostic, without creating an unusable empty plan. Prerequisites should not treat an empty plan as ready for downstream work.

Actual Behavior

Missing-template setup exits 0, emits Warning: Plan template not found on stderr, returns valid path JSON, and creates a zero-byte plan.md. Prerequisites exit 0.

After restoring the template, setup exits 0 and reports skipping template copy; plan.md remains zero bytes and prerequisites still exit 0.

The missing-template case also succeeds in text mode; its warning goes to stdout instead of stderr.

Specify CLI Version

1.1.4

AI Agent

Alquimia AI

Operating System

Windows; PowerShell 7.6.7

Python Version

Python 3.11.5 (reproduction harness)

Error Logs

Missing template:
  stderr: Warning: Plan template not found
  exit code: 0
  plan.md size: 0 bytes

Prerequisites with empty plan (-Json -RequireSpec):
  exit code: 0

Restored template, setup rerun:
  stderr: Plan already exists at <fixture>\specs\001-repro\plan.md, skipping template copy
  exit code: 0
  plan.md size: 0 bytes

Prerequisites after template restoration:
  exit code: 0

Additional Context

No response

AI Disclosure

GitHub Copilot, powered by GPT-6.1 Sol

Activity

  1. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    Bug assessment — missing-plan-template: Valid · severity medium


    Bug Assessment: Missing plan template creates a zero-byte plan.md and reports success

    Report (summarized)

    The reporter observes that, on Windows with PowerShell 7.6.7 and Specify CLI 1.1.4, running the installed PowerShell setup-plan.ps1 -Json with no resolvable plan template exits successfully, emits a warning, returns path JSON, and creates a zero-byte plan.md. check-prerequisites.ps1 -Json -RequireSpec then accepts that file. Restoring the template and rerunning setup does not repair the file because setup treats the existing empty file as a valid plan. The report also notes the missing-template text-mode warning is written to stdout.

    No additional comments supplied reproduction context.

    Symptom

    When plan-template.md cannot be resolved, PowerShell setup reports success and materializes an empty plan file instead of failing without creating an unusable artifact. Because prerequisite validation checks only whether plan.md exists, downstream workflow steps proceed as though a usable plan is present; later template restoration is ineffective because the existing empty file is skipped.

    Reproduction

    1. Install common.ps1, setup-plan.ps1, and check-prerequisites.ps1 into an isolated fixture's .specify\scripts\powershell directory.
    2. Create .specify\feature.json pointing to specs/001-repro, create that feature directory with a nonempty spec.md, and leave all plan-template sources absent.
    3. Run pwsh -NoProfile -NonInteractive -File .\.specify\scripts\powershell\setup-plan.ps1 -Json; observe exit code 0 and a zero-byte plan.md.
    4. Run check-prerequisites.ps1 -Json -RequireSpec; observe exit code 0.
    5. Restore .specify\templates\plan-template.md and rerun setup; observe that the existing empty plan is skipped and remains zero bytes.

    The report states that inherited SPECIFY_* variables were cleared. The exact fixture and command output are from the issue report.

    Suspected Code Paths

    • scripts/powershell/setup-plan.ps1:41-67 — checks only whether IMPL_PLAN is a leaf file; when template resolution returns $null, prints Warning: Plan template not found, creates the file with New-Item, and continues to the success JSON output.
    • scripts/powershell/setup-plan.ps1:42-47 — on subsequent runs, any existing plan.md, including zero bytes, takes the skip path, so a later template restoration cannot initialize it.
    • scripts/powershell/check-prerequisites.ps1:103-109 — validates IMPL_PLAN with Test-Path ... -PathType Leaf, which accepts an empty file and does not validate nonzero content.
    • scripts/powershell/common.ps1:532-600 — Resolve-TemplateContent is the template-resolution boundary and returns $null when no valid template source is found.
    • scripts/bash/setup-plan.sh:45-63 and scripts/python/setup_plan.py:68-72 — the same empty-file fallback exists in the Bash and Python ports, indicating this is a cross-port behavior gap rather than only a PowerShell implementation detail.
    • tests/test_setup_plan_python_parity.py:125-143 — current parity coverage explicitly expects missing-template setup to return 0 and create an empty plan, so it would need to change with the intended behavior.
    • tests/test_setup_plan_no_overwrite.py:258-285 — current PowerShell coverage expects a missing-template warning but also a successful run, leaving the failure case untested.

    Root Cause Hypothesis

    Confidence: high. The setup contract treats template absence as a recoverable warning: PowerShell explicitly calls New-Item -ItemType File after a null template result, while prerequisite checks define readiness as file existence only. The existing-file guard then makes the empty placeholder durable. The Bash and Python ports implement the same fallback (touch / touch()), so parity tests have institutionalized the behavior.

    Proposed Remediation

    Preferred: Treat inability to resolve the required plan-template as a setup error. In all three setup implementations, emit an actionable diagnostic to stderr, remove any partially created output if necessary, return a nonzero exit code, and do not create plan.md. Preserve the existing-plan behavior for a nonempty user-authored file. Add a content/readiness check to prerequisite validation so an empty plan.md is rejected (with a clear remediation message), or ensure setup is the only producer and reject zero-byte files there as well. The error and stream behavior should remain consistent between JSON and text modes: stdout must stay reserved for the documented JSON payload in JSON mode.

    A compatibility-conscious variant can recognize an existing zero-byte plan.md as an incomplete setup artifact, replace it only when a template is now resolvable, and fail otherwise. This repairs the reported restoration scenario but risks overwriting a deliberately empty user file; the preferred approach avoids treating empty files as valid and requires explicit user action for ambiguous existing files.

    Files likely to change:

    • scripts/powershell/setup-plan.ps1
    • scripts/bash/setup-plan.sh
    • scripts/python/setup_plan.py
    • scripts/powershell/check-prerequisites.ps1
    • scripts/bash/check-prerequisites.sh
    • scripts/python/check_prerequisites.py
    • tests/test_setup_plan_python_parity.py
    • tests/test_setup_plan_no_overwrite.py
    • tests/test_check_prerequisites_python_parity.py

    Tests to add or update:

    • For each implementation, missing plan-template returns nonzero, writes no plan.md, and emits the same actionable error in JSON and text modes with JSON stdout remaining parseable where applicable.
    • An existing nonempty plan remains unchanged and setup remains successful.
    • A pre-existing zero-byte plan is not accepted by prerequisites; verify the diagnostic and nonzero exit code for both normal and -RequireSpec/equivalent flows.
    • After a failed missing-template run, adding the template and rerunning creates the template-backed plan.
    • Preserve parity across Bash, PowerShell, and Python, including template-composition errors and path resolution behavior.

    Risks & Considerations

    • This changes an established success-shaped fallback and may surface failures earlier for projects that currently rely on an empty placeholder; release notes or migration guidance may be appropriate.
    • Rejecting empty files can affect users who intentionally created a blank plan, so the error should explain how to remove/recreate it or populate it manually.
    • Keep template-resolution errors distinct from a missing template and preserve nonzero status codes; do not mask composition or filesystem errors.
    • The Bash/Python parity tests currently encode the old behavior, so updating only PowerShell would leave the ports inconsistent and would not address the same root cause elsewhere.
    • No security or data-loss impact is evident from the report; the main impact is silent workflow misconfiguration and potentially wasted downstream agent work.

    Open Questions

    • [NEEDS CLARIFICATION: Should an existing zero-byte plan.md always be treated as invalid, or should setup repair it automatically when a template becomes available?]
    • [NEEDS CLARIFICATION: Is the intended contract to reject whitespace-only plans as well as strictly zero-byte files?]
    • [NEEDS CLARIFICATION: Should the remediation be released as a cross-port behavior change, or is PowerShell compatibility requiring a staged rollout?]

    Generated by 🐛 Assess Bug from Labeled Issue for #4961 · copilot · gpt52codex · 1.81 AIC · ⌖ 0.596 AIC · ⊞ 22.1K · ◷

  2. added
    bug-fixTrigger the bug-fix agentic workflow
    triage-nice-to-haveVerdict: evidence-backed fix or greenlit feature — land after review
    and removed on Oct 14, 2026
  3. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    Pull request created: #4962

    Generated by Fix Bug from Labeled Issue · copilot · gpt52codex · 6.33 AIC · ⌖ 0.719 AIC · ⊞ 24.4K

  4. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    Draft PR #4962 proposes the missing-plan-template fix: setup now fails without creating plan.md when the template is missing, and prerequisite checks reject zero-byte plans. Please review the draft and validate the fix in the stage-3 bug-test workflow if configured.

    Generated by 🛠️ Fix Bug from Labeled Issue for #4961 · copilot · gpt52codex · 6.33 AIC · ⌖ 0.719 AIC · ⊞ 24.4K · ◷

  5. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    Bug test — missing-plan-template: ⚠️ inconclusive · 0 passed, 0 failed, 0 skipped · fix from PR #4962 (head 9c7cc2221231913023ed6fd8b7bf4dc734b42900)


    Bug Test Report: Missing plan template creates an empty plan

    Summary

    The proposed fix was checked out at the PR head, and the repository's focused regression tests were identified. The test run could not start because the runner denied permission for dependency setup and test-process execution before either command produced test results; therefore this run provides no pass/fail evidence for the fix.

    Test Results

    Metric Count
    Passed 0
    Failed 0
    Skipped 0
    Errored 0
    Duration Not measured; execution was blocked before tests started

    Failures (if any)

    None. The run was blocked during environment/test-process setup rather than by an assertion failure.

    Verification vs. Historical Fix

    Not applicable (no historical fix referenced in the issue or assessment).

    Notes & Caveats

    • Fix source: linked PR [bug-fix] Fix missing-plan-template: reject empty plan setup #4962, head SHA 9c7cc2221231913023ed6fd8b7bf4dc734b42900.
    • The project uses Python/pytest with the test optional dependency group in pyproject.toml; the focused tests are the three files named by the bug-fix assessment and PR.
    • uv sync --extra test was attempted first, but the runner returned a permission-denied result before dependency setup could execute. A direct timed pytest invocation was also blocked by the runner, so no test counts or duration can be inferred.
    • PowerShell is present on the runner, but invoking the PowerShell runtime was likewise blocked; PowerShell-specific tests therefore did not run.
    • To produce a passing or failing result, rerun this stage in a runner that permits the repository's dependency installation and test processes.

    Generated by 🧪 Test a Bug Fix from a Labeled Issue for #4961 · copilot · gpt52codex · 1.4 AIC · ⌖ 0.633 AIC · ⊞ 27.2K · ◷

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions