Fix code review issues from PR #30#31
Conversation
Install spec-kit commands, scripts, and templates from github/spec-kit. Add spec-kit-auto skill that autonomously chains /speckit.specify, /speckit.plan, /speckit.tasks, /speckit.analyze, and /speckit.implement with inline lint/security/finish phases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix broken path reference in speckit.constitution.md (.specify/templates/commands/*.md → .claude/commands/speckit.*.md) - Regenerate .repomap.txt to reflect new files - Add .worktrees/ to .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WalkthroughThis pull request introduces a comprehensive specification-driven development framework called "speckit" comprising Claude command definitions, Bash utility scripts, Markdown templates, a skill orchestration definition, plugin configuration, and initialization options for automated feature specification, planning, task generation, implementation, and quality analysis workflows. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 18
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude/commands/speckit.clarify.md:
- Line 25: Update the documentation line that invokes the script to remove the
unsupported aliases `-Json` and `-PathsOnly` and only reference the real CLI
flags `--json` and `--paths-only` (lowercase, dashed); specifically change the
example invocation of check-prerequisites.sh (the string containing
`.specify/scripts/bash/check-prerequisites.sh --json --paths-only`) so it no
longer lists `-Json -PathsOnly`, and ensure surrounding text/references mention
the exact supported flags only.
In @.claude/commands/speckit.implement.md:
- Around line 25-44: The markdown fences in the Extension Hooks examples are
missing blank lines around the triple-backticks and lack a fence language,
causing MD031/MD040 failures; update each fenced code block around the "##
Extension Hooks" examples (the optional pre-hook and mandatory hook blocks
shown) to add a blank line before and after each ``` fence and add a fence
language (use "text") so each block starts with ```text and ends with ``` with a
blank line following the closing fence.
- Line 171: Update the ordered list item at Line 171 in
.claude/commands/speckit.implement.md so it restarts numbering instead of using
"10."; replace the "10." prefix on the line that begins "10. **Check for
extension hooks**: After completion validation, check if
`.specify/extensions.yml` exists in the project root." with "1." (or the
appropriate restart marker) to comply with MD029 ordered-list style.
In @.claude/commands/speckit.plan.md:
- Around line 61-71: The document references Phase 0 and Phase 1 but instructs
to "stop after Phase 2 planning," creating an ambiguous termination point;
update the IMPL_PLAN steps so the phase boundary is consistent by either (A)
changing the stop instruction to "stop after Phase 1 planning" to match the
listed phases, or (B) adding a clear Phase 2 definition and steps into the
numbered workflow (including how it affects Technical Context, Constitution
Check, gates, and artifacts) so that IMPL_PLAN, Phase 0, Phase 1, and Phase 2
are all explicitly defined and consistent.
In @.claude/commands/speckit.specify.md:
- Around line 81-82: The PowerShell examples call the Bash script
`.specify/scripts/bash/create-new-feature.sh` with incorrect PascalCase short
flags (`-Json`, `-ShortName`, `-Timestamp`) which will be treated as positional
args; update the examples to use the script's lowercase kebab-case flags
(`--json`, `--short-name`, `--timestamp`) so the options are parsed correctly,
or alternatively add a PowerShell wrapper that maps
`-Json`/`-ShortName`/`-Timestamp` to `--json`/`--short-name`/`--timestamp`
before invoking `create-new-feature.sh`.
- Around line 79-80: The Bash examples for
`.specify/scripts/bash/create-new-feature.sh` currently pass the feature
description twice (via "$ARGUMENTS" and the literal "Add user authentication");
update both examples (the plain and the timestamp variant) to provide the
description only once by removing the duplicated literal description so the
script receives either "$ARGUMENTS" or the quoted description but not both;
ensure the examples still include the flags `--json`/`--timestamp` and
`--short-name "user-auth"` and verify that `$ARGUMENTS` remains in the example
if you want to demonstrate passing arguments via the variable.
In @.claude/skills/spec-kit-auto/SKILL.md:
- Line 79: Change the lowercase platform name "GitHub" in prose to the proper
capitalized form while leaving filesystem path fragments like
".github/workflows/*.yml" unchanged; specifically update the descriptive text
around the table row containing `.github/workflows/*.yml | actionlint |
actionlint` and the other occurrence near the later mention (the text at the
location referenced as 115-115) to use "GitHub" instead of "Github" or "github".
In @.repomap.txt:
- Around line 15-63: The repomap generator is mis-parsing Bash function names in
.specify/scripts/bash/update-agent-context.sh (e.g., producing g_info(),
g_success(), error(), warning(), nup(), date_environment(), act_plan_field(),
e_plan_data(), at_technology_stack(), project_structure(),
commands_for_language(), language_conventions(), te_new_agent_file(),
te_existing_agent_file(), te_agent_file(), te_specific_agent(), if_new(),
ll_existing_agents(), mmary()); update the parser so it correctly recognizes
Bash function declaration patterns (handles "name()", "name ()", "function
name()", and multiline/header comments) and map the parsed identifiers to the
real function names (log_info, log_success, log_error, log_warning, cleanup,
validate_environment, extract_plan_field, parse_plan_data,
format_technology_stack, get_project_structure, get_commands_for_language,
get_language_conventions, create_new_agent_file, update_existing_agent_file,
update_agent_file, update_specific_agent, _update_if_new,
update_all_existing_agents, print_summary) then regenerate .repomap.txt (or
replace the parsing step with a robust shell AST/tokenizer) so entries are not
corrupted.
In @.specify/init-options.json:
- Line 5: The branch_numbering setting in .specify/init-options.json is unused
by the create-new-feature.sh flow; update the create-new-feature.sh script to
read the "branch_numbering" value (e.g., export or set a BRANCH_NUMBERING
variable) at startup and use it to control branch naming unless an explicit
--timestamp flag is provided, so the script's branch name generation logic (the
code handling --timestamp and sequential/timestamp decision) honors
branch_numbering by default; ensure precedence: CLI --timestamp overrides
config, otherwise use branch_numbering ("sequential" vs "timestamp") to pick the
naming strategy.
In @.specify/scripts/bash/common.sh:
- Line 57: The current line "local repo_root=$(get_repo_root)" masks any
non-zero return from get_repo_root (SC2155); fix by declaring the variable and
assigning in two steps: first declare local repo_root, then assign repo_root by
calling get_repo_root (use command substitution with quotes, e.g.,
repo_root="$(get_repo_root)") so failures are not masked; update the code around
the local repo_root usage to use the newly assigned variable.
- Around line 44-45: The combined declaration and command-substitution masks
subshell failures; split declaration and assignment so failures from the
subshell propagate: first declare local script_dir, then perform the command
substitution/ subshell to compute the path and assign to script_dir (e.g., run
the cd/pwd subshell in a separate statement and set script_dir from its output),
ensuring any non-zero exit from the subshell is not masked; update references to
the variable name script_dir accordingly.
In @.specify/scripts/bash/create-new-feature.sh:
- Around line 31-43: The --number parsing branch currently sets BRANCH_NUMBER
without validation which later causes a cryptic failure at the arithmetic
expansion $((10#$BRANCH_NUMBER)); update the --number case (the --number) to
validate next_arg before assigning it to BRANCH_NUMBER: ensure it matches a
non-negative integer regex (e.g., ^[0-9]+$), reject empty/negative/alpha values
with a clear error message and exit non-zero, and only then assign
BRANCH_NUMBER; additionally ensure any later use of $((10#$BRANCH_NUMBER)) can
rely on this validation (no further change required if validation passes).
In @.specify/scripts/bash/setup-plan.sh:
- Around line 41-50: The current setup script unconditionally copies the
resolved TEMPLATE into IMPL_PLAN which will overwrite any existing user plan;
update the logic in the block that uses resolve_template and TEMPLATE to first
check if IMPL_PLAN already exists and is non-empty (e.g., test -e or -s on
IMPL_PLAN) and only perform cp "$TEMPLATE" "$IMPL_PLAN" when the plan file does
not exist or is empty; if IMPL_PLAN exists, skip copying and log a message
instead so user content is preserved.
- Around line 7-24: The ARGS array is populated in the argument-parsing loop but
never used; remove the unused ARGS variable and the ARGS+=("$arg") branch from
the case in setup-plan.sh (or alternatively, if non-option arguments are
intended to be handled, implement consuming/using ARGS after parsing). Update
the loop to only handle --json and --help (and default to reporting/ignoring
unexpected args) and remove the ARGS declaration to eliminate the
unused-variable warning; reference the ARGS variable and the argument-parsing
case block around the for arg in "$@" loop and JSON_MODE handling when making
the change.
In @.specify/scripts/bash/update-agent-context.sh:
- Around line 196-199: The create-path branch in
parse_plan_data/extract_plan_field sets NEW_DB but never adds it to the new
context's tech_stack or recent_change, so include NEW_DB (the Storage value
returned by extract_plan_field) when assembling the tech_stack array and append
it to recent_change in the "create" flow just as the update flow does; mirror
the same logic you use for NEW_LANG/NEW_FRAMEWORK (the variables set by
extract_plan_field) when building the initial context and apply the same fix to
the analogous create branch around the other occurrence mentioned (the block
similar to lines 323-343).
- Around line 465-483: The Recent Changes block is not idempotent because the
script always echoes new_change_entry, causing duplicates; fix by detecting
whether new_change_entry already exists in that section before adding it: when
you enter the "## Recent Changes" branch (use the in_changes_section variable
and the new_change_entry variable), scan the following lines (until the next "##
" heading) for a line equal to new_change_entry and set a flag like
new_change_present; only echo new_change_entry into the temp_file if
new_change_present is false, and ensure existing_changes_count logic still
copies at most two unique bullets (skip lines equal to new_change_entry while
counting) so reruns won't prepend a duplicate.
- Around line 318-320: The sed replacement values are not properly escaped for
replacement text (specials like &, | and \), so add a small helper (e.g.
escape_sed_replacement) that escapes backslashes, ampersands and your chosen sed
delimiter (|) and then use it to produce escaped versions of NEW_LANG,
NEW_FRAMEWORK, CURRENT_BRANCH and also the other replacement values used in the
substitutions array (project_name, current_date, project_structure, commands,
language_conventions); replace the current printf/sed regex-escape usage with
calls to this helper and use the escaped_* variables when building the
substitutions array and invoking sed.
In @.specify/templates/plan-template.md:
- Line 6: Update the misleading self-reference in the note: change the execution
workflow link text in .specify/templates/plan-template.md so it no longer points
to the same template but instead references the command workflow document (e.g.,
.claude/commands/speckit.plan.md) and the /speckit.plan command; edit the
sentence beginning "**Note**: This template is filled in by the `/speckit.plan`
command. See `.specify/templates/plan-template.md` for the execution workflow."
to point to the proper workflow doc (.claude/commands/speckit.plan.md) and
ensure the phrasing clearly ties the template to the `/speckit.plan` command.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6ec57547-23d6-47ca-acbe-e9a02e15f66a
📒 Files selected for processing (26)
.claude-plugin/plugin.json.claude/commands/speckit.analyze.md.claude/commands/speckit.checklist.md.claude/commands/speckit.clarify.md.claude/commands/speckit.constitution.md.claude/commands/speckit.implement.md.claude/commands/speckit.plan.md.claude/commands/speckit.specify.md.claude/commands/speckit.tasks.md.claude/commands/speckit.taskstoissues.md.claude/skills/spec-kit-auto/SKILL.md.gitignore.repomap.txt.specify/init-options.json.specify/memory/constitution.md.specify/scripts/bash/check-prerequisites.sh.specify/scripts/bash/common.sh.specify/scripts/bash/create-new-feature.sh.specify/scripts/bash/setup-plan.sh.specify/scripts/bash/update-agent-context.sh.specify/templates/agent-file-template.md.specify/templates/checklist-template.md.specify/templates/constitution-template.md.specify/templates/plan-template.md.specify/templates/spec-template.md.specify/templates/tasks-template.md
|
|
||
| Execution steps: | ||
|
|
||
| 1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields: |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm supported options in the prerequisites script.
rg -n -C2 -- '--json|--paths-only|-Json|-PathsOnly' .specify/scripts/bash/check-prerequisites.shRepository: ambient-code/reference
Length of output: 1341
Remove unsupported -Json -PathsOnly aliases.
Line 25 references flag aliases that are not supported by check-prerequisites.sh. The script documentation and argument parsing only support --json and --paths-only (lowercase with dashes). Including the unsupported aliases creates confusion and contradicts the actual CLI interface.
Proposed fix
-1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields:
+1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode). Parse minimal JSON payload fields:📝 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.
| 1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields: | |
| 1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode). Parse minimal JSON payload fields: |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/commands/speckit.clarify.md at line 25, Update the documentation
line that invokes the script to remove the unsupported aliases `-Json` and
`-PathsOnly` and only reference the real CLI flags `--json` and `--paths-only`
(lowercase, dashed); specifically change the example invocation of
check-prerequisites.sh (the string containing
`.specify/scripts/bash/check-prerequisites.sh --json --paths-only`) so it no
longer lists `-Json -PathsOnly`, and ensure surrounding text/references mention
the exact supported flags only.
| ``` | ||
| ## Extension Hooks | ||
|
|
||
| **Optional Pre-Hook**: {extension} | ||
| Command: `/{command}` | ||
| Description: {description} | ||
|
|
||
| Prompt: {prompt} | ||
| To execute: `/{command}` | ||
| ``` | ||
| - **Mandatory hook** (`optional: false`): | ||
| ``` | ||
| ## Extension Hooks | ||
|
|
||
| **Automatic Pre-Hook**: {extension} | ||
| Executing: `/{command}` | ||
| EXECUTE_COMMAND: {command} | ||
|
|
||
| Wait for the result of the hook command before proceeding to the Outline. | ||
| ``` |
There was a problem hiding this comment.
Fix fenced code block formatting to unblock markdownlint.
Lines in these ranges are failing MD031/MD040 (missing blank lines around fences and missing fence language), which is currently breaking the documentation validation pipeline.
Proposed lint-compliant fence format
- ```
+
+ ```text
## Extension Hooks
@@
- ```
+ ```
+
@@
- ```
+
+ ```text
## Extension Hooks
@@
- ```
+ ```
+
@@
- ```
+
+ ```text
## Extension Hooks
@@
- ```
+ ```
+
@@
- ```
+
+ ```text
## Extension Hooks
@@
- ```
+ ```
+ Also applies to: 180-197
🧰 Tools
🪛 GitHub Actions: Documentation Validation
[error] 25-25: markdownlint-cli2 (markdownlint v0.33.0): MD031/blanks-around-fences — Fenced code blocks should be surrounded by blank lines [Context: "```"]
🪛 GitHub Check: lint-markdown
[failure] 44-44: Fenced code blocks should be surrounded by blank lines
.claude/commands/speckit.implement.md:44 MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md
[failure] 36-36: Fenced code blocks should have a language specified
.claude/commands/speckit.implement.md:36 MD040/fenced-code-language Fenced code blocks should have a language specified [Context: " ```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md040.md
[failure] 36-36: Fenced code blocks should be surrounded by blank lines
.claude/commands/speckit.implement.md:36 MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md
[failure] 34-34: Fenced code blocks should be surrounded by blank lines
.claude/commands/speckit.implement.md:34 MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md
[failure] 25-25: Fenced code blocks should have a language specified
.claude/commands/speckit.implement.md:25 MD040/fenced-code-language Fenced code blocks should have a language specified [Context: " ```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md040.md
[failure] 25-25: Fenced code blocks should be surrounded by blank lines
.claude/commands/speckit.implement.md:25 MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/commands/speckit.implement.md around lines 25 - 44, The markdown
fences in the Extension Hooks examples are missing blank lines around the
triple-backticks and lack a fence language, causing MD031/MD040 failures; update
each fenced code block around the "## Extension Hooks" examples (the optional
pre-hook and mandatory hook blocks shown) to add a blank line before and after
each ``` fence and add a fence language (use "text") so each block starts with
```text and ends with ``` with a blank line following the closing fence.
|
|
||
| Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/speckit.tasks` first to regenerate the task list. | ||
|
|
||
| 10. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root. |
There was a problem hiding this comment.
Restart ordered-list numbering at Line 171.
Line 171 uses 10. as a new list start, which violates the configured ordered-list style (MD029) and fails lint.
Proposed fix
-10. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root.
+1. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root.📝 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.
| 10. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root. | |
| 1. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root. |
🧰 Tools
🪛 GitHub Check: lint-markdown
[failure] 171-171: Ordered list item prefix
.claude/commands/speckit.implement.md:171:1 MD029/ol-prefix Ordered list item prefix [Expected: 1; Actual: 10; Style: 1/1/1] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md029.md
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/commands/speckit.implement.md at line 171, Update the ordered list
item at Line 171 in .claude/commands/speckit.implement.md so it restarts
numbering instead of using "10."; replace the "10." prefix on the line that
begins "10. **Check for extension hooks**: After completion validation, check if
`.specify/extensions.yml` exists in the project root." with "1." (or the
appropriate restart marker) to comply with MD029 ordered-list style.
| 3. **Execute plan workflow**: Follow the structure in IMPL_PLAN template to: | ||
| - Fill Technical Context (mark unknowns as "NEEDS CLARIFICATION") | ||
| - Fill Constitution Check section from constitution | ||
| - Evaluate gates (ERROR if violations unjustified) | ||
| - Phase 0: Generate research.md (resolve all NEEDS CLARIFICATION) | ||
| - Phase 1: Generate data-model.md, contracts/, quickstart.md | ||
| - Phase 1: Update agent context by running the agent script | ||
| - Re-evaluate Constitution Check post-design | ||
|
|
||
| 4. **Stop and report**: Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generated artifacts. | ||
|
|
There was a problem hiding this comment.
Clarify phase boundary to prevent ambiguous termination.
Line 70 says to stop after “Phase 2 planning,” but the outlined workflow defines Phase 0 and Phase 1 only. This creates conflicting execution guidance.
Proposed doc fix
-4. **Stop and report**: Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generated artifacts.
+4. **Stop and report**: Command ends after Phase 1 design planning artifacts are produced. Report branch, IMPL_PLAN path, and generated artifacts.📝 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.
| 3. **Execute plan workflow**: Follow the structure in IMPL_PLAN template to: | |
| - Fill Technical Context (mark unknowns as "NEEDS CLARIFICATION") | |
| - Fill Constitution Check section from constitution | |
| - Evaluate gates (ERROR if violations unjustified) | |
| - Phase 0: Generate research.md (resolve all NEEDS CLARIFICATION) | |
| - Phase 1: Generate data-model.md, contracts/, quickstart.md | |
| - Phase 1: Update agent context by running the agent script | |
| - Re-evaluate Constitution Check post-design | |
| 4. **Stop and report**: Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generated artifacts. | |
| 3. **Execute plan workflow**: Follow the structure in IMPL_PLAN template to: | |
| - Fill Technical Context (mark unknowns as "NEEDS CLARIFICATION") | |
| - Fill Constitution Check section from constitution | |
| - Evaluate gates (ERROR if violations unjustified) | |
| - Phase 0: Generate research.md (resolve all NEEDS CLARIFICATION) | |
| - Phase 1: Generate data-model.md, contracts/, quickstart.md | |
| - Phase 1: Update agent context by running the agent script | |
| - Re-evaluate Constitution Check post-design | |
| 4. **Stop and report**: Command ends after Phase 1 design planning artifacts are produced. Report branch, IMPL_PLAN path, and generated artifacts. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/commands/speckit.plan.md around lines 61 - 71, The document
references Phase 0 and Phase 1 but instructs to "stop after Phase 2 planning,"
creating an ambiguous termination point; update the IMPL_PLAN steps so the phase
boundary is consistent by either (A) changing the stop instruction to "stop
after Phase 1 planning" to match the listed phases, or (B) adding a clear Phase
2 definition and steps into the numbered workflow (including how it affects
Technical Context, Constitution Check, gates, and artifacts) so that IMPL_PLAN,
Phase 0, Phase 1, and Phase 2 are all explicitly defined and consistent.
| - Bash example: `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --short-name "user-auth" "Add user authentication"` | ||
| - Bash (timestamp): `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --timestamp --short-name "user-auth" "Add user authentication"` |
There was a problem hiding this comment.
Pass the feature description only once in the Bash examples.
create-new-feature.sh concatenates every non-option argument into the description, so keeping both $ARGUMENTS and "Add user authentication" here duplicates the feature text and can change the generated branch/spec names.
Suggested fix
- - Bash example: `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --short-name "user-auth" "Add user authentication"`
- - Bash (timestamp): `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --timestamp --short-name "user-auth" "Add user authentication"`
+ - Bash example: `.specify/scripts/bash/create-new-feature.sh --json --short-name "user-auth" "$ARGUMENTS"`
+ - Bash (timestamp): `.specify/scripts/bash/create-new-feature.sh --json --timestamp --short-name "user-auth" "$ARGUMENTS"`📝 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.
| - Bash example: `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --short-name "user-auth" "Add user authentication"` | |
| - Bash (timestamp): `.specify/scripts/bash/create-new-feature.sh "$ARGUMENTS" --json --timestamp --short-name "user-auth" "Add user authentication"` | |
| - Bash example: `.specify/scripts/bash/create-new-feature.sh --json --short-name "user-auth" "$ARGUMENTS"` | |
| - Bash (timestamp): `.specify/scripts/bash/create-new-feature.sh --json --timestamp --short-name "user-auth" "$ARGUMENTS"` |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/commands/speckit.specify.md around lines 79 - 80, The Bash examples
for `.specify/scripts/bash/create-new-feature.sh` currently pass the feature
description twice (via "$ARGUMENTS" and the literal "Add user authentication");
update both examples (the plain and the timestamp variant) to provide the
description only once by removing the duplicated literal description so the
script receives either "$ARGUMENTS" or the quoted description but not both;
ensure the examples still include the flags `--json`/`--timestamp` and
`--short-name "user-auth"` and verify that `$ARGUMENTS` remains in the example
if you want to demonstrate passing arguments via the variable.
| # Copy plan template if it exists | ||
| TEMPLATE=$(resolve_template "plan-template" "$REPO_ROOT") || true | ||
| if [[ -n "$TEMPLATE" ]] && [[ -f "$TEMPLATE" ]]; then | ||
| cp "$TEMPLATE" "$IMPL_PLAN" | ||
| echo "Copied plan template to $IMPL_PLAN" | ||
| else | ||
| echo "Warning: Plan template not found" | ||
| # Create a basic plan file if template doesn't exist | ||
| touch "$IMPL_PLAN" | ||
| fi |
There was a problem hiding this comment.
Template copy overwrites existing plan unconditionally.
If $IMPL_PLAN already exists with user content, this will overwrite it. Consider checking if the file exists first and only copying the template when creating a new plan.
🛡️ Proposed fix
# Copy plan template if it exists
TEMPLATE=$(resolve_template "plan-template" "$REPO_ROOT") || true
-if [[ -n "$TEMPLATE" ]] && [[ -f "$TEMPLATE" ]]; then
- cp "$TEMPLATE" "$IMPL_PLAN"
- echo "Copied plan template to $IMPL_PLAN"
-else
- echo "Warning: Plan template not found"
- # Create a basic plan file if template doesn't exist
- touch "$IMPL_PLAN"
+if [[ ! -f "$IMPL_PLAN" ]]; then
+ if [[ -n "$TEMPLATE" ]] && [[ -f "$TEMPLATE" ]]; then
+ cp "$TEMPLATE" "$IMPL_PLAN"
+ echo "Copied plan template to $IMPL_PLAN"
+ else
+ echo "Warning: Plan template not found"
+ # Create a basic plan file if template doesn't exist
+ touch "$IMPL_PLAN"
+ fi
+else
+ echo "Plan already exists: $IMPL_PLAN"
fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.specify/scripts/bash/setup-plan.sh around lines 41 - 50, The current setup
script unconditionally copies the resolved TEMPLATE into IMPL_PLAN which will
overwrite any existing user plan; update the logic in the block that uses
resolve_template and TEMPLATE to first check if IMPL_PLAN already exists and is
non-empty (e.g., test -e or -s on IMPL_PLAN) and only perform cp "$TEMPLATE"
"$IMPL_PLAN" when the plan file does not exist or is empty; if IMPL_PLAN exists,
skip copying and log a message instead so user content is preserved.
| NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file") | ||
| NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file") | ||
| NEW_DB=$(extract_plan_field "Storage" "$plan_file") | ||
| NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file") |
There was a problem hiding this comment.
A brand-new context file drops the extracted storage technology.
parse_plan_data captures Storage into NEW_DB, and the update path later adds it under Active Technologies, but the create path never includes NEW_DB in either tech_stack or recent_change. Repositories getting their first context file will therefore lose the database/storage choice entirely.
Also applies to: 323-343
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.specify/scripts/bash/update-agent-context.sh around lines 196 - 199, The
create-path branch in parse_plan_data/extract_plan_field sets NEW_DB but never
adds it to the new context's tech_stack or recent_change, so include NEW_DB (the
Storage value returned by extract_plan_field) when assembling the tech_stack
array and append it to recent_change in the "create" flow just as the update
flow does; mirror the same logic you use for NEW_LANG/NEW_FRAMEWORK (the
variables set by extract_plan_field) when building the initial context and apply
the same fix to the analogous create branch around the other occurrence
mentioned (the block similar to lines 323-343).
| 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') |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
tmp=$(mktemp)
trap 'rm -f "$tmp" "$tmp".bak' EXIT
printf '[EXTRACTED FROM ALL PLAN.MD FILES]\n' > "$tmp"
NEW_LANG='Node.js'
NEW_FRAMEWORK='R&D + C++'
CURRENT_BRANCH='20260401-demo'
escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)"
sed -i.bak -e "s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|" "$tmp" || true
cat "$tmp"Repository: ambient-code/reference
Length of output: 136
🏁 Script executed:
# First, let's look at the file and the specific line ranges mentioned
cd /root/codebase || cd . 2>/dev/null
find . -name "update-agent-context.sh" -type f 2>/dev/null | head -20Repository: ambient-code/reference
Length of output: 195
🏁 Script executed:
find . -path "*/.specify/scripts/bash/update-agent-context.sh" -type f 2>/dev/nullRepository: ambient-code/reference
Length of output: 113
🏁 Script executed:
# Search more broadly
fd -i "update-agent-context" . 2>/dev/null | head -20Repository: ambient-code/reference
Length of output: 48
🏁 Script executed:
# List the directory structure if it exists
ls -la .specify/scripts/bash/ 2>/dev/null || echo "Directory not found, searching..."
find . -type d -name ".specify" 2>/dev/nullRepository: ambient-code/reference
Length of output: 533
🏁 Script executed:
# Search in git to find the file
git ls-files | grep -i "update-agent-context"Repository: ambient-code/reference
Length of output: 111
🏁 Script executed:
# Examine the specific lines mentioned in the review
sed -n '315,325p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 728
🏁 Script executed:
# Also check lines 345-357
sed -n '340,360p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 922
🏁 Script executed:
# Search for all uses of escaped_lang, escaped_framework, escaped_branch
grep -n "escaped_" ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 1199
🏁 Script executed:
# Get context around all sed substitutions to understand the full scope
grep -n "sed.*escaped" ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 48
🏁 Script executed:
# Check what other variables are used in the substitutions array
sed -n '344,360p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 789
🏁 Script executed:
# Look for all variable assignments that might be used in sed replacements
grep -n "project_name\|project_structure\|commands\|language_conventions" ./.specify/scripts/bash/update-agent-context.sh | head -20Repository: ambient-code/reference
Length of output: 1038
🏁 Script executed:
# Search for where these other variables are defined to see if they're escaped
grep -n "^[[:space:]]*local.*=" ./.specify/scripts/bash/update-agent-context.sh | head -30Repository: ambient-code/reference
Length of output: 1257
🏁 Script executed:
# Let me trace where project_name, project_structure, commands, language_conventions come from
# to understand what they contain
# Check the get_project_structure function
sed -n '249,258p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 263
🏁 Script executed:
# Check the get_commands_for_language function
sed -n '259,277p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 490
🏁 Script executed:
# Check the get_language_conventions function
sed -n '278,282p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 163
🏁 Script executed:
# Let's create a comprehensive test to show ALL the escaping issues
cat > /tmp/test_escaping.sh << 'EOF'
#!/bin/bash
set -euo pipefail
tmp=$(mktemp)
trap 'rm -f "$tmp" "$tmp".bak' EXIT
printf '[PROJECT NAME] [COMMANDS] [LANG] [STRUCTURE]\n' > "$tmp"
# Simulate variables with problematic characters
project_name='My & Project'
commands='npm run build && npm test'
escaped_lang=$(printf '%s\n' 'Node.js' | sed 's/[\[\.*^$()+{}|]/\\&/g')
project_structure='src/ | tests/'
# Current approach - only escaped_lang is "escaped" for regex but NOT for replacement
tech_stack="- $escaped_lang"
echo "BEFORE:"
cat "$tmp"
echo -e "\nTrying substitutions with current approach:"
# This will fail/mangle because & isn't escaped for replacement text
sed -i.bak -e "s|\[PROJECT NAME\]|$project_name|" "$tmp" || true
sed -i.bak -e "s|\[COMMANDS\]|$commands|" "$tmp" || true
sed -i.bak -e "s|\[LANG\]|$tech_stack|" "$tmp" || true
sed -i.bak -e "s|\[STRUCTURE\]|$project_structure|" "$tmp" || true
echo "AFTER (broken):"
cat "$tmp"
EOF
bash /tmp/test_escaping.shRepository: ambient-code/reference
Length of output: 342
🏁 Script executed:
# Better test showing the specific & problem and delimiter problem
cat > /tmp/test_escaping2.sh << 'EOF'
#!/bin/bash
set -euo pipefail
tmp=$(mktemp)
trap 'rm -f "$tmp" "$tmp".bak' EXIT
printf '[PLACEHOLDER]\n' > "$tmp"
echo "=== Test 1: & character in replacement text ==="
value_with_ampersand='Research & Development'
sed -i.bak -e "s|\[PLACEHOLDER\]|$value_with_ampersand|" "$tmp" 2>&1 || echo "Failed"
cat "$tmp"
printf '[PLACEHOLDER]\n' > "$tmp"
echo -e "\n=== Test 2: Pipe character in replacement text ==="
value_with_pipe='option1 | option2'
sed -i.bak -e "s|\[PLACEHOLDER\]|$value_with_pipe|" "$tmp" 2>&1 || echo "Failed"
cat "$tmp"
printf '[PLACEHOLDER]\n' > "$tmp"
echo -e "\n=== Test 3: Backslash in replacement text ==="
value_with_backslash='path\\to\\file'
sed -i.bak -e "s|\[PLACEHOLDER\]|$value_with_backslash|" "$tmp" 2>&1 || echo "Failed"
cat "$tmp"
printf '[PLACEHOLDER]\n' > "$tmp"
echo -e "\n=== Test 4: Proper escaping for replacement text ==="
escape_sed_replacement() {
printf '%s' "$1" | sed 's/[&|\\]/\\&/g'
}
proper_escaped=$(escape_sed_replacement "R&D | Testing\\Path")
sed -i.bak -e "s|\[PLACEHOLDER\]|$proper_escaped|" "$tmp" 2>&1 || echo "Failed"
cat "$tmp"
EOF
bash /tmp/test_escaping2.shRepository: ambient-code/reference
Length of output: 408
🏁 Script executed:
# Verify the exact line range 345-357 that the review mentions
sed -n '345,357p' ./.specify/scripts/bash/update-agent-context.shRepository: ambient-code/reference
Length of output: 708
🏁 Script executed:
# Check if there are any other variables used in sed replacements that aren't escaped
grep -n "local substitutions" -A 15 ./.specify/scripts/bash/update-agent-context.sh | head -25Repository: ambient-code/reference
Length of output: 852
Escape all sed replacement text values to handle &, |, and \ properly.
The current approach only regex-escapes three variables (lines 318-320) for sed pattern matching, but these same values are used as sed replacement text where different characters need escaping. Additionally, four other unescaped variables (project_name, current_date, project_structure, commands, language_conventions) are directly interpolated into the replacements array (lines 345-352) without any escaping.
In sed replacement text:
&expands to the full matched pattern (breaks output)|is the chosen delimiter and causes syntax errors\has special meaning and needs escaping
Apply replacement text escaping to all seven variables used in the substitutions array:
Suggested direction
+escape_sed_replacement() {
+ printf '%s' "$1" | sed 's/[&|\\]/\\&/g'
+}Then escape each variable before use:
local escaped_lang=$(escape_sed_replacement "$NEW_LANG")
local escaped_framework=$(escape_sed_replacement "$NEW_FRAMEWORK")
local escaped_branch=$(escape_sed_replacement "$CURRENT_BRANCH")
local project_name=$(escape_sed_replacement "$(basename "$REPO_ROOT")")
local current_date=$(escape_sed_replacement "$(date +%Y-%m-%d)")
local project_structure=$(escape_sed_replacement "$(get_project_structure "$NEW_PROJECT_TYPE")")
local commands=$(escape_sed_replacement "$(get_commands_for_language "$NEW_LANG")")
local language_conventions=$(escape_sed_replacement "$(get_language_conventions "$NEW_LANG")")
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 318-318: Declare and assign separately to avoid masking return values.
(SC2155)
[info] 318-318: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[warning] 319-319: Declare and assign separately to avoid masking return values.
(SC2155)
[info] 319-319: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
[warning] 320-320: Declare and assign separately to avoid masking return values.
(SC2155)
[info] 320-320: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.specify/scripts/bash/update-agent-context.sh around lines 318 - 320, The
sed replacement values are not properly escaped for replacement text (specials
like &, | and \), so add a small helper (e.g. escape_sed_replacement) that
escapes backslashes, ampersands and your chosen sed delimiter (|) and then use
it to produce escaped versions of NEW_LANG, NEW_FRAMEWORK, CURRENT_BRANCH and
also the other replacement values used in the substitutions array (project_name,
current_date, project_structure, commands, language_conventions); replace the
current printf/sed regex-escape usage with calls to this helper and use the
escaped_* variables when building the substitutions array and invoking sed.
| if [[ "$line" == "## Recent Changes" ]]; then | ||
| echo "$line" >> "$temp_file" | ||
| # Add new change entry right after the heading | ||
| if [[ -n "$new_change_entry" ]]; then | ||
| echo "$new_change_entry" >> "$temp_file" | ||
| fi | ||
| in_changes_section=true | ||
| changes_entries_added=true | ||
| continue | ||
| elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then | ||
| echo "$line" >> "$temp_file" | ||
| in_changes_section=false | ||
| continue | ||
| elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then | ||
| # Keep only first 2 existing changes | ||
| if [[ $existing_changes_count -lt 2 ]]; then | ||
| echo "$line" >> "$temp_file" | ||
| ((existing_changes_count++)) | ||
| fi |
There was a problem hiding this comment.
The Recent Changes rewrite isn't idempotent.
Every run prepends new_change_entry and then copies the first two existing bullets. If the file already contains the same branch entry from a prior update, the current branch is duplicated on every rerun.
Suggested fix
- if [[ -n "$new_change_entry" ]]; then
+ if [[ -n "$new_change_entry" ]] && ! grep -Fqx -- "$new_change_entry" "$target_file"; then
echo "$new_change_entry" >> "$temp_file"
fi📝 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.
| if [[ "$line" == "## Recent Changes" ]]; then | |
| echo "$line" >> "$temp_file" | |
| # Add new change entry right after the heading | |
| if [[ -n "$new_change_entry" ]]; then | |
| echo "$new_change_entry" >> "$temp_file" | |
| fi | |
| in_changes_section=true | |
| changes_entries_added=true | |
| continue | |
| elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then | |
| echo "$line" >> "$temp_file" | |
| in_changes_section=false | |
| continue | |
| elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then | |
| # Keep only first 2 existing changes | |
| if [[ $existing_changes_count -lt 2 ]]; then | |
| echo "$line" >> "$temp_file" | |
| ((existing_changes_count++)) | |
| fi | |
| if [[ "$line" == "## Recent Changes" ]]; then | |
| echo "$line" >> "$temp_file" | |
| # Add new change entry right after the heading | |
| if [[ -n "$new_change_entry" ]] && ! grep -Fqx -- "$new_change_entry" "$target_file"; then | |
| echo "$new_change_entry" >> "$temp_file" | |
| fi | |
| in_changes_section=true | |
| changes_entries_added=true | |
| continue | |
| elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then | |
| echo "$line" >> "$temp_file" | |
| in_changes_section=false | |
| continue | |
| elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then | |
| # Keep only first 2 existing changes | |
| if [[ $existing_changes_count -lt 2 ]]; then | |
| echo "$line" >> "$temp_file" | |
| ((existing_changes_count++)) | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.specify/scripts/bash/update-agent-context.sh around lines 465 - 483, The
Recent Changes block is not idempotent because the script always echoes
new_change_entry, causing duplicates; fix by detecting whether new_change_entry
already exists in that section before adding it: when you enter the "## Recent
Changes" branch (use the in_changes_section variable and the new_change_entry
variable), scan the following lines (until the next "## " heading) for a line
equal to new_change_entry and set a flag like new_change_present; only echo
new_change_entry into the temp_file if new_change_present is false, and ensure
existing_changes_count logic still copies at most two unique bullets (skip lines
equal to new_change_entry while counting) so reruns won't prepend a duplicate.
| **Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link] | ||
| **Input**: Feature specification from `/specs/[###-feature-name]/spec.md` | ||
|
|
||
| **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow. |
There was a problem hiding this comment.
Fix misleading self-reference in note.
This line points to the current file for execution workflow details. It should reference the command workflow document (e.g., .claude/commands/speckit.plan.md) instead.
📝 Proposed fix
-**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow.
+**Note**: This template is filled in by the `/speckit.plan` command. See `.claude/commands/speckit.plan.md` for the execution workflow.📝 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.
| **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow. | |
| **Note**: This template is filled in by the `/speckit.plan` command. See `.claude/commands/speckit.plan.md` for the execution workflow. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.specify/templates/plan-template.md at line 6, Update the misleading
self-reference in the note: change the execution workflow link text in
.specify/templates/plan-template.md so it no longer points to the same template
but instead references the command workflow document (e.g.,
.claude/commands/speckit.plan.md) and the /speckit.plan command; edit the
sentence beginning "**Note**: This template is filled in by the `/speckit.plan`
command. See `.specify/templates/plan-template.md` for the execution workflow."
to point to the proper workflow doc (.claude/commands/speckit.plan.md) and
ensure the phrasing clearly ties the template to the `/speckit.plan` command.
Summary
speckit.constitution.md(.specify/templates/commands/*.md→.claude/commands/speckit.*.md).repomap.txtto reflect new files added in PR Add spec-kit integration and rewrite spec-kit-auto skill #30.worktrees/to.gitignoreContext
Issues identified during code review of PR #30.
Depends on PR #30 being merged first (this branch is based on
feature/add-spec-kit-auto-skill).Test plan
speckit.constitution.mdreferences correct path.repomap.txtincludes new spec-kit files.worktrees/is gitignored🤖 Generated with Claude Code