Skip to content

Conversation

@pproenca
Copy link
Owner

@pproenca pproenca commented Dec 29, 2025

Summary

Transform hyh into a complete spec-driven development workflow tool with Claude Code plugin integration:

  • Speckit checkbox parser - Parse tasks.md format with phase-based dependencies
  • DHH-style git worktrees - hyh worktree create/list/switch for feature isolation
  • Workflow phase detection - Auto-detect specify → plan → implement → complete phases
  • Claude Code plugin - /hyh command with guided workflow routing
  • hyh init command - Scaffold plugin + templates in any project

Key Changes

Area Files Description
Parser plan.py parse_speckit_tasks(), SpecTaskList.to_workflow_state()
Worktree worktree.py DHH-style create_worktree(), list_worktrees(), get_worktree()
Workflow workflow.py detect_phase() with 5-state machine
CLI client.py worktree create/list/switch, workflow status commands
Templates templates/ 4 bundled templates (spec, plan, tasks, checklist)
Plugin plugin/ Claude Code plugin files (commands, hooks, skills)
Init init.py init_project() scaffolds .claude/plugins/hyh/ and .hyh/

Test Plan

  • All 479 tests pass
  • Integration test covers full workflow (init → worktree → phases → completion)
  • Templates accessible via importlib.resources
  • Plugin files valid JSON/markdown with proper frontmatter

Summary by CodeRabbit

Release Notes

  • New Features
    • Added spec-driven development workflow with CLI commands for specify, plan, and implement phases
    • Added project initialization tool that scaffolds plugin configuration and templates
    • Added Git worktree management for feature-branch isolation (create, list, switch commands)
    • Added workflow phase detection and status tracking
    • Bundled templates for specifications, implementation plans, task tracking, and checklists
    • Added Claude Code plugin integration with automated workflow hooks

✏️ Tip: You can customize this high-level summary in your review settings.

Design for transforming hyh into a complete spec-driven development
workflow tool with:
- Claude Code plugin architecture
- DHH-style git worktree management
- Three-phase workflow (specify/plan/implement)
- Speckit checkbox format parser
- Bundled templates from test-prompt
12-task TDD implementation plan covering:
- Speckit checkbox parser with phase dependencies
- DHH-style git worktree management
- Workflow state detection
- Claude Code plugin files
- hyh init command
- Full integration test
Enhance documentation with format examples, checkbox markers, and special flags to clarify the speckit task parsing format.
Implements git worktree management with sibling directory naming pattern
(project--branch). This allows parallel development on multiple features
in isolated directories.
Add functions to list all DHH-style worktrees for a repository and
find a specific worktree by branch name. The list function parses
git worktree list --porcelain output and filters to worktrees matching
the {repo}--{branch} naming pattern.
Adds WorkflowPhase struct and detect_phase() function to determine
current workflow state based on specs directory contents:
- No spec.md -> phase="none", next_action="specify"
- Has spec.md, no plan.md -> phase="specify", next_action="plan"
- Has plan.md, tasks incomplete -> phase="plan", next_action="implement"
- All tasks complete -> phase="complete", next_action=None
Add `hyh workflow status` CLI command that wraps detect_phase() to show
current workflow phase with three output modes:
- Default: Human-readable status with progress
- --json: Machine-readable JSON output
- --quiet: Minimal one-line output for hooks
Bundle spec, plan, tasks, and checklist templates from the speckit
workflow into the hyh package, making them accessible via importlib.resources.
This allows templates to be shipped with `pip install hyh`.
Add plugin structure for hyh that provides:
- Main /hyh command with subcommand routing (specify/plan/implement/status)
- /hyh:help command for documentation
- SessionStart hook to show workflow status on session start
- spec-driven-dev skill for AI guidance on the workflow

Files created:
- plugin.json: Plugin manifest
- commands/hyh.md: Main command with argument routing
- commands/help.md: Help documentation
- hooks/hooks.json: SessionStart hook configuration
- skills/spec-driven-dev.md: Workflow guidance skill

Also excludes plugin markdown files from mdformat and markdownlint
hooks to preserve YAML frontmatter.
Add `hyh init` command that scaffolds:
- .claude/plugins/hyh/ with plugin files (plugin.json, commands, hooks, skills)
- .hyh/ with config.json and templates

The command auto-detects the main branch from git and initializes
next_feature_number to 1 in the config.
Adds end-to-end test covering hyh init, worktree creation, workflow
phase detection through all states, and speckit task parsing.
@coderabbitai
Copy link

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive spec-driven development workflow framework for hyh. It adds project initialization with plugin scaffolding, Git worktree management using DHH-style naming, workflow phase detection (specify/plan/implement), Speckit checkbox task parsing with dependency inference, new CLI commands (init, worktree, workflow), complete plugin infrastructure with configuration and command documentation, bundled templates for spec and plan generation, and an extensive test suite with bash utility scripts for feature branch management.

Changes

Cohort / File(s) Summary
Core Workflow Management
src/hyh/init.py, src/hyh/worktree.py, src/hyh/workflow.py
New modules implementing project initialization with plugin and template scaffolding, DHH-style git worktree creation/listing, and workflow phase detection (none/specify/plan/complete) based on spec/plan/tasks presence.
Task Parsing & State Conversion
src/hyh/plan.py
Added SpecTaskDefinition and SpecTaskList data structures; new parse_speckit_tasks() function to extract phases, tasks, statuses, user stories, and file paths from checkbox-formatted markdown; new to_workflow_state() method converting parsed tasks to WorkflowState with dependency inference.
CLI Extensions
src/hyh/client.py
Integrated new subcommands: init, worktree (create/list/switch), and workflow status with JSON and quiet output modes; added corresponding internal command handlers routing to new modules.
Plugin Configuration & Documentation
src/hyh/plugin/plugin.json, src/hyh/plugin/commands/hyh.md, src/hyh/plugin/commands/help.md, src/hyh/plugin/hooks/hooks.json, src/hyh/plugin/skills/spec-driven-dev.md
Added complete plugin metadata, command routing, workflow documentation, session start hook for status display, and skills documentation outlining the three-phase spec-driven development process.
Markdown Templates (hyh package)
src/hyh/templates/spec-template.md, src/hyh/templates/plan-template.md, src/hyh/templates/tasks-template.md, src/hyh/templates/checklist-template.md
New bundled templates for feature specifications (user stories, requirements, success criteria), implementation plans (technical context, governance checks, project structure), task lists (phase-based organization with dependencies), and checklists with metadata and category placeholders.
Markdown Templates (test-prompt)
test-prompt/.specify/templates/*
Parallel set of templates mirroring hyh package templates for test/demo usage, including agent context template for AI agent integration.
Test Suite
tests/hyh/test_init.py, tests/hyh/test_worktree.py, tests/hyh/test_workflow.py, tests/hyh/test_plan.py, tests/hyh/test_templates.py, tests/hyh/test_integration_workflow.py
Comprehensive unit and integration tests covering project initialization, worktree CRUD operations, workflow phase detection across all states, Speckit parsing with dependencies, template asset validation, and full end-to-end workflow from init through task completion.
Bash Utility Scripts
test-prompt/.specify/scripts/bash/common.sh, test-prompt/.specify/scripts/bash/check-prerequisites.sh, test-prompt/.specify/scripts/bash/create-new-feature.sh, test-prompt/.specify/scripts/bash/setup-plan.sh, test-prompt/.specify/scripts/bash/update-agent-context.sh
Helper scripts for feature directory management, branch discovery, prerequisite validation, feature creation with auto-numbering, plan setup, and agent context file generation with plan data extraction.
Planning & Design Documents
docs/plans/2025-12-29-speckit-implementation.md, docs/plans/2025-12-29-speckit-integration-design.md, test-prompt/.specify/memory/constitution.md
Architecture documentation and design rationale for Speckit integration, dual package/plugin architecture, workflow lifecycle, and project governance principles.
Configuration Updates
.nvim.lua, .pre-commit-config.yaml, pyproject.toml
Added Neovim local config enabling Neo-tree with custom filtering, excluded src/hyh/plugin/ from pre-commit hooks (mdformat, markdownlint-fix), and suppressed S603/S607 bandit checks for new modules with subprocess calls.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as hyh CLI
    participant Init as init.py
    participant Worktree as worktree.py
    participant Workflow as workflow.py
    participant Plan as plan.py

    User->>CLI: /hyh init
    CLI->>Init: init_project(root)
    Init->>Init: Create .claude/plugins/hyh
    Init->>Init: Create .hyh with config.json
    Init->>Init: Copy bundled templates
    Init-->>CLI: InitResult
    
    User->>CLI: /hyh worktree create feature-branch
    CLI->>Worktree: create_worktree(main_repo, branch)
    Worktree->>Worktree: git worktree add repo--branch
    Worktree-->>CLI: WorktreeResult
    
    User->>CLI: /hyh workflow status
    CLI->>Workflow: detect_phase(worktree_path)
    Workflow->>Workflow: Check specs/spec.md exists?
    alt spec missing
        Workflow-->>CLI: phase=none, next_action=specify
    else spec exists, plan missing
        Workflow-->>CLI: phase=specify, next_action=plan
    else plan exists, parse tasks
        Workflow->>Plan: parse_speckit_tasks(tasks.md)
        Plan->>Plan: Extract phases & dependencies
        Plan-->>Workflow: SpecTaskList
        Workflow->>Workflow: Count tasks & completion
        alt all tasks done
            Workflow-->>CLI: phase=complete, next_action=None
        else tasks pending
            Workflow-->>CLI: phase=plan, next_action=implement
        end
    end
    
    CLI-->>User: Display phase & next action
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Worktrees sprout like carrots in the garden fair,
Specs and plans unfold with utmost care,
Phase by phase, the workflow hops along,
From specify to done—a dev-song strong!
Templates bloom, tasks parse with cheer,
Spec-driven dreams now crystal clear! 🌱

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.10% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: integrate speckit workflow into hyh' directly and accurately reflects the main objective of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (16)
src/hyh/plugin/hooks/hooks.json (2)

5-5: Verify that empty matcher is intentional.

The empty matcher string means this SessionStart hook will execute on every session regardless of context. This could result in the workflow status command running even when not needed.

Consider whether you want to add a matcher pattern to scope this hook to specific session contexts (e.g., only in feature worktrees or when a spec file exists).


9-9: Consider adding timeout and error handling to the hook command.

The hook executes hyh workflow status --quiet without any timeout or error handling configuration. If the command hangs or fails, it could impact session startup experience.

Verify whether the Claude Code plugin system supports additional configuration options for command hooks such as:

  • Timeout values
  • Error handling strategies (fail silently, log, etc.)
  • Background execution
Does Claude Code plugin hooks.json support timeout or error handling configuration for command hooks?
src/hyh/plugin/skills/spec-driven-dev.md (1)

1-36: Clear documentation of the spec-driven workflow.

The skill document effectively communicates the three-phase workflow (Specify → Plan → Implement) and provides clear rationale for each step. The structure aligns well with the broader PR objectives.

💡 Optional: Consider adding concrete examples

To help users understand the workflow more quickly, consider adding a brief "Quick Example" section:

+## Quick Example
+
+```bash
+# 1. Start with an idea
+/hyh specify "Add user authentication with OAuth"
+
+# 2. Generate the plan
+/hyh plan
+
+# 3. Execute the implementation
+/hyh implement
+
+# Check progress anytime
+/hyh status
+```
+
 ## Why This Matters
.nvim.lua (1)

1-12: Project-local Neovim configuration looks good.

The Neo-tree configuration is straightforward and improves the development experience by showing hidden files while hiding git-ignored files.

Security note: Line 2's comment mentions vim.o.exrc = true. Be aware that enabling exrc allows Neovim to execute project-local configuration files, which could be a security risk if you open untrusted repositories. Ensure team members are aware of this requirement and its implications.

src/hyh/plugin/commands/hyh.md (1)

1-56: Comprehensive command documentation with clear workflow steps.

The routing logic and step-by-step instructions for each command (specify/plan/implement/status) are well-defined and align with the broader spec-driven workflow introduced in this PR.

💡 Optional: Consider clarifying "consistency analysis" on line 32

Line 32 mentions "Run consistency analysis" without explaining what this involves. Consider adding a brief note about what aspects are checked:

-8. Run consistency analysis
+8. Run consistency analysis (verify spec alignment, check for conflicting requirements, validate entity relationships)
test-prompt/.specify/scripts/bash/check-prerequisites.sh (1)

82-82: Address shellcheck warning: quote command substitution.

Shellcheck flags unquoted command substitution which could lead to word splitting issues. While eval is used here intentionally to set variables from get_feature_paths output, it's still best practice to quote the command substitution for safety.

🔎 Proposed fix
 # Get feature paths and validate branch
-eval $(get_feature_paths)
+eval "$(get_feature_paths)"
 check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1

Based on static analysis hints (Shellcheck).

test-prompt/.specify/scripts/bash/create-new-feature.sh (1)

91-111: Use -print0 with xargs -0 for safe filename handling.

The find ... | xargs pipeline on line 99 can break with directory names containing spaces or special characters. This is flagged by ShellCheck (SC2038).

🔎 Proposed fix
-    local spec_dirs=""
-    if [ -d "$SPECS_DIR" ]; then
-        spec_dirs=$(find "$SPECS_DIR" -maxdepth 1 -type d -name "[0-9]*-${short_name}" 2>/dev/null | xargs -n1 basename 2>/dev/null | sed 's/-.*//' | sort -n)
-    fi
+    local spec_dirs=""
+    if [ -d "$SPECS_DIR" ]; then
+        spec_dirs=$(find "$SPECS_DIR" -maxdepth 1 -type d -name "[0-9]*-${short_name}" -print0 2>/dev/null | xargs -0 -n1 basename 2>/dev/null | sed 's/-.*//' | sort -n)
+    fi
src/hyh/init.py (1)

20-42: Consider adding timeout to subprocess calls.

The subprocess.run calls in _get_main_branch don't specify a timeout. If git is unresponsive (e.g., waiting for SSH passphrase, network issues), the call could hang indefinitely.

🔎 Proposed fix
     result = subprocess.run(
         ["git", "symbolic-ref", "refs/remotes/origin/HEAD"],
         cwd=project_root,
         capture_output=True,
         text=True,
+        timeout=10,
     )
     if result.returncode == 0:
         # refs/remotes/origin/main -> main
         return result.stdout.strip().split("/")[-1]

     # Fallback: check if main or master exists
     for branch in ["main", "master"]:
         result = subprocess.run(
             ["git", "rev-parse", "--verify", branch],
             cwd=project_root,
             capture_output=True,
+            timeout=10,
         )
test-prompt/.specify/scripts/bash/common.sh (1)

127-156: Consider splitting declaration and assignment for robustness.

ShellCheck flags SC2155 on lines 128, 129, and 137. If the subshell commands fail, the exit status is masked by the assignment. While the current code handles empty strings gracefully, separating declaration and assignment is a defensive practice.

🔎 Proposed fix
 get_feature_paths() {
-    local repo_root=$(get_repo_root)
-    local current_branch=$(get_current_branch)
+    local repo_root
+    repo_root=$(get_repo_root)
+    local current_branch
+    current_branch=$(get_current_branch)
     local has_git_repo="false"

     if has_git; then
         has_git_repo="true"
     fi

     # Use prefix-based lookup to support multiple branches per spec
-    local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
+    local feature_dir
+    feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
src/hyh/worktree.py (1)

21-52: Consider adding timeout to subprocess.run.

Similar to init.py, the subprocess call could hang indefinitely if git is unresponsive.

🔎 Proposed fix
     subprocess.run(
         ["git", "worktree", "add", "-b", branch_name, str(worktree_path)],
         cwd=main_repo,
         capture_output=True,
         check=True,
+        timeout=30,
     )
test-prompt/.specify/scripts/bash/update-agent-context.sh (6)

302-304: Declare and assign separately to avoid masking return values.

When local and command substitution are combined, a non-zero exit from the subshell is masked by the successful local declaration.

🔎 Proposed fix
-    local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
-    local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
-    local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
+    local escaped_lang
+    escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
+    local escaped_framework
+    escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
+    local escaped_branch
+    escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')

Based on shellcheck SC2155.


374-374: Separate declaration from assignment.

Same issue as above - the return value from format_technology_stack would be masked.

🔎 Proposed fix
-    local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")
+    local tech_stack
+    tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")

Based on shellcheck SC2155.


412-412: Remove unused variable file_ended.

This variable is declared but never used in the function.

🔎 Proposed fix
     local changes_entries_added=false
     local existing_changes_count=0
-    local file_ended=false

Based on shellcheck SC2034.


453-459: Existing entries beyond limit 2 are silently dropped.

When processing "Recent Changes", only the first 2 existing entries are preserved (lines 454-458). Combined with the new entry added at line 444, this results in at most 3 entries. This behavior is likely intentional (keeping last 3 changes), but the limit is hardcoded and the logic is split.

Consider extracting the limit as a constant and adding a brief comment for clarity:

readonly MAX_RECENT_CHANGES=3  # Keep last N changes

# In update_existing_agent_file:
# Keep only first (MAX_RECENT_CHANGES - 1) existing changes since we add one new entry
if [[ $existing_changes_count -lt $((MAX_RECENT_CHANGES - 1)) ]]; then

486-489: Remove unused variable changes_entries_added.

The variable is set at lines 447 and 488 but never read.

🔎 Proposed fix
-            changes_entries_added=true
             continue

And remove the assignment at line 488:

         echo "$new_change_entry" >> "$temp_file"
-        changes_entries_added=true
     fi

Based on shellcheck SC2034.


700-701: Missing newline before function definition.

The print_summary function definition immediately follows the closing brace of update_all_existing_agents without a blank line, reducing readability.

🔎 Proposed fix
     fi
 }
+
 print_summary() {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb87a32 and 9d92e0d.

📒 Files selected for processing (36)
  • .nvim.lua
  • .pre-commit-config.yaml
  • docs/plans/2025-12-29-speckit-implementation.md
  • docs/plans/2025-12-29-speckit-integration-design.md
  • pyproject.toml
  • src/hyh/client.py
  • src/hyh/init.py
  • src/hyh/plan.py
  • src/hyh/plugin/commands/help.md
  • src/hyh/plugin/commands/hyh.md
  • src/hyh/plugin/hooks/hooks.json
  • src/hyh/plugin/plugin.json
  • src/hyh/plugin/skills/spec-driven-dev.md
  • src/hyh/templates/checklist-template.md
  • src/hyh/templates/plan-template.md
  • src/hyh/templates/spec-template.md
  • src/hyh/templates/tasks-template.md
  • src/hyh/workflow.py
  • src/hyh/worktree.py
  • test-prompt/.specify/memory/constitution.md
  • test-prompt/.specify/scripts/bash/check-prerequisites.sh
  • test-prompt/.specify/scripts/bash/common.sh
  • test-prompt/.specify/scripts/bash/create-new-feature.sh
  • test-prompt/.specify/scripts/bash/setup-plan.sh
  • test-prompt/.specify/scripts/bash/update-agent-context.sh
  • test-prompt/.specify/templates/agent-file-template.md
  • test-prompt/.specify/templates/checklist-template.md
  • test-prompt/.specify/templates/plan-template.md
  • test-prompt/.specify/templates/spec-template.md
  • test-prompt/.specify/templates/tasks-template.md
  • tests/hyh/test_init.py
  • tests/hyh/test_integration_workflow.py
  • tests/hyh/test_plan.py
  • tests/hyh/test_templates.py
  • tests/hyh/test_workflow.py
  • tests/hyh/test_worktree.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use msgspec.Struct instead of dataclasses for defining structs
Use forbid_unknown_fields=True when defining msgspec.Struct classes
Use tuples instead of lists for immutable collections in struct fields
Type hints are mandatory everywhere in Python code
Use Final for immutable attributes in Python
Use ClassVar for class-level variables in Python
Always use datetime.now(UTC) for timezone-aware datetimes in Python

Files:

  • tests/hyh/test_init.py
  • src/hyh/workflow.py
  • tests/hyh/test_integration_workflow.py
  • src/hyh/init.py
  • src/hyh/worktree.py
  • tests/hyh/test_workflow.py
  • tests/hyh/test_templates.py
  • tests/hyh/test_plan.py
  • src/hyh/plan.py
  • src/hyh/client.py
  • tests/hyh/test_worktree.py
🧬 Code graph analysis (9)
tests/hyh/test_init.py (1)
src/hyh/init.py (2)
  • init_project (45-124)
  • InitResult (11-17)
test-prompt/.specify/scripts/bash/setup-plan.sh (1)
test-prompt/.specify/scripts/bash/common.sh (2)
  • get_feature_paths (127-152)
  • check_feature_branch (65-82)
tests/hyh/test_integration_workflow.py (4)
src/hyh/init.py (1)
  • init_project (45-124)
src/hyh/worktree.py (1)
  • create_worktree (21-52)
src/hyh/workflow.py (1)
  • detect_phase (21-84)
src/hyh/plan.py (1)
  • parse_speckit_tasks (278-348)
test-prompt/.specify/scripts/bash/update-agent-context.sh (1)
test-prompt/.specify/scripts/bash/common.sh (1)
  • get_feature_paths (127-152)
test-prompt/.specify/scripts/bash/check-prerequisites.sh (1)
test-prompt/.specify/scripts/bash/common.sh (4)
  • get_feature_paths (127-152)
  • check_feature_branch (65-82)
  • check_file (154-154)
  • check_dir (155-155)
tests/hyh/test_plan.py (2)
src/hyh/plan.py (3)
  • parse_speckit_tasks (278-348)
  • to_workflow_state (53-64)
  • to_workflow_state (89-105)
src/hyh/state.py (1)
  • TaskStatus (57-61)
src/hyh/plan.py (1)
src/hyh/state.py (3)
  • WorkflowState (114-176)
  • TaskStatus (57-61)
  • Task (67-111)
src/hyh/client.py (3)
src/hyh/init.py (1)
  • init_project (45-124)
src/hyh/worktree.py (3)
  • create_worktree (21-52)
  • list_worktrees (55-98)
  • get_worktree (101-115)
src/hyh/workflow.py (1)
  • detect_phase (21-84)
tests/hyh/test_worktree.py (2)
src/hyh/worktree.py (3)
  • create_worktree (21-52)
  • list_worktrees (55-98)
  • get_worktree (101-115)
src/hyh/client.py (1)
  • main (441-640)
🪛 LanguageTool
test-prompt/.specify/memory/constitution.md

[grammar] ~86-~86: Ensure spelling is correct
Context: ...: - All API response times must target 200ms or less at the 95th percentile (p95) - ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

test-prompt/.specify/templates/plan-template.md

[grammar] ~55-~55: Ensure spelling is correct
Context: ... ] Are API response time targets (p95 < 200ms) considered? - [ ] Is database optimiza...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

src/hyh/templates/plan-template.md

[grammar] ~55-~55: Ensure spelling is correct
Context: ... ] Are API response time targets (p95 < 200ms) considered? - [ ] Is database optimiza...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
docs/plans/2025-12-29-speckit-integration-design.md

28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


60-60: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


136-136: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


149-149: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


164-164: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


179-179: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


225-225: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


248-248: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


286-286: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


292-292: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


298-298: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


304-304: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🪛 Shellcheck (0.11.0)
test-prompt/.specify/scripts/bash/setup-plan.sh

[warning] 31-31: Quote this to prevent word splitting.

(SC2046)

test-prompt/.specify/scripts/bash/common.sh

[warning] 10-10: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 39-39: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 128-128: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 129-129: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 137-137: Declare and assign separately to avoid masking return values.

(SC2155)

test-prompt/.specify/scripts/bash/update-agent-context.sh

[warning] 56-56: Quote this to prevent word splitting.

(SC2046)


[warning] 302-302: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 303-303: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 304-304: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 374-374: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 412-412: file_ended appears unused. Verify use (or export if used externally).

(SC2034)


[warning] 488-488: changes_entries_added appears unused. Verify use (or export if used externally).

(SC2034)

test-prompt/.specify/scripts/bash/check-prerequisites.sh

[warning] 82-82: Quote this to prevent word splitting.

(SC2046)

test-prompt/.specify/scripts/bash/create-new-feature.sh

[warning] 91-91: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 94-94: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 99-99: Use 'find .. -print0 | xargs -0 ..' or 'find .. -exec .. +' to allow non-alphanumeric filenames.

(SC2038)


[warning] 144-144: Declare and assign separately to avoid masking return values.

(SC2155)

🔇 Additional comments (55)
test-prompt/.specify/templates/agent-file-template.md (1)

1-29: Clean template structure for auto-generated development guidelines.

The template provides a logical, well-organized scaffolding for developer-facing documentation. The section hierarchy (technologies → structure → commands → style → recent changes) supports quick onboarding, and the manual additions section appropriately allows customization on top of auto-generated content. Placeholder format is clear and maintainable.

.pre-commit-config.yaml (1)

41-41: Markdown exclusions are justified.

The plugin markdown files (help.md, hyh.md, spec-driven-dev.md) contain YAML front matter with Claude Code plugin-specific metadata (description, argument-hint, allowed-tools, etc.). Excluding them from mdformat and markdownlint-fix prevents these formatters from altering plugin-critical metadata structures. The pattern scope is appropriate for this use case.

pyproject.toml (1)

131-134: LGTM! Security suppressions appropriately justified.

The S603/S607 suppressions for worktree.py and init.py are correctly scoped and documented. The comments clearly explain that these modules intentionally execute git commands via subprocess, which is consistent with the existing pattern for other command-execution modules in the project.

test-prompt/.specify/templates/spec-template.md (1)

1-115: Excellent template structure for independent user stories.

The template does an outstanding job emphasizing:

  • Priority-based organization (P1, P2, P3)
  • Independent testability of each user story
  • Clear acceptance criteria
  • Separation of requirements and success metrics

The inline HTML comment guidance is particularly helpful for template users. This structure supports incremental delivery and MVP-first development well.

src/hyh/templates/tasks-template.md (3)

27-44: Excellent warning for template users.

The prominent HTML comment warning that sample tasks must be replaced is critical for preventing copy-paste errors. The explicit instructions on what to replace and how to organize tasks by user stories are very helpful.


46-185: Outstanding phase-based task organization.

The template excels at:

  • Clear phase dependencies (Setup → Foundational → User Stories → Polish)
  • Emphasis on foundational tasks blocking all user stories
  • Independent testability of each user story
  • Checkpoint markers for validation
  • Priority-based execution (P1 → P2 → P3)

This structure strongly supports incremental delivery and MVP-first development.


161-194: Comprehensive dependency and parallelization guidance.

The "Dependencies & Execution Order" section provides clear, actionable guidance on:

  • Phase dependencies
  • User story dependencies
  • Within-story task ordering
  • Parallel execution opportunities

This is exactly the level of detail needed for effective task planning.

test-prompt/.specify/memory/constitution.md (1)

38-173: Comprehensive and well-structured constitution.

The development constitution provides excellent governance with:

  • Clear, measurable standards (80% test coverage, p95 200ms response times, 3s initial load)
  • Strong emphasis on TDD and independent testability
  • Specific UX and accessibility requirements
  • Versioning and amendment processes
  • Justification requirements for complexity

The rationale sections for each principle effectively communicate the "why" behind the standards. This document will serve as valuable guidance for maintaining consistent development practices.

Note: The static analysis hint flagging "200ms" as a spelling error is a false positive—this is correct technical notation for 200 milliseconds.

src/hyh/plugin/commands/help.md (2)

21-27: LGTM!

The workflow diagram clearly shows the progression through phases and the artifacts produced at each stage.


29-35: LGTM!

The worktree commands table is clear and uses consistent CLI syntax.

src/hyh/plugin/plugin.json (1)

1-14: LGTM!

The plugin manifest is well-structured with valid JSON, appropriate metadata, and correctly formatted relative paths for commands, skills, and hooks.

test-prompt/.specify/templates/checklist-template.md (1)

1-40: LGTM!

The checklist template is well-structured with clear placeholders, prominent warnings about sample items, and helpful usage notes. The template provides good guidance for generating checklists.

src/hyh/templates/spec-template.md (1)

1-115: LGTM!

The specification template is comprehensive and well-designed with excellent guidance on prioritization, independent testing, and measurable outcomes. The instructional comments and "NEEDS CLARIFICATION" pattern provide clear guidance for users.

test-prompt/.specify/scripts/bash/setup-plan.sh (3)

1-24: LGTM!

The argument parsing logic is clean and handles both JSON output mode and help display appropriately. The use of set -e ensures the script fails fast on errors.


33-48: LGTM!

The feature validation and template copying logic is sound. The fallback behavior of creating an empty plan file with a warning when the template is missing is reasonable.


50-61: LGTM!

The output formatting logic correctly handles both JSON and human-readable text modes.

src/hyh/templates/checklist-template.md (1)

1-40: LGTM!

The checklist template is well-structured and consistent with the parallel template in test-prompt. The prominent sample-item warnings and clear placeholders provide good guidance.

test-prompt/.specify/templates/tasks-template.md (3)

1-72: LGTM!

The template header and foundational phases are well-structured with clear format guidance, prominent sample-task warnings, and helpful path conventions. The distinction between Setup and Foundational phases is clear.


74-158: LGTM!

The user story phases are excellently structured with consistent format, clear independence markers, and helpful checkpoints. The emphasis on independent testing and MVP delivery at each story completion is valuable.


160-250: LGTM!

The dependencies, execution strategies, and implementation approaches are comprehensive and well-documented. The parallel team strategy and incremental delivery guidance provide excellent practical advice for different team configurations.

src/hyh/templates/plan-template.md (3)

1-28: LGTM!

The header and technical context section provide comprehensive coverage of all relevant technical details with helpful examples and a clear pattern for marking unknowns.


29-66: LGTM!

The Constitution Check section provides excellent governance with comprehensive checklists covering all five principles. The reference to complexity tracking for violations is a good practice.

Note: The static analysis warning about "p95" is a false positive—this is standard performance engineering notation for the 95th percentile.


67-134: LGTM!

The project structure section provides flexible options for different project types with clear guidance to customize and remove unused sections. The complexity tracking table provides a structured way to justify deviations from the constitution.

tests/hyh/test_plan.py (1)

380-460: LGTM! Comprehensive test coverage for Speckit parsing.

The three new test functions provide solid coverage for:

  • Checkbox parsing with all markers (status, parallel, user story, file paths)
  • Phase-based dependency inference (Phase N depends on all Phase N-1 tasks)
  • Conversion to WorkflowState with correct status mapping

The tests align well with the implementation in src/hyh/plan.py and verify the core Speckit integration functionality.

src/hyh/client.py (3)

917-953: LGTM! Worktree command handlers are well-structured.

The three worktree CLI handlers follow consistent patterns:

  • Proper type hints with -> None return types
  • Import worktree module functions at function scope
  • Clear output formatting
  • Appropriate error handling in _cmd_worktree_switch

955-1003: LGTM! Workflow status implementation handles all output modes correctly.

The function provides three well-structured output modes (JSON, quiet, human-readable) with proper type hints and consistent formatting. The use of json_module alias is a good practice to avoid naming conflicts.


864-879: Add return type hint.

The function is missing a return type annotation. Per coding guidelines, type hints are mandatory everywhere in Python code.

🔎 Proposed fix
-def _cmd_init() -> None:
+def _cmd_init() -> None:
     from hyh.init import init_project

Wait, looking again at line 864, it seems the function already has -> None in the annotated code. Let me re-check the annotated code...

Actually, I see line 864 is marked with ~ which means it's new/modified. Looking at the code:

def _cmd_init() -> None:

The return type IS present. So this is actually fine.

Actually, upon closer inspection, the return type hint -> None is already present on line 864. No issue here.

tests/hyh/test_templates.py (1)

1-47: LGTM! Template tests validate structure correctly.

The tests ensure bundled templates are accessible and contain required sections. The use of importlib.resources.files is the correct approach for accessing package resources.

tests/hyh/test_worktree.py (1)

7-184: LGTM! Comprehensive worktree management test coverage.

The tests thoroughly exercise the DHH-style worktree functionality:

  • Creating worktrees with proper naming convention
  • Listing and filtering DHH-style worktrees
  • Looking up worktrees by branch name
  • CLI integration via hyh worktree create

All tests properly initialize git repositories with user configuration and verify expected outcomes.

test-prompt/.specify/templates/plan-template.md (1)

1-134: LGTM! Comprehensive implementation plan template.

The template provides a well-structured framework for feature planning with clear sections for overview, technical context, constitution checks, project structure, and complexity tracking.

Note: The LanguageTool hint about "p95" is a false positive—this is standard performance notation for 95th percentile and not a spelling error.

tests/hyh/test_workflow.py (1)

1-91: LGTM! Workflow phase detection tests cover all states.

The tests comprehensively verify the five-state workflow progression (none → specify → plan → implement → complete):

  • Phase detection based on artifact presence
  • Task completion tracking
  • CLI integration via hyh workflow status

All tests properly set up the necessary file structures and verify expected phase transitions.

tests/hyh/test_init.py (1)

1-122: LGTM! Comprehensive initialization test coverage.

The tests thoroughly verify the hyh init functionality:

  • Plugin directory structure and file creation
  • Configuration file format and required fields
  • Template copying (all four templates)
  • Skills directory setup
  • Idempotent behavior
  • Git branch detection

All tests properly validate the initialization workflow and expected artifacts.

tests/hyh/test_integration_workflow.py (3)

9-35: LGTM: Test setup is comprehensive.

The git repository initialization with proper user config and initial commit provides a realistic test environment for the integration test.


37-49: LGTM: Init and worktree creation flow.

The lazy imports and assertions for plugin scaffolding and worktree creation are appropriate for this integration test.


51-112: LGTM: Phase transition coverage is thorough.

The test correctly validates the full workflow progression: none → specify → plan → complete, including task parsing and dependency verification.

test-prompt/.specify/scripts/bash/create-new-feature.sh (3)

1-68: LGTM: Argument parsing and validation.

The flag parsing handles edge cases well (checking for missing values after --short-name and --number). Help message is comprehensive.


136-181: LGTM: Branch name generation with stop-word filtering.

The generate_branch_name function intelligently filters stop words and short words while preserving acronyms. Good defensive programming.


216-235: LGTM: GitHub branch length enforcement.

Good attention to the 244-byte GitHub branch name limit with user-friendly warning messages.

docs/plans/2025-12-29-speckit-integration-design.md (1)

1-307: LGTM: Comprehensive design document.

The design doc thoroughly covers the architecture, command structure, workflow phases, plugin files, and design rationale. It aligns well with the implementation in the PR.

Minor note: Several code blocks lack language specifiers (flagged by markdownlint MD040), and some headings in the "Design Decisions" section lack surrounding blank lines (MD022). These are cosmetic and can be addressed later if desired.

src/hyh/workflow.py (2)

10-18: LGTM: WorkflowPhase struct follows coding guidelines.

The struct correctly uses frozen=True and forbid_unknown_fields=True as per coding guidelines. Default values are appropriate.


21-84: Consider adding the "implement" phase to align with design.

The design document describes a five-state machine: none → specify → plan → implement → complete. However, detect_phase transitions directly from "plan" to "complete" without an "implement" phase. When tasks exist but are not all complete, the phase is "plan" with next_action="implement".

This may be intentional (the "implement" state is implicit while tasks are being executed), but worth verifying alignment with the design intent.

src/hyh/init.py (2)

11-18: LGTM: InitResult struct follows coding guidelines.

Correctly uses frozen=True and forbid_unknown_fields=True.


45-124: LGTM: init_project implementation is robust.

The function properly handles directory creation with exist_ok=True, checks for file existence before copying, and gracefully handles optional assets. The use of importlib.resources.files for package resources is appropriate.

src/hyh/plan.py (3)

10-14: LGTM: Regex patterns use Final type hint.

Patterns are correctly marked as Final per coding guidelines.


35-65: LGTM: SpecTaskDefinition and SpecTaskList follow coding guidelines.

Both structs correctly use frozen=True, forbid_unknown_fields=True, and tuples for immutable collections (dependencies, phases). The to_workflow_state conversion properly maps to the existing Task and WorkflowState types.


278-348: LGTM: parse_speckit_tasks implementation is correct.

The parsing logic correctly:

  • Extracts phase names and task definitions from checkbox format
  • Handles parallel markers [P] and user story references [US*]
  • Builds phase-based dependencies (Phase N depends on all tasks in Phase N-1)
  • Creates new immutable SpecTaskDefinition instances when adding dependencies

The pattern matching and dependency wiring align with the design spec.

test-prompt/.specify/scripts/bash/common.sh (3)

1-13: LGTM: get_repo_root with git fallback.

Good defensive implementation that falls back to script directory traversal when git is unavailable.


15-58: LGTM: get_current_branch priority chain.

The function correctly prioritizes: SPECIFY_FEATURE env var → git branch → latest feature directory → "main" fallback. This supports both git and non-git workflows.


86-125: LGTM: Prefix-based feature directory lookup.

The find_feature_dir_by_prefix function correctly handles the multi-branch-per-spec scenario with appropriate error messaging for multiple matches.

src/hyh/worktree.py (2)

13-18: LGTM: WorktreeResult struct follows coding guidelines.

Correctly uses frozen=True and forbid_unknown_fields=True.


101-115: LGTM: get_worktree implementation.

Simple and correct lookup by branch name.

test-prompt/.specify/scripts/bash/update-agent-context.sh (2)

41-45: Good use of strict mode settings.

The script enables set -e, set -u, and set -o pipefail, which are best practices for robust error handling in Bash scripts.


105-114: Well-implemented cleanup trap.

The cleanup function properly captures exit code before cleanup, removes temp files using PID suffix for uniqueness, and re-exits with original code. The trap covers EXIT, INT, and TERM signals appropriately.

docs/plans/2025-12-29-speckit-implementation.md (2)

1-12: Well-structured implementation plan.

The document follows a clear TDD approach with:

  • Explicit test-first steps for each task
  • Clear file mappings
  • Incremental commits
  • Comprehensive integration test at the end

This provides good guidance for implementing the Speckit integration.


1852-1868: Helpful summary table.

The summary provides a quick reference for all 12 tasks with their affected files, making it easy to track implementation progress.

Comment on lines +1093 to +1097
workflow_sub.add_parser("status", help="Show current workflow phase")
workflow_status = workflow_sub.add_parser("status", help="Show current workflow phase")
workflow_status.add_argument("--json", action="store_true", help="Output JSON")
workflow_status.add_argument("--quiet", action="store_true", help="Minimal output")
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Duplicate parser registration in example code.

The example adds workflow_status parser twice at lines 1093-1094 and 1094-1096, which would cause a runtime error.

🔎 Proposed fix
 workflow_sub = workflow_parser.add_subparsers(dest="workflow_command", required=True)
 
-workflow_sub.add_parser("status", help="Show current workflow phase")
 workflow_status = workflow_sub.add_parser("status", help="Show current workflow phase")
 workflow_status.add_argument("--json", action="store_true", help="Output JSON")
 workflow_status.add_argument("--quiet", action="store_true", help="Minimal output")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
workflow_sub.add_parser("status", help="Show current workflow phase")
workflow_status = workflow_sub.add_parser("status", help="Show current workflow phase")
workflow_status.add_argument("--json", action="store_true", help="Output JSON")
workflow_status.add_argument("--quiet", action="store_true", help="Minimal output")
```
workflow_status = workflow_sub.add_parser("status", help="Show current workflow phase")
workflow_status.add_argument("--json", action="store_true", help="Output JSON")
workflow_status.add_argument("--quiet", action="store_true", help="Minimal output")
🤖 Prompt for AI Agents
In docs/plans/2025-12-29-speckit-implementation.md around lines 1093 to 1097,
the example registers the "status" parser twice which will raise a runtime
error; remove the duplicate registration by deleting the standalone
workflow_sub.add_parser("status", help="Show current workflow phase") line (or
replace it with assigning to workflow_status only once) and ensure the
subsequent workflow_status.add_argument calls operate on that single parser
instance.

Comment on lines +9 to +19
1. Run: `hyh workflow status`
2. Show this help:

## Commands

| Command | Description |
|---------|-------------|
| `/hyh specify <idea>` | Start new feature - creates worktree, generates spec |
| `/hyh plan` | Generate design artifacts and tasks from spec |
| `/hyh implement` | Execute tasks with daemon coordination |
| `/hyh status` | Show current workflow phase and progress |
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify the distinction between CLI and plugin commands.

The documentation mixes two command interfaces without explaining the difference:

  • Line 9 instructs users to run hyh workflow status (CLI command)
  • Line 19 documents /hyh status (plugin command)

Users may be confused about when to use hyh workflow status versus /hyh status, and whether they provide the same functionality.

Consider adding a brief explanation distinguishing:

  • Plugin commands (prefix /hyh) - used within Claude Code
  • CLI commands (hyh) - used in terminal
🔎 Suggested clarification
 # hyh Help
 
-Display available commands and current state:
+## Command Types
 
-1. Run: `hyh workflow status`
-2. Show this help:
+**Plugin Commands** (within Claude Code): Commands prefixed with `/hyh`
+**CLI Commands** (terminal): Commands using `hyh` directly
+
+Display current workflow state:
+- In terminal: `hyh workflow status`
+- In Claude Code: `/hyh status`

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/hyh/plugin/commands/help.md around lines 9 to 19, the doc mixes CLI and
plugin commands without clarification (line 9 shows `hyh workflow status` while
line 19 shows `/hyh status`), so add a short clarifying sentence or two before
the Commands section that: briefly defines plugin commands (start with `/hyh`,
used inside Claude Code or the chat/plugin environment) versus CLI commands
(start with `hyh`, used in a terminal), and state whether the two commands are
equivalent or what differences exist (e.g., scope, required environment, or
feature parity). Update the text near those lines to explicitly label examples
as “CLI” or “Plugin” and, if they provide the same functionality, note that one
is the chat/plugin alias of the other.

Comment on lines +55 to +98
def list_worktrees(main_repo: Path) -> list[WorktreeResult]:
"""List all DHH-style worktrees for a repository.

Args:
main_repo: Path to the main repository.

Returns:
List of WorktreeResult for each worktree.
"""
main_repo = Path(main_repo).resolve()
repo_name = main_repo.name
prefix = f"{repo_name}--"

result = subprocess.run(
["git", "worktree", "list", "--porcelain"],
cwd=main_repo,
capture_output=True,
text=True,
check=True,
)

worktrees: list[WorktreeResult] = []
current_path: Path | None = None
current_branch: str | None = None

for line in result.stdout.split("\n"):
if line.startswith("worktree "):
current_path = Path(line.split(" ", 1)[1])
elif line.startswith("branch refs/heads/"):
current_branch = line.replace("branch refs/heads/", "")
elif line == "" and current_path and current_branch:
# Filter to DHH-style worktrees only
if current_path.name.startswith(prefix):
worktrees.append(
WorktreeResult(
worktree_path=current_path,
branch_name=current_branch,
main_repo=main_repo,
)
)
current_path = None
current_branch = None

return worktrees
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Last worktree may be missed if output doesn't end with empty line.

The parsing loop only appends a worktree when it encounters an empty line (elif line == ""). If git's porcelain output doesn't end with a trailing newline/empty line, the final worktree entry won't be captured.

🔎 Proposed fix - handle final entry after loop
     for line in result.stdout.split("\n"):
         if line.startswith("worktree "):
             current_path = Path(line.split(" ", 1)[1])
         elif line.startswith("branch refs/heads/"):
             current_branch = line.replace("branch refs/heads/", "")
         elif line == "" and current_path and current_branch:
             # Filter to DHH-style worktrees only
             if current_path.name.startswith(prefix):
                 worktrees.append(
                     WorktreeResult(
                         worktree_path=current_path,
                         branch_name=current_branch,
                         main_repo=main_repo,
                     )
                 )
             current_path = None
             current_branch = None

+    # Handle final entry if output doesn't end with empty line
+    if current_path and current_branch and current_path.name.startswith(prefix):
+        worktrees.append(
+            WorktreeResult(
+                worktree_path=current_path,
+                branch_name=current_branch,
+                main_repo=main_repo,
+            )
+        )
+
     return worktrees
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def list_worktrees(main_repo: Path) -> list[WorktreeResult]:
"""List all DHH-style worktrees for a repository.
Args:
main_repo: Path to the main repository.
Returns:
List of WorktreeResult for each worktree.
"""
main_repo = Path(main_repo).resolve()
repo_name = main_repo.name
prefix = f"{repo_name}--"
result = subprocess.run(
["git", "worktree", "list", "--porcelain"],
cwd=main_repo,
capture_output=True,
text=True,
check=True,
)
worktrees: list[WorktreeResult] = []
current_path: Path | None = None
current_branch: str | None = None
for line in result.stdout.split("\n"):
if line.startswith("worktree "):
current_path = Path(line.split(" ", 1)[1])
elif line.startswith("branch refs/heads/"):
current_branch = line.replace("branch refs/heads/", "")
elif line == "" and current_path and current_branch:
# Filter to DHH-style worktrees only
if current_path.name.startswith(prefix):
worktrees.append(
WorktreeResult(
worktree_path=current_path,
branch_name=current_branch,
main_repo=main_repo,
)
)
current_path = None
current_branch = None
return worktrees
def list_worktrees(main_repo: Path) -> list[WorktreeResult]:
"""List all DHH-style worktrees for a repository.
Args:
main_repo: Path to the main repository.
Returns:
List of WorktreeResult for each worktree.
"""
main_repo = Path(main_repo).resolve()
repo_name = main_repo.name
prefix = f"{repo_name}--"
result = subprocess.run(
["git", "worktree", "list", "--porcelain"],
cwd=main_repo,
capture_output=True,
text=True,
check=True,
)
worktrees: list[WorktreeResult] = []
current_path: Path | None = None
current_branch: str | None = None
for line in result.stdout.split("\n"):
if line.startswith("worktree "):
current_path = Path(line.split(" ", 1)[1])
elif line.startswith("branch refs/heads/"):
current_branch = line.replace("branch refs/heads/", "")
elif line == "" and current_path and current_branch:
# Filter to DHH-style worktrees only
if current_path.name.startswith(prefix):
worktrees.append(
WorktreeResult(
worktree_path=current_path,
branch_name=current_branch,
main_repo=main_repo,
)
)
current_path = None
current_branch = None
# Handle final entry if output doesn't end with empty line
if current_path and current_branch and current_path.name.startswith(prefix):
worktrees.append(
WorktreeResult(
worktree_path=current_path,
branch_name=current_branch,
main_repo=main_repo,
)
)
return worktrees
🤖 Prompt for AI Agents
In src/hyh/worktree.py around lines 55 to 98, the parser only appends a
WorktreeResult when it sees a blank line, so the final worktree is dropped if
git output doesn't end with an empty line; after the for-loop, add a final check
that if current_path and current_branch are set (and current_path.name
startswith the prefix) then append the WorktreeResult (same construction as
inside the loop) before returning worktrees.

Comment on lines +253 to +259
if $JSON_MODE; then
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
else
echo "BRANCH_NAME: $BRANCH_NAME"
echo "SPEC_FILE: $SPEC_FILE"
echo "FEATURE_NUM: $FEATURE_NUM"
echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Environment variable export won't persist to parent shell.

export SPECIFY_FEATURE="$BRANCH_NAME" only affects the current script's process and child processes, not the calling shell. The message on line 259 may mislead users into thinking the variable is available after the script exits.

🔎 Proposed fix
-# Set the SPECIFY_FEATURE environment variable for the current session
-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"
 else
     echo "BRANCH_NAME: $BRANCH_NAME"
     echo "SPEC_FILE: $SPEC_FILE"
     echo "FEATURE_NUM: $FEATURE_NUM"
-    echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
+    echo "To set SPECIFY_FEATURE in your shell, run: export SPECIFY_FEATURE='$BRANCH_NAME'"
 fi

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In test-prompt/.specify/scripts/bash/create-new-feature.sh around lines 253 to
259, the script exports SPECIFY_FEATURE but that export only affects the
script/process and children — the calling shell won't see it; update the script
to either detect if it's being sourced and perform the export only in that case
(and print a warning+usage if not sourced), or stop exporting and instead print
a clear instruction for the user to run: `source <script>` (or print the exact
`export SPECIFY_FEATURE="..."` line so the caller can eval it). Also update the
echo message on line 259 to explicitly state that the variable will not persist
unless the script is sourced or the export line is evaluated in the caller
shell.

Comment on lines +26 to +31
# Get script directory and load common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get all paths and variables from common functions
eval $(get_feature_paths)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Quote the command substitution to prevent word splitting.

The unquoted command substitution on line 31 can cause issues if any paths returned by get_feature_paths contain spaces or special characters.

🔎 Proposed fix
 # Get all paths and variables from common functions
-eval $(get_feature_paths)
+eval "$(get_feature_paths)"
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 31-31: Quote this to prevent word splitting.

(SC2046)

🤖 Prompt for AI Agents
In test-prompt/.specify/scripts/bash/setup-plan.sh around lines 26 to 31, the
command substitution used with eval is unquoted (eval $(get_feature_paths)),
which can cause word splitting or globbing if returned paths contain spaces or
special characters; change it to quote the substitution so it becomes eval
"$(get_feature_paths)" to preserve spacing and prevent unwanted
splitting/globbing.

source "$SCRIPT_DIR/common.sh"

# Get all paths and variables from common functions
eval $(get_feature_paths)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Quote command substitution to prevent word splitting.

The output of get_feature_paths is evaluated without quoting, which can cause issues if any paths contain spaces or special characters.

🔎 Proposed fix
-eval $(get_feature_paths)
+eval "$(get_feature_paths)"

Based on shellcheck SC2046.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
eval $(get_feature_paths)
eval "$(get_feature_paths)"
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 56-56: Quote this to prevent word splitting.

(SC2046)

🤖 Prompt for AI Agents
In test-prompt/.specify/scripts/bash/update-agent-context.sh around line 56, the
command substitution passed to eval is unquoted which allows word-splitting and
globbing on paths containing spaces or special characters; change it to quote
the substitution (e.g. use eval "$(get_feature_paths)") so the output is treated
as a single string, or refactor get_feature_paths to output shell-safe lines and
read them with read -r or an array and avoid unquoted eval entirely.

Comment on lines +67 to +74
AGENTS_FILE="$REPO_ROOT/AGENTS.md"
WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md"
AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md"
ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"
CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md"
AMP_FILE="$REPO_ROOT/AGENTS.md"
Q_FILE="$REPO_ROOT/AGENTS.md"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Multiple agent types share the same file path.

AGENTS_FILE, AMP_FILE, and Q_FILE all point to $REPO_ROOT/AGENTS.md. When update_all_existing_agents runs, if AGENTS_FILE exists, it will be updated once (line 661-664). However, lines 691-694 check Q_FILE (same path) again and would attempt another update on the same file.

This creates potential for:

  1. Redundant file operations
  2. Confusing log messages showing multiple updates to the same file
🔎 Suggested approach

Consider deduplicating the file paths in update_all_existing_agents or tracking which files have already been updated:

update_all_existing_agents() {
    local found_agent=false
    local -A updated_files=()  # Track already-updated files
    
    # Example for AGENTS_FILE
    if [[ -f "$AGENTS_FILE" ]] && [[ -z "${updated_files[$AGENTS_FILE]:-}" ]]; then
        update_agent_file "$AGENTS_FILE" "Codex/opencode"
        updated_files[$AGENTS_FILE]=1
        found_agent=true
    fi
    # ... similar for other files
}
🤖 Prompt for AI Agents
In test-prompt/.specify/scripts/bash/update-agent-context.sh around lines 67 to
74, multiple constants (AGENTS_FILE, AMP_FILE, Q_FILE) point to the same path
($REPO_ROOT/AGENTS.md) which causes duplicate update attempts later; modify the
script by either deduplicating these constants so each agent type has a unique
target path or, preferably, change update_all_existing_agents to track
already-updated file paths (e.g., use an associative array or list) and skip
updating/logging the same file more than once; ensure the check before calling
update_agent_file verifies the file hasn’t been processed yet and adjust log
messages to reflect a single update per path.


**Reason for this priority**: [Explain the value and why it has this priority level]

**Independent testing**: \[Explain how this can be tested independently - e.g., "Can be fully tested by [specific action] and provides [specific value]"\]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Check for unintended escaped brackets.

Line 29 contains \[Explain how this can be tested independently...]\ with backslash-escaped brackets. This appears to be a formatting inconsistency, as other similar placeholder text uses plain brackets.

Verify whether the escaping is intentional (e.g., for literal rendering) or an error:

#!/bin/bash
# Search for escaped bracket patterns in template files
rg -n '\\[' test-prompt/.specify/templates/
🤖 Prompt for AI Agents
In test-prompt/.specify/templates/spec-template.md around line 29, the
placeholder uses escaped brackets `\[ ... \]` but other placeholders use plain
brackets; remove the backslashes so the line reads with standard brackets (i.e.,
replace `\[` and `\]` with `[` and `]`) to make formatting consistent, then run
a project search for occurrences of escaped brackets and fix any other
accidental escapes or, if the escape was intentional for literal rendering,
document that intent and make escaping consistent across templates.

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.

2 participants