Compare commits

..

4 Commits

Author SHA1 Message Date
Den Delimarsky
fa3171ca6e Merge pull request #214 from github/update-cli
Saner approach to scripts
2025-09-12 14:06:34 -07:00
Den Delimarsky 🌺
117ec67e47 Saner approach to scripts 2025-09-12 14:05:55 -07:00
Den Delimarsky
5bd7027526 Merge pull request #213 from github/update-cli
Update packaging
2025-09-12 13:45:55 -07:00
Den Delimarsky 🌺
ec7d87f121 Update packaging 2025-09-12 13:45:28 -07:00
4 changed files with 44 additions and 47 deletions

View File

@@ -47,43 +47,36 @@ generate_commands() {
mkdir -p "$output_dir"
for template in templates/commands/*.md; do
[[ -f "$template" ]] || continue
local name description raw_body variant_line injected body file_norm delim_count
local name description script_command body
name=$(basename "$template" .md)
# Normalize line endings first (remove CR) for consistent regex matching
file_norm=$(tr -d '\r' < "$template")
# Extract description from frontmatter
description=$(printf '%s\n' "$file_norm" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
# Count YAML frontmatter delimiter lines
delim_count=$(printf '%s\n' "$file_norm" | grep -c '^---$' || true)
if [[ $delim_count -ge 2 ]]; then
# Grab everything after the second --- line
raw_body=$(printf '%s\n' "$file_norm" | awk '/^---$/ {if(++c==2){next}; if(c>=2){print}}')
else
# Fallback: no proper frontmatter detected; use entire file content (still allowing variant parsing)
raw_body=$file_norm
# Normalize line endings
file_content=$(tr -d '\r' < "$template")
# Extract description and script command from YAML frontmatter
description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
script_command=$(printf '%s\n' "$file_content" | awk -v sv="$script_variant" '/^[[:space:]]*'"$script_variant"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, ""); print; exit}')
if [[ -z $script_command ]]; then
echo "Warning: no script command found for $script_variant in $template" >&2
script_command="(Missing script command for $script_variant)"
fi
# If somehow still empty, fallback once more to whole normalized file
if [[ -z ${raw_body// /} ]]; then
echo "Warning: body extraction empty for $template; using full file" >&2
raw_body=$file_norm
fi
# Find single-line variant comment matching the variant: <!-- VARIANT:sh ... --> or <!-- VARIANT:ps ... -->
variant_line=$(printf '%s\n' "$raw_body" | awk -v sv="$script_variant" '/<!--[[:space:]]+VARIANT:'sv'/ {match($0, /VARIANT:'"sv"'[[:space:]]+(.*)-->/, m); if (m[1]!="") {print m[1]; exit}}')
if [[ -z $variant_line ]]; then
echo "Warning: no variant line found for $script_variant in $template" >&2
variant_line="(Missing variant command for $script_variant)"
fi
# Replace the token VARIANT-INJECT with the selected variant line
injected=$(printf '%s\n' "$raw_body" | sed "s/VARIANT-INJECT/${variant_line//\//\/}/")
# Remove all single-line variant comments
injected=$(printf '%s\n' "$injected" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d')
# Guard: if after stripping variant lines and injection the body became empty, restore original (minus variant comments) to avoid empty prompt files
if [[ -z ${injected// /} ]]; then
echo "Warning: resulting injected body empty for $template; writing unmodified body" >&2
injected=$raw_body
fi
# Apply arg substitution and path rewrite
body=$(printf '%s\n' "$injected" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
# Replace {SCRIPT} placeholder with the script command
body=$(printf '%s\n' "$file_content" | sed "s|{SCRIPT}|${script_command}|g")
# Remove the scripts: section from frontmatter while preserving YAML structure
body=$(printf '%s\n' "$body" | awk '
/^---$/ { print; if (++dash_count == 1) in_frontmatter=1; else in_frontmatter=0; next }
in_frontmatter && /^scripts:$/ { skip_scripts=1; next }
in_frontmatter && /^[a-zA-Z].*:/ && skip_scripts { skip_scripts=0 }
in_frontmatter && skip_scripts && /^[[:space:]]/ { next }
{ print }
')
# Apply other substitutions
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
case $ext in
toml)
{ echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/$name.$ext" ;;
@@ -104,12 +97,13 @@ build_variant() {
# Inject variant into plan-template.md within .specify/templates if present
local plan_tpl="$base_dir/.specify/templates/plan-template.md"
if [[ -f "$plan_tpl" ]]; then
variant_line=$(awk -v sv="$script" '/<!--[[:space:]]*VARIANT:'"$script"'/ {match($0, /VARIANT:'"$script"'[[:space:]]+(.*)-->/, m); if(m[1]!=""){print m[1]; exit}}' "$plan_tpl")
plan_norm=$(tr -d '\r' < "$plan_tpl")
variant_line=$(printf '%s\n' "$plan_norm" | grep -E "<!--[[:space:]]*VARIANT:$script" | head -1 | sed -E "s/.*VARIANT:$script[[:space:]]+//; s/-->.*//; s/^[[:space:]]+//; s/[[:space:]]+$//")
if [[ -n $variant_line ]]; then
tmp_file=$(mktemp)
sed "s/VARIANT-INJECT/${variant_line//\//\/}/" "$plan_tpl" | sed "/__AGENT__/s//${agent}/g" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d' > "$tmp_file" && mv "$tmp_file" "$plan_tpl"
sed "s|VARIANT-INJECT|${variant_line}|" "$plan_tpl" | tr -d '\r' | sed "s|__AGENT__|${agent}|g" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d' > "$tmp_file" && mv "$tmp_file" "$plan_tpl"
else
echo "Warning: no plan-template variant for $script" >&2
echo "Warning: no plan-template variant for $script (pattern not matched)" >&2
fi
fi
case $agent in

View File

@@ -1,12 +1,13 @@
---
description: Execute the implementation planning workflow using the plan template to generate design artifacts.
scripts:
sh: scripts/bash/setup-plan.sh --json
ps: scripts/powershell/setup-plan.ps1 -Json
---
<!-- VARIANT:sh 1. Run `scripts/bash/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. -->
<!-- VARIANT:ps 1. Run `scripts/powershell/setup-plan.ps1 -Json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. -->
Given the implementation details provided as an argument, do this:
1. VARIANT-INJECT
1. Run `{SCRIPT}` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute.
2. Read and analyze the feature specification to understand:
- The feature requirements and user stories
- Functional and non-functional requirements

View File

@@ -1,12 +1,13 @@
---
description: Create or update the feature specification from a natural language feature description.
scripts:
sh: scripts/bash/create-new-feature.sh --json "{ARGS}"
ps: scripts/powershell/create-new-feature.ps1 -Json "{ARGS}"
---
<!-- VARIANT:sh 1. Run the script `scripts/bash/create-new-feature.sh --json "{ARGS}"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. -->
<!-- VARIANT:ps 1. Run the script `scripts/powershell/create-new-feature.ps1 -Json "{ARGS}"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. -->
Given the feature description provided as an argument, do this:
1. VARIANT-INJECT
1. Run the script `{SCRIPT}` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
2. Load `templates/spec-template.md` to understand required sections.
3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
4. Report completion with branch name, spec file path, and readiness for the next phase.

View File

@@ -1,12 +1,13 @@
---
description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
scripts:
sh: scripts/bash/check-task-prerequisites.sh --json
ps: scripts/powershell/check-task-prerequisites.ps1 -Json
---
<!-- VARIANT:sh 1. Run `scripts/bash/check-task-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. -->
<!-- VARIANT:ps 1. Run `scripts/powershell/check-task-prerequisites.ps1 -Json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. -->
Given the context provided as an argument, do this:
1. VARIANT-INJECT
1. Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
2. Load and analyze available design documents:
- Always read plan.md for tech stack and libraries
- IF EXISTS: Read data-model.md for entities