Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46ba4d57e9 | ||
|
|
692fd34697 | ||
|
|
2f043ef682 | ||
|
|
d90cc16786 | ||
|
|
5fc1d0b939 | ||
|
|
fb9bc613a5 | ||
|
|
ebd99bc11b | ||
|
|
7c13281d34 | ||
|
|
8bd155b9f5 | ||
|
|
f6e4714ba0 | ||
|
|
919bda2355 | ||
|
|
1414bcb1b2 | ||
|
|
ec47ecfd16 | ||
|
|
c5f7582470 | ||
|
|
87d4998b9d | ||
|
|
10e56aa67c | ||
|
|
cc686c6621 | ||
|
|
8b49d5d0fb | ||
|
|
66688dffa3 | ||
|
|
b18ef208cb | ||
|
|
5828e58f84 | ||
|
|
dd57e9d444 | ||
|
|
558e682865 | ||
|
|
c5e0c1840b | ||
|
|
63bc6b495d | ||
|
|
70b3db27db | ||
|
|
6e94588615 | ||
|
|
ad9c93c13b | ||
|
|
f979b64338 | ||
|
|
b1591282f6 | ||
|
|
856680e3bc | ||
|
|
60b015a094 | ||
|
|
0c2b367ba0 | ||
|
|
6b8b1a8b93 | ||
|
|
0e6f513c14 | ||
|
|
6f81f7d6a0 | ||
|
|
c875bd0f30 | ||
|
|
736e282562 | ||
|
|
542751fcd1 | ||
|
|
6c83e9ff66 | ||
|
|
a55448057b | ||
|
|
88cded5c4d | ||
|
|
0ad2f169d2 | ||
|
|
fa3171ca6e | ||
|
|
117ec67e47 | ||
|
|
0c419e5198 | ||
|
|
fe4de3ca45 | ||
|
|
73a9af70a4 |
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@@ -81,7 +81,7 @@ jobs:
|
|||||||
cat > release_notes.md << EOF
|
cat > release_notes.md << EOF
|
||||||
Template release ${{ steps.get_tag.outputs.new_version }}
|
Template release ${{ steps.get_tag.outputs.new_version }}
|
||||||
|
|
||||||
Updated specification-driven development templates for GitHub Copilot, Claude Code, and Gemini CLI.
|
Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, Cursor, Qwen, and opencode.
|
||||||
|
|
||||||
Now includes per-script variants for POSIX shell (sh) and PowerShell (ps).
|
Now includes per-script variants for POSIX shell (sh) and PowerShell (ps).
|
||||||
|
|
||||||
@@ -92,6 +92,12 @@ jobs:
|
|||||||
- spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
- spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
- spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip
|
- spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
- spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
- spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-opencode-sh-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-qwen-sh-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
|
- spec-kit-template-qwen-ps-${{ steps.get_tag.outputs.new_version }}.zip
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "Generated release notes:"
|
echo "Generated release notes:"
|
||||||
@@ -110,6 +116,12 @@ jobs:
|
|||||||
spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip \
|
spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-opencode-sh-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-qwen-sh-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
|
spec-kit-template-qwen-ps-${{ steps.get_tag.outputs.new_version }}.zip \
|
||||||
--title "Spec Kit Templates - $VERSION_NO_V" \
|
--title "Spec Kit Templates - $VERSION_NO_V" \
|
||||||
--notes-file release_notes.md
|
--notes-file release_notes.md
|
||||||
env:
|
env:
|
||||||
|
|||||||
122
.github/workflows/scripts/create-release-packages.sh
vendored
122
.github/workflows/scripts/create-release-packages.sh
vendored
@@ -6,7 +6,7 @@ set -euo pipefail
|
|||||||
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
|
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
|
||||||
# Version argument should include leading 'v'.
|
# Version argument should include leading 'v'.
|
||||||
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
|
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
|
||||||
# AGENTS : space or comma separated subset of: claude gemini copilot (default: all)
|
# AGENTS : space or comma separated subset of: claude gemini copilot qwen opencode (default: all)
|
||||||
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
|
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
|
||||||
# Examples:
|
# Examples:
|
||||||
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
|
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
|
||||||
@@ -25,15 +25,7 @@ fi
|
|||||||
|
|
||||||
echo "Building release packages for $NEW_VERSION"
|
echo "Building release packages for $NEW_VERSION"
|
||||||
|
|
||||||
rm -rf sdd-package-base* sdd-*-package-* spec-kit-template-*-${NEW_VERSION}.zip || true
|
rm -rf sdd-package-base* sdd-*-package-* spec-kit-template-*-"${NEW_VERSION}".zip || true
|
||||||
|
|
||||||
mkdir -p sdd-package-base
|
|
||||||
SPEC_DIR="sdd-package-base/.specify"
|
|
||||||
mkdir -p "$SPEC_DIR"
|
|
||||||
|
|
||||||
[[ -d memory ]] && { cp -r memory "$SPEC_DIR/"; echo "Copied memory -> .specify"; }
|
|
||||||
[[ -d scripts ]] && { cp -r scripts "$SPEC_DIR/"; echo "Copied scripts -> .specify/scripts"; }
|
|
||||||
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
|
|
||||||
|
|
||||||
rewrite_paths() {
|
rewrite_paths() {
|
||||||
sed -E \
|
sed -E \
|
||||||
@@ -47,22 +39,36 @@ generate_commands() {
|
|||||||
mkdir -p "$output_dir"
|
mkdir -p "$output_dir"
|
||||||
for template in templates/commands/*.md; do
|
for template in templates/commands/*.md; do
|
||||||
[[ -f "$template" ]] || continue
|
[[ -f "$template" ]] || continue
|
||||||
local name description file_content variant_line injected body
|
local name description script_command body
|
||||||
name=$(basename "$template" .md)
|
name=$(basename "$template" .md)
|
||||||
# Normalize line endings and work with entire file content
|
|
||||||
|
# Normalize line endings
|
||||||
file_content=$(tr -d '\r' < "$template")
|
file_content=$(tr -d '\r' < "$template")
|
||||||
# Extract description from frontmatter
|
|
||||||
|
# Extract description and script command from YAML frontmatter
|
||||||
description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
|
description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
|
||||||
# Find variant line content
|
script_command=$(printf '%s\n' "$file_content" | awk -v sv="$script_variant" '/^[[:space:]]*'"$script_variant"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, ""); print; exit}')
|
||||||
variant_line=$(printf '%s\n' "$file_content" | grep -E "<!--[[:space:]]*VARIANT:${script_variant}[[:space:]]" | head -1 | sed -E "s/.*VARIANT:${script_variant}[[:space:]]+//; s/-->.*//")
|
|
||||||
if [[ -z $variant_line ]]; then
|
if [[ -z $script_command ]]; then
|
||||||
echo "Warning: no variant line found for $script_variant in $template" >&2
|
echo "Warning: no script command found for $script_variant in $template" >&2
|
||||||
variant_line="(Missing variant command for $script_variant)"
|
script_command="(Missing script command for $script_variant)"
|
||||||
fi
|
fi
|
||||||
# Replace VARIANT-INJECT and remove variant comments
|
|
||||||
body=$(printf '%s\n' "$file_content" | sed "s|VARIANT-INJECT|${variant_line}|" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d')
|
# Replace {SCRIPT} placeholder with the script command
|
||||||
# Apply substitutions
|
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)
|
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
|
||||||
|
|
||||||
case $ext in
|
case $ext in
|
||||||
toml)
|
toml)
|
||||||
{ echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/$name.$ext" ;;
|
{ echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/$name.$ext" ;;
|
||||||
@@ -79,19 +85,54 @@ build_variant() {
|
|||||||
local base_dir="sdd-${agent}-package-${script}"
|
local base_dir="sdd-${agent}-package-${script}"
|
||||||
echo "Building $agent ($script) package..."
|
echo "Building $agent ($script) package..."
|
||||||
mkdir -p "$base_dir"
|
mkdir -p "$base_dir"
|
||||||
cp -r sdd-package-base/. "$base_dir"/
|
|
||||||
|
# Copy base structure but filter scripts by variant
|
||||||
|
SPEC_DIR="$base_dir/.specify"
|
||||||
|
mkdir -p "$SPEC_DIR"
|
||||||
|
|
||||||
|
[[ -d memory ]] && { cp -r memory "$SPEC_DIR/"; echo "Copied memory -> .specify"; }
|
||||||
|
|
||||||
|
# Only copy the relevant script variant directory
|
||||||
|
if [[ -d scripts ]]; then
|
||||||
|
mkdir -p "$SPEC_DIR/scripts"
|
||||||
|
case $script in
|
||||||
|
sh)
|
||||||
|
[[ -d scripts/bash ]] && { cp -r scripts/bash "$SPEC_DIR/scripts/"; echo "Copied scripts/bash -> .specify/scripts"; }
|
||||||
|
# Copy any script files that aren't in variant-specific directories
|
||||||
|
find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
ps)
|
||||||
|
[[ -d scripts/powershell ]] && { cp -r scripts/powershell "$SPEC_DIR/scripts/"; echo "Copied scripts/powershell -> .specify/scripts"; }
|
||||||
|
# Copy any script files that aren't in variant-specific directories
|
||||||
|
find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
|
||||||
# Inject variant into plan-template.md within .specify/templates if present
|
# Inject variant into plan-template.md within .specify/templates if present
|
||||||
local plan_tpl="$base_dir/.specify/templates/plan-template.md"
|
local plan_tpl="$base_dir/.specify/templates/plan-template.md"
|
||||||
if [[ -f "$plan_tpl" ]]; then
|
if [[ -f "$plan_tpl" ]]; then
|
||||||
plan_norm=$(tr -d '\r' < "$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:]]+$//")
|
# Extract script command from YAML frontmatter
|
||||||
if [[ -n $variant_line ]]; then
|
script_command=$(printf '%s\n' "$plan_norm" | awk -v sv="$script" '/^[[:space:]]*'"$script"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script"':[[:space:]]*/, ""); print; exit}')
|
||||||
tmp_file=$(mktemp)
|
if [[ -n $script_command ]]; then
|
||||||
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"
|
# Always prefix with .specify/ for plan usage
|
||||||
|
script_command=".specify/$script_command"
|
||||||
|
# Replace {SCRIPT} placeholder with the script command and __AGENT__ with agent name
|
||||||
|
substituted=$(sed "s|{SCRIPT}|${script_command}|g" "$plan_tpl" | tr -d '\r' | sed "s|__AGENT__|${agent}|g")
|
||||||
|
# Strip YAML frontmatter from plan template output (keep body only)
|
||||||
|
stripped=$(printf '%s\n' "$substituted" | awk 'BEGIN{fm=0;dash=0} /^---$/ {dash++; if(dash==1){fm=1; next} else if(dash==2){fm=0; next}} {if(!fm) print}')
|
||||||
|
printf '%s\n' "$stripped" > "$plan_tpl"
|
||||||
else
|
else
|
||||||
echo "Warning: no plan-template variant for $script (pattern not matched)" >&2
|
echo "Warning: no plan-template script command found for $script in YAML frontmatter" >&2
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
|
||||||
|
# * Markdown/prompt (claude, copilot, cursor, opencode): $ARGUMENTS
|
||||||
|
# * TOML (gemini, qwen): {{args}}
|
||||||
|
# This keeps formats readable without extra abstraction.
|
||||||
|
|
||||||
case $agent in
|
case $agent in
|
||||||
claude)
|
claude)
|
||||||
mkdir -p "$base_dir/.claude/commands"
|
mkdir -p "$base_dir/.claude/commands"
|
||||||
@@ -103,26 +144,37 @@ build_variant() {
|
|||||||
copilot)
|
copilot)
|
||||||
mkdir -p "$base_dir/.github/prompts"
|
mkdir -p "$base_dir/.github/prompts"
|
||||||
generate_commands copilot prompt.md "\$ARGUMENTS" "$base_dir/.github/prompts" "$script" ;;
|
generate_commands copilot prompt.md "\$ARGUMENTS" "$base_dir/.github/prompts" "$script" ;;
|
||||||
|
cursor)
|
||||||
|
mkdir -p "$base_dir/.cursor/commands"
|
||||||
|
generate_commands cursor md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
|
||||||
|
qwen)
|
||||||
|
mkdir -p "$base_dir/.qwen/commands"
|
||||||
|
generate_commands qwen toml "{{args}}" "$base_dir/.qwen/commands" "$script"
|
||||||
|
[[ -f agent_templates/qwen/QWEN.md ]] && cp agent_templates/qwen/QWEN.md "$base_dir/QWEN.md" ;;
|
||||||
|
opencode)
|
||||||
|
mkdir -p "$base_dir/.opencode/command"
|
||||||
|
generate_commands opencode md "\$ARGUMENTS" "$base_dir/.opencode/command" "$script" ;;
|
||||||
esac
|
esac
|
||||||
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
|
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
|
||||||
echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
|
echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine agent list
|
# Determine agent list
|
||||||
ALL_AGENTS=(claude gemini copilot)
|
ALL_AGENTS=(claude gemini copilot cursor qwen opencode)
|
||||||
ALL_SCRIPTS=(sh ps)
|
ALL_SCRIPTS=(sh ps)
|
||||||
|
|
||||||
|
|
||||||
norm_list() {
|
norm_list() {
|
||||||
# convert comma+space separated -> space separated unique while preserving order of first occurrence
|
# convert comma+space separated -> space separated unique while preserving order of first occurrence
|
||||||
tr ',\n' ' ' | awk '{for(i=1;i<=NF;i++){if(!seen[$i]++){printf((out?" ":"") $i)}}}END{printf("\n")}'
|
tr ',\n' ' ' | awk '{for(i=1;i<=NF;i++){if(!seen[$i]++){printf((out?" ":"") $i)}}}END{printf("\n")}'
|
||||||
}
|
}
|
||||||
|
|
||||||
validate_subset() {
|
validate_subset() {
|
||||||
local type=$1; shift; local -n allowed=$1; shift; local items=($@)
|
local type=$1; shift; local -n allowed=$1; shift; local items=("$@")
|
||||||
local ok=1
|
local ok=1
|
||||||
for it in "${items[@]}"; do
|
for it in "${items[@]}"; do
|
||||||
local found=0
|
local found=0
|
||||||
for a in "${allowed[@]}"; do [[ $it == $a ]] && { found=1; break; }; done
|
for a in "${allowed[@]}"; do [[ $it == "$a" ]] && { found=1; break; }; done
|
||||||
if [[ $found -eq 0 ]]; then
|
if [[ $found -eq 0 ]]; then
|
||||||
echo "Error: unknown $type '$it' (allowed: ${allowed[*]})" >&2
|
echo "Error: unknown $type '$it' (allowed: ${allowed[*]})" >&2
|
||||||
ok=0
|
ok=0
|
||||||
@@ -132,17 +184,17 @@ validate_subset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [[ -n ${AGENTS:-} ]]; then
|
if [[ -n ${AGENTS:-} ]]; then
|
||||||
AGENT_LIST=($(printf '%s' "$AGENTS" | norm_list))
|
mapfile -t AGENT_LIST < <(printf '%s' "$AGENTS" | norm_list)
|
||||||
validate_subset agent ALL_AGENTS "${AGENT_LIST[@]}" || exit 1
|
validate_subset agent ALL_AGENTS "${AGENT_LIST[@]}" || exit 1
|
||||||
else
|
else
|
||||||
AGENT_LIST=(${ALL_AGENTS[@]})
|
AGENT_LIST=("${ALL_AGENTS[@]}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n ${SCRIPTS:-} ]]; then
|
if [[ -n ${SCRIPTS:-} ]]; then
|
||||||
SCRIPT_LIST=($(printf '%s' "$SCRIPTS" | norm_list))
|
mapfile -t SCRIPT_LIST < <(printf '%s' "$SCRIPTS" | norm_list)
|
||||||
validate_subset script ALL_SCRIPTS "${SCRIPT_LIST[@]}" || exit 1
|
validate_subset script ALL_SCRIPTS "${SCRIPT_LIST[@]}" || exit 1
|
||||||
else
|
else
|
||||||
SCRIPT_LIST=(${ALL_SCRIPTS[@]})
|
SCRIPT_LIST=("${ALL_SCRIPTS[@]}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Agents: ${AGENT_LIST[*]}"
|
echo "Agents: ${AGENT_LIST[*]}"
|
||||||
@@ -155,4 +207,4 @@ for agent in "${AGENT_LIST[@]}"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "Archives:"
|
echo "Archives:"
|
||||||
ls -1 spec-kit-template-*-${NEW_VERSION}.zip
|
ls -1 spec-kit-template-*-"${NEW_VERSION}".zip
|
||||||
|
|||||||
35
CHANGELOG.md
Normal file
35
CHANGELOG.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to the Specify CLI will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.0.6] - 2025-09-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- opencode support as additional AI assistant option
|
||||||
|
|
||||||
|
## [0.0.5] - 2025-09-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Qwen Code support as additional AI assistant option
|
||||||
|
|
||||||
|
## [0.0.4] - 2025-09-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- SOCKS proxy support for corporate environments via `httpx[socks]` dependency
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ These are one time installations required to be able to test your changes locall
|
|||||||
1. Install [Python 3.11+](https://www.python.org/downloads/)
|
1. Install [Python 3.11+](https://www.python.org/downloads/)
|
||||||
1. Install [uv](https://docs.astral.sh/uv/) for package management
|
1. Install [uv](https://docs.astral.sh/uv/) for package management
|
||||||
1. Install [Git](https://git-scm.com/downloads)
|
1. Install [Git](https://git-scm.com/downloads)
|
||||||
1. Have an AI coding agent available: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), or [Gemini CLI](https://github.com/google-gemini/gemini-cli) are recommended, but we're working on adding support for other agents as well.
|
1. Have an AI coding agent available: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Qwen Code](https://github.com/QwenLM/qwen-code). We're working on adding support for other agents as well.
|
||||||
|
|
||||||
## Submitting a pull request
|
## Submitting a pull request
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ Here are a few things you can do that will increase the likelihood of your pull
|
|||||||
|
|
||||||
- Follow the project's coding conventions.
|
- Follow the project's coding conventions.
|
||||||
- Write tests for new functionality.
|
- Write tests for new functionality.
|
||||||
- Update documentation (`README.md,` `spec-driven.md`) if your changes affect user-facing features.
|
- Update documentation (`README.md`, `spec-driven.md`) if your changes affect user-facing features.
|
||||||
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
|
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
|
||||||
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||||
- Test your changes with the Spec-Driven Development workflow to ensure compatibility.
|
- Test your changes with the Spec-Driven Development workflow to ensure compatibility.
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
- [🤔 What is Spec-Driven Development?](#-what-is-spec-driven-development)
|
- [🤔 What is Spec-Driven Development?](#-what-is-spec-driven-development)
|
||||||
- [⚡ Get started](#-get-started)
|
- [⚡ Get started](#-get-started)
|
||||||
|
- [📽️ Video Overview](#️-video-overview)
|
||||||
- [🔧 Specify CLI Reference](#-specify-cli-reference)
|
- [🔧 Specify CLI Reference](#-specify-cli-reference)
|
||||||
- [📚 Core philosophy](#-core-philosophy)
|
- [📚 Core philosophy](#-core-philosophy)
|
||||||
- [🌟 Development phases](#-development-phases)
|
- [🌟 Development phases](#-development-phases)
|
||||||
@@ -45,7 +46,7 @@ uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME
|
|||||||
|
|
||||||
### 2. Create the spec
|
### 2. Create the spec
|
||||||
|
|
||||||
Use the `/specify` command to describe what you want to build. Focus on the **what** and **why**, not the tech stack.
|
Use the **`/specify`** command to describe what you want to build. Focus on the **what** and **why**, not the tech stack.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface.
|
/specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface.
|
||||||
@@ -53,7 +54,7 @@ Use the `/specify` command to describe what you want to build. Focus on the **wh
|
|||||||
|
|
||||||
### 3. Create a technical implementation plan
|
### 3. Create a technical implementation plan
|
||||||
|
|
||||||
Use the `/plan` command to provide your tech stack and architecture choices.
|
Use the **`/plan`** command to provide your tech stack and architecture choices.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database.
|
/plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database.
|
||||||
@@ -61,10 +62,16 @@ Use the `/plan` command to provide your tech stack and architecture choices.
|
|||||||
|
|
||||||
### 4. Break down and implement
|
### 4. Break down and implement
|
||||||
|
|
||||||
Use `/tasks` to create an actionable task list, then ask your agent to implement the feature.
|
Use **`/tasks`** to create an actionable task list, then ask your agent to implement the feature.
|
||||||
|
|
||||||
For detailed step-by-step instructions, see our [comprehensive guide](./spec-driven.md).
|
For detailed step-by-step instructions, see our [comprehensive guide](./spec-driven.md).
|
||||||
|
|
||||||
|
## 📽️ Video Overview
|
||||||
|
|
||||||
|
Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.com/watch?v=a9eR1xsfvHg&pp=0gcJCckJAYcqIYzv)!
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=a9eR1xsfvHg&pp=0gcJCckJAYcqIYzv)
|
||||||
|
|
||||||
## 🔧 Specify CLI Reference
|
## 🔧 Specify CLI Reference
|
||||||
|
|
||||||
The `specify` command supports the following options:
|
The `specify` command supports the following options:
|
||||||
@@ -74,18 +81,20 @@ The `specify` command supports the following options:
|
|||||||
| Command | Description |
|
| Command | Description |
|
||||||
|-------------|----------------------------------------------------------------|
|
|-------------|----------------------------------------------------------------|
|
||||||
| `init` | Initialize a new Specify project from the latest template |
|
| `init` | Initialize a new Specify project from the latest template |
|
||||||
| `check` | Check for installed tools (`git`, `claude`, `gemini`) |
|
| `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `opencode`, `cursor-agent`) |
|
||||||
|
|
||||||
### `specify init` Arguments & Options
|
### `specify init` Arguments & Options
|
||||||
|
|
||||||
| Argument/Option | Type | Description |
|
| Argument/Option | Type | Description |
|
||||||
|------------------------|----------|------------------------------------------------------------------------------|
|
|------------------------|----------|------------------------------------------------------------------------------|
|
||||||
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) |
|
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) |
|
||||||
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, or `copilot` |
|
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `opencode`, or `cursor` |
|
||||||
|
| `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) |
|
||||||
| `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
|
| `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
|
||||||
| `--no-git` | Flag | Skip git repository initialization |
|
| `--no-git` | Flag | Skip git repository initialization |
|
||||||
| `--here` | Flag | Initialize project in the current directory instead of creating a new one |
|
| `--here` | Flag | Initialize project in the current directory instead of creating a new one |
|
||||||
| `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) |
|
| `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) |
|
||||||
|
| `--debug` | Flag | Enable detailed debug output for troubleshooting |
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -96,12 +105,21 @@ specify init my-project
|
|||||||
# Initialize with specific AI assistant
|
# Initialize with specific AI assistant
|
||||||
specify init my-project --ai claude
|
specify init my-project --ai claude
|
||||||
|
|
||||||
|
# Initialize with Cursor support
|
||||||
|
specify init my-project --ai cursor
|
||||||
|
|
||||||
|
# Initialize with PowerShell scripts (Windows/cross-platform)
|
||||||
|
specify init my-project --ai copilot --script ps
|
||||||
|
|
||||||
# Initialize in current directory
|
# Initialize in current directory
|
||||||
specify init --here --ai copilot
|
specify init --here --ai copilot
|
||||||
|
|
||||||
# Skip git initialization
|
# Skip git initialization
|
||||||
specify init my-project --ai gemini --no-git
|
specify init my-project --ai gemini --no-git
|
||||||
|
|
||||||
|
# Enable debug output for troubleshooting
|
||||||
|
specify init my-project --ai claude --debug
|
||||||
|
|
||||||
# Check system requirements
|
# Check system requirements
|
||||||
specify check
|
specify check
|
||||||
```
|
```
|
||||||
@@ -152,7 +170,7 @@ Our research and experimentation focus on:
|
|||||||
## 🔧 Prerequisites
|
## 🔧 Prerequisites
|
||||||
|
|
||||||
- **Linux/macOS** (or WSL2 on Windows)
|
- **Linux/macOS** (or WSL2 on Windows)
|
||||||
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), or [Gemini CLI](https://github.com/google-gemini/gemini-cli)
|
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Cursor](https://cursor.sh/), [Qwen CLI](https://github.com/QwenLM/qwen-code) or [opencode](https://opencode.ai/)
|
||||||
- [uv](https://docs.astral.sh/uv/) for package management
|
- [uv](https://docs.astral.sh/uv/) for package management
|
||||||
- [Python 3.11+](https://www.python.org/downloads/)
|
- [Python 3.11+](https://www.python.org/downloads/)
|
||||||
- [Git](https://git-scm.com/downloads)
|
- [Git](https://git-scm.com/downloads)
|
||||||
@@ -189,11 +207,13 @@ You will be prompted to select the AI agent you are using. You can also proactiv
|
|||||||
specify init <project_name> --ai claude
|
specify init <project_name> --ai claude
|
||||||
specify init <project_name> --ai gemini
|
specify init <project_name> --ai gemini
|
||||||
specify init <project_name> --ai copilot
|
specify init <project_name> --ai copilot
|
||||||
|
specify init <project_name> --ai qwen
|
||||||
|
specify init <project_name> --ai opencode
|
||||||
# Or in current directory:
|
# Or in current directory:
|
||||||
specify init --here --ai claude
|
specify init --here --ai claude
|
||||||
```
|
```
|
||||||
|
|
||||||
The CLI will check if you have Claude Code or Gemini CLI installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
The CLI will check if you have Claude Code, Gemini CLI, Qwen CLI or opencode installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify init <project_name> --ai claude --ignore-agent-tools
|
specify init <project_name> --ai claude --ignore-agent-tools
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Spec-Driven Development **flips the script** on traditional software development
|
|||||||
|
|
||||||
- [Installation Guide](installation.md)
|
- [Installation Guide](installation.md)
|
||||||
- [Quick Start Guide](quickstart.md)
|
- [Quick Start Guide](quickstart.md)
|
||||||
- [Local Development](local-development.md)
|
- [Local Development](local-development.md)
|
||||||
|
|
||||||
## Core Philosophy
|
## Core Philosophy
|
||||||
|
|
||||||
|
|||||||
BIN
media/spec-kit-video-header.jpg
Normal file
BIN
media/spec-kit-video-header.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@@ -1,85 +0,0 @@
|
|||||||
# Constitution Update Checklist
|
|
||||||
|
|
||||||
When amending the constitution (`/memory/constitution.md`), ensure all dependent documents are updated to maintain consistency.
|
|
||||||
|
|
||||||
## Templates to Update
|
|
||||||
|
|
||||||
### When adding/modifying ANY article:
|
|
||||||
- [ ] `/templates/plan-template.md` - Update Constitution Check section
|
|
||||||
- [ ] `/templates/spec-template.md` - Update if requirements/scope affected
|
|
||||||
- [ ] `/templates/tasks-template.md` - Update if new task types needed
|
|
||||||
- [ ] `/.claude/commands/plan.md` - Update if planning process changes
|
|
||||||
- [ ] `/.claude/commands/tasks.md` - Update if task generation affected
|
|
||||||
- [ ] `/CLAUDE.md` - Update runtime development guidelines
|
|
||||||
|
|
||||||
### Article-specific updates:
|
|
||||||
|
|
||||||
#### Article I (Library-First):
|
|
||||||
- [ ] Ensure templates emphasize library creation
|
|
||||||
- [ ] Update CLI command examples
|
|
||||||
- [ ] Add llms.txt documentation requirements
|
|
||||||
|
|
||||||
#### Article II (CLI Interface):
|
|
||||||
- [ ] Update CLI flag requirements in templates
|
|
||||||
- [ ] Add text I/O protocol reminders
|
|
||||||
|
|
||||||
#### Article III (Test-First):
|
|
||||||
- [ ] Update test order in all templates
|
|
||||||
- [ ] Emphasize TDD requirements
|
|
||||||
- [ ] Add test approval gates
|
|
||||||
|
|
||||||
#### Article IV (Integration Testing):
|
|
||||||
- [ ] List integration test triggers
|
|
||||||
- [ ] Update test type priorities
|
|
||||||
- [ ] Add real dependency requirements
|
|
||||||
|
|
||||||
#### Article V (Observability):
|
|
||||||
- [ ] Add logging requirements to templates
|
|
||||||
- [ ] Include multi-tier log streaming
|
|
||||||
- [ ] Update performance monitoring sections
|
|
||||||
|
|
||||||
#### Article VI (Versioning):
|
|
||||||
- [ ] Add version increment reminders
|
|
||||||
- [ ] Include breaking change procedures
|
|
||||||
- [ ] Update migration requirements
|
|
||||||
|
|
||||||
#### Article VII (Simplicity):
|
|
||||||
- [ ] Update project count limits
|
|
||||||
- [ ] Add pattern prohibition examples
|
|
||||||
- [ ] Include YAGNI reminders
|
|
||||||
|
|
||||||
## Validation Steps
|
|
||||||
|
|
||||||
1. **Before committing constitution changes:**
|
|
||||||
- [ ] All templates reference new requirements
|
|
||||||
- [ ] Examples updated to match new rules
|
|
||||||
- [ ] No contradictions between documents
|
|
||||||
|
|
||||||
2. **After updating templates:**
|
|
||||||
- [ ] Run through a sample implementation plan
|
|
||||||
- [ ] Verify all constitution requirements addressed
|
|
||||||
- [ ] Check that templates are self-contained (readable without constitution)
|
|
||||||
|
|
||||||
3. **Version tracking:**
|
|
||||||
- [ ] Update constitution version number
|
|
||||||
- [ ] Note version in template footers
|
|
||||||
- [ ] Add amendment to constitution history
|
|
||||||
|
|
||||||
## Common Misses
|
|
||||||
|
|
||||||
Watch for these often-forgotten updates:
|
|
||||||
- Command documentation (`/commands/*.md`)
|
|
||||||
- Checklist items in templates
|
|
||||||
- Example code/commands
|
|
||||||
- Domain-specific variations (web vs mobile vs CLI)
|
|
||||||
- Cross-references between documents
|
|
||||||
|
|
||||||
## Template Sync Status
|
|
||||||
|
|
||||||
Last sync check: 2025-07-16
|
|
||||||
- Constitution version: 2.1.1
|
|
||||||
- Templates aligned: ❌ (missing versioning, observability details)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*This checklist ensures the constitution's principles are consistently applied across all project documentation.*
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "specify-cli"
|
name = "specify-cli"
|
||||||
version = "0.0.3"
|
version = "0.0.6"
|
||||||
description = "Setup tool for Specify spec-driven development projects"
|
description = "Setup tool for Specify spec-driven development projects"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typer",
|
"typer",
|
||||||
"rich",
|
"rich",
|
||||||
"httpx",
|
"httpx[socks]",
|
||||||
"platformdirs",
|
"platformdirs",
|
||||||
"readchar",
|
"readchar",
|
||||||
"truststore>=0.10.4",
|
"truststore>=0.10.4",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
|
|||||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||||
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
|
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
|
||||||
NEW_PLAN="$FEATURE_DIR/plan.md"
|
NEW_PLAN="$FEATURE_DIR/plan.md"
|
||||||
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"
|
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"; CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"; QWEN_FILE="$REPO_ROOT/QWEN.md"; AGENTS_FILE="$REPO_ROOT/AGENTS.md"
|
||||||
AGENT_TYPE="$1"
|
AGENT_TYPE="$1"
|
||||||
[ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; }
|
[ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; }
|
||||||
echo "=== Updating agent context files for feature $CURRENT_BRANCH ==="
|
echo "=== Updating agent context files for feature $CURRENT_BRANCH ==="
|
||||||
@@ -13,7 +13,7 @@ NEW_FRAMEWORK=$(grep "^**Primary Dependencies**: " "$NEW_PLAN" 2>/dev/null | hea
|
|||||||
NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "")
|
NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "")
|
||||||
NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "")
|
NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "")
|
||||||
update_agent_file() { local target_file="$1" agent_name="$2"; echo "Updating $agent_name context file: $target_file"; local temp_file=$(mktemp); if [ ! -f "$target_file" ]; then
|
update_agent_file() { local target_file="$1" agent_name="$2"; echo "Updating $agent_name context file: $target_file"; local temp_file=$(mktemp); if [ ! -f "$target_file" ]; then
|
||||||
echo "Creating new $agent_name context file..."; if [ -f "$REPO_ROOT/templates/agent-file-template.md" ]; then cp "$REPO_ROOT/templates/agent-file-template.md" "$temp_file"; else echo "ERROR: Template not found"; return 1; fi;
|
echo "Creating new $agent_name context file..."; if [ -f "$REPO_ROOT/.specify/templates/agent-file-template.md" ]; then cp "$REPO_ROOT/.specify/templates/agent-file-template.md" "$temp_file"; else echo "ERROR: Template not found"; return 1; fi;
|
||||||
sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file"; sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file"; sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file";
|
sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file"; sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file"; sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file";
|
||||||
if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file"; else sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file"; fi;
|
if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file"; else sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file"; fi;
|
||||||
if [[ "$NEW_LANG" == *"Python"* ]]; then COMMANDS="cd src && pytest && ruff check ."; elif [[ "$NEW_LANG" == *"Rust"* ]]; then COMMANDS="cargo test && cargo clippy"; elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then COMMANDS="npm test && npm run lint"; else COMMANDS="# Add commands for $NEW_LANG"; fi; sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file";
|
if [[ "$NEW_LANG" == *"Python"* ]]; then COMMANDS="cd src && pytest && ruff check ."; elif [[ "$NEW_LANG" == *"Rust"* ]]; then COMMANDS="cargo test && cargo clippy"; elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then COMMANDS="npm test && npm run lint"; else COMMANDS="# Add commands for $NEW_LANG"; fi; sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file";
|
||||||
@@ -51,7 +51,16 @@ case "$AGENT_TYPE" in
|
|||||||
claude) update_agent_file "$CLAUDE_FILE" "Claude Code" ;;
|
claude) update_agent_file "$CLAUDE_FILE" "Claude Code" ;;
|
||||||
gemini) update_agent_file "$GEMINI_FILE" "Gemini CLI" ;;
|
gemini) update_agent_file "$GEMINI_FILE" "Gemini CLI" ;;
|
||||||
copilot) update_agent_file "$COPILOT_FILE" "GitHub Copilot" ;;
|
copilot) update_agent_file "$COPILOT_FILE" "GitHub Copilot" ;;
|
||||||
"") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; [ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; [ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
|
cursor) update_agent_file "$CURSOR_FILE" "Cursor IDE" ;;
|
||||||
*) echo "ERROR: Unknown agent type '$AGENT_TYPE'"; exit 1 ;;
|
qwen) update_agent_file "$QWEN_FILE" "Qwen Code" ;;
|
||||||
|
opencode) update_agent_file "$AGENTS_FILE" "opencode" ;;
|
||||||
|
"") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; \
|
||||||
|
[ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; \
|
||||||
|
[ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; \
|
||||||
|
[ -f "$CURSOR_FILE" ] && update_agent_file "$CURSOR_FILE" "Cursor IDE"; \
|
||||||
|
[ -f "$QWEN_FILE" ] && update_agent_file "$QWEN_FILE" "Qwen Code"; \
|
||||||
|
[ -f "$AGENTS_FILE" ] && update_agent_file "$AGENTS_FILE" "opencode"; \
|
||||||
|
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ] && [ ! -f "$QWEN_FILE" ] && [ ! -f "$AGENTS_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
|
||||||
|
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor|qwen|opencode)"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot]"
|
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode]"
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ if (-not (Test-Path $newPlan)) { Write-Error "ERROR: No plan.md found at $newPla
|
|||||||
$claudeFile = Join-Path $repoRoot 'CLAUDE.md'
|
$claudeFile = Join-Path $repoRoot 'CLAUDE.md'
|
||||||
$geminiFile = Join-Path $repoRoot 'GEMINI.md'
|
$geminiFile = Join-Path $repoRoot 'GEMINI.md'
|
||||||
$copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
|
$copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
|
||||||
|
$cursorFile = Join-Path $repoRoot '.cursor/rules/specify-rules.mdc'
|
||||||
|
$qwenFile = Join-Path $repoRoot 'QWEN.md'
|
||||||
|
$agentsFile = Join-Path $repoRoot 'AGENTS.md'
|
||||||
|
|
||||||
Write-Output "=== Updating agent context files for feature $currentBranch ==="
|
Write-Output "=== Updating agent context files for feature $currentBranch ==="
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ $newProjectType = Get-PlanValue 'Project Type'
|
|||||||
|
|
||||||
function Initialize-AgentFile($targetFile, $agentName) {
|
function Initialize-AgentFile($targetFile, $agentName) {
|
||||||
if (Test-Path $targetFile) { return }
|
if (Test-Path $targetFile) { return }
|
||||||
$template = Join-Path $repoRoot 'templates/agent-file-template.md'
|
$template = Join-Path $repoRoot '.specify/templates/agent-file-template.md'
|
||||||
if (-not (Test-Path $template)) { Write-Error "Template not found: $template"; return }
|
if (-not (Test-Path $template)) { Write-Error "Template not found: $template"; return }
|
||||||
$content = Get-Content $template -Raw
|
$content = Get-Content $template -Raw
|
||||||
$content = $content.Replace('[PROJECT NAME]', (Split-Path $repoRoot -Leaf))
|
$content = $content.Replace('[PROJECT NAME]', (Split-Path $repoRoot -Leaf))
|
||||||
@@ -43,8 +46,8 @@ function Initialize-AgentFile($targetFile, $agentName) {
|
|||||||
elseif ($newLang -match 'JavaScript|TypeScript') { $commands = 'npm test && npm run lint' }
|
elseif ($newLang -match 'JavaScript|TypeScript') { $commands = 'npm test && npm run lint' }
|
||||||
else { $commands = "# Add commands for $newLang" }
|
else { $commands = "# Add commands for $newLang" }
|
||||||
$content = $content.Replace('[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]', $commands)
|
$content = $content.Replace('[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]', $commands)
|
||||||
$content = $content.Replace('[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]', "$newLang: Follow standard conventions")
|
$content = $content.Replace('[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]', "${newLang}: Follow standard conventions")
|
||||||
$content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- $currentBranch: Added $newLang + $newFramework")
|
$content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- ${currentBranch}: Added ${newLang} + ${newFramework}")
|
||||||
$content | Set-Content $targetFile -Encoding UTF8
|
$content | Set-Content $targetFile -Encoding UTF8
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +58,7 @@ function Update-AgentFile($targetFile, $agentName) {
|
|||||||
if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($currentBranch)`n" }
|
if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($currentBranch)`n" }
|
||||||
if ($content -match '## Recent Changes\n([\s\S]*?)(\n\n|$)') {
|
if ($content -match '## Recent Changes\n([\s\S]*?)(\n\n|$)') {
|
||||||
$changesBlock = $matches[1].Trim().Split("`n")
|
$changesBlock = $matches[1].Trim().Split("`n")
|
||||||
$changesBlock = ,"- $currentBranch: Added $newLang + $newFramework" + $changesBlock
|
$changesBlock = ,"- ${currentBranch}: Added ${newLang} + ${newFramework}" + $changesBlock
|
||||||
$changesBlock = $changesBlock | Where-Object { $_ } | Select-Object -First 3
|
$changesBlock = $changesBlock | Where-Object { $_ } | Select-Object -First 3
|
||||||
$joined = ($changesBlock -join "`n")
|
$joined = ($changesBlock -join "`n")
|
||||||
$content = [regex]::Replace($content, '## Recent Changes\n([\s\S]*?)(\n\n|$)', "## Recent Changes`n$joined`n`n")
|
$content = [regex]::Replace($content, '## Recent Changes\n([\s\S]*?)(\n\n|$)', "## Recent Changes`n$joined`n`n")
|
||||||
@@ -69,16 +72,26 @@ switch ($AgentType) {
|
|||||||
'claude' { Update-AgentFile $claudeFile 'Claude Code' }
|
'claude' { Update-AgentFile $claudeFile 'Claude Code' }
|
||||||
'gemini' { Update-AgentFile $geminiFile 'Gemini CLI' }
|
'gemini' { Update-AgentFile $geminiFile 'Gemini CLI' }
|
||||||
'copilot' { Update-AgentFile $copilotFile 'GitHub Copilot' }
|
'copilot' { Update-AgentFile $copilotFile 'GitHub Copilot' }
|
||||||
|
'cursor' { Update-AgentFile $cursorFile 'Cursor IDE' }
|
||||||
|
'qwen' { Update-AgentFile $qwenFile 'Qwen Code' }
|
||||||
|
'opencode' { Update-AgentFile $agentsFile 'opencode' }
|
||||||
'' {
|
'' {
|
||||||
foreach ($pair in @(@{file=$claudeFile; name='Claude Code'}, @{file=$geminiFile; name='Gemini CLI'}, @{file=$copilotFile; name='GitHub Copilot'})) {
|
foreach ($pair in @(
|
||||||
|
@{file=$claudeFile; name='Claude Code'},
|
||||||
|
@{file=$geminiFile; name='Gemini CLI'},
|
||||||
|
@{file=$copilotFile; name='GitHub Copilot'},
|
||||||
|
@{file=$cursorFile; name='Cursor IDE'},
|
||||||
|
@{file=$qwenFile; name='Qwen Code'},
|
||||||
|
@{file=$agentsFile; name='opencode'}
|
||||||
|
)) {
|
||||||
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
|
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
|
||||||
}
|
}
|
||||||
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile)) {
|
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile) -and -not (Test-Path $qwenFile) -and -not (Test-Path $agentsFile)) {
|
||||||
Write-Output 'No agent context files found. Creating Claude Code context file by default.'
|
Write-Output 'No agent context files found. Creating Claude Code context file by default.'
|
||||||
Update-AgentFile $claudeFile 'Claude Code'
|
Update-AgentFile $claudeFile 'Claude Code'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, or leave empty for all."; exit 1 }
|
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor, qwen, opencode or leave empty for all."; exit 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Output ''
|
Write-Output ''
|
||||||
@@ -88,4 +101,4 @@ if ($newFramework) { Write-Output "- Added framework: $newFramework" }
|
|||||||
if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" }
|
if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" }
|
||||||
|
|
||||||
Write-Output ''
|
Write-Output ''
|
||||||
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot]'
|
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor|qwen|opencode]'
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
## The Power Inversion
|
## The Power Inversion
|
||||||
|
|
||||||
For decades, code has been king. Specifications served code—they were the scaffolding we built and then discarded once the "real work" of coding began. We wrote PRDs to guide development, created design docs to inform implementation, drew diagrams to visualize architecture. But these were always subordinate to the code itself. Code was truth. Everything else was, at best, good intentions. Code was the source of truth, as it moved forward, and spec's rarely kept pace. As the asset (code) and the implementation are one, it's not easy to have a parallel implementation without trying to build from the code.
|
For decades, code has been king. Specifications served code—they were the scaffolding we built and then discarded once the "real work" of coding began. We wrote PRDs to guide development, created design docs to inform implementation, drew diagrams to visualize architecture. But these were always subordinate to the code itself. Code was truth. Everything else was, at best, good intentions. Code was the source of truth, and as it moved forward, specs rarely kept pace. As the asset (code) and the implementation are one, it's not easy to have a parallel implementation without trying to build from the code.
|
||||||
|
|
||||||
Spec-Driven Development (SDD) inverts this power structure. Specifications don't serve code—code serves specifications. The (Product Requirements Document-Specification) PRD isn't a guide for implementation; it's the source that generates implementation. Technical plans aren't documents that inform coding; they're precise definitions that produce code. This isn't an incremental improvement to how we build software. It's a fundamental rethinking of what drives development.
|
Spec-Driven Development (SDD) inverts this power structure. Specifications don't serve code—code serves specifications. The Product Requirements Document (PRD) isn't a guide for implementation; it's the source that generates implementation. Technical plans aren't documents that inform coding; they're precise definitions that produce code. This isn't an incremental improvement to how we build software. It's a fundamental rethinking of what drives development.
|
||||||
|
|
||||||
The gap between specification and implementation has plagued software development since its inception. We've tried to bridge it with better documentation, more detailed requirements, stricter processes. These approaches fail because they accept the gap as inevitable. They try to narrow it but never eliminate it. SDD eliminates the gap by making specifications or and their concrete implementation plans born from the specification executable. When specifications to implementation plans generate code, there is no gap—only transformation.
|
The gap between specification and implementation has plagued software development since its inception. We've tried to bridge it with better documentation, more detailed requirements, stricter processes. These approaches fail because they accept the gap as inevitable. They try to narrow it but never eliminate it. SDD eliminates the gap by making specifications and their concrete implementation plans born from the specification executable. When specifications and implementation plans generate code, there is no gap—only transformation.
|
||||||
|
|
||||||
This transformation is now possible because AI can understand and implement complex specifications, and create detailed implementation plans. But raw AI generation without structure produces chaos. SDD provides that structure through specifications and subsequent implementation plans that are precise, complete, and unambiguous enough to generate working systems. The specification becomes the primary artifact. Code becomes its expression (as an implementation from the implementation plan) in a particular language and framework.
|
This transformation is now possible because AI can understand and implement complex specifications, and create detailed implementation plans. But raw AI generation without structure produces chaos. SDD provides that structure through specifications and subsequent implementation plans that are precise, complete, and unambiguous enough to generate working systems. The specification becomes the primary artifact. Code becomes its expression (as an implementation from the implementation plan) in a particular language and framework.
|
||||||
|
|
||||||
In this new world, maintaining software means evolving specifications. The intent of the development team is expressed in natural language ("**intent-driven development**"), design assets, core principles and other guidelines . The **lingua franca** of development moves to a higher-level, and code is the last-mile approach.
|
In this new world, maintaining software means evolving specifications. The intent of the development team is expressed in natural language ("**intent-driven development**"), design assets, core principles and other guidelines. The **lingua franca** of development moves to a higher level, and code is the last-mile approach.
|
||||||
|
|
||||||
Debugging means fixing specifications and their implementation plans that generate incorrect code. Refactoring means restructuring for clarity. The entire development workflow reorganizes around specifications as the central source of truth, with implementation plans and code as the continuously regenerated output. Updating apps with new features or creating a new parallel implementation because we are creative beings, means revisiting the specification and creating new implementation plans. This process is therefore a 0 -> 1, (1', ..), 2, 3, N.
|
Debugging means fixing specifications and their implementation plans that generate incorrect code. Refactoring means restructuring for clarity. The entire development workflow reorganizes around specifications as the central source of truth, with implementation plans and code as the continuously regenerated output. Updating apps with new features or creating a new parallel implementation because we are creative beings, means revisiting the specification and creating new implementation plans. This process is therefore a 0 -> 1, (1', ..), 2, 3, N.
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ The development team focuses in on their creativity, experimentation, their crit
|
|||||||
|
|
||||||
## The SDD Workflow in Practice
|
## The SDD Workflow in Practice
|
||||||
|
|
||||||
The workflow begins with an idea—often vague and incomplete. Through iterative dialogue with AI, this idea becomes a comprehensive PRD. The AI asks clarifying questions, identifies edge cases, and helps define precise acceptance criteria. What might take days of meetings and documentation in traditional development happens in hours of focused specification work. This transforms the traditional SDLC—requirements and design become continuous activities rather than discrete phases. This is supportive of a **team process**, that's team reviewed-specifications are expressed and versioned, created in branches, and merged.
|
The workflow begins with an idea—often vague and incomplete. Through iterative dialogue with AI, this idea becomes a comprehensive PRD. The AI asks clarifying questions, identifies edge cases, and helps define precise acceptance criteria. What might take days of meetings and documentation in traditional development happens in hours of focused specification work. This transforms the traditional SDLC—requirements and design become continuous activities rather than discrete phases. This is supportive of a **team process**, where team-reviewed specifications are expressed and versioned, created in branches, and merged.
|
||||||
|
|
||||||
When a product manager updates acceptance criteria, implementation plans automatically flag affected technical decisions. When an architect discovers a better pattern, the PRD updates to reflect new possibilities.
|
When a product manager updates acceptance criteria, implementation plans automatically flag affected technical decisions. When an architect discovers a better pattern, the PRD updates to reflect new possibilities.
|
||||||
|
|
||||||
@@ -34,13 +34,13 @@ The feedback loop extends beyond initial development. Production metrics and inc
|
|||||||
|
|
||||||
Three trends make SDD not just possible but necessary:
|
Three trends make SDD not just possible but necessary:
|
||||||
|
|
||||||
First, AI capabilities have reached a threshold where natural language specifications can reliably generate working code. This isn't about replacing developers—it's about amplifying their effectiveness by automating the mechanical translation from specification to implementation. It can amplify exploration and creativity, it can support "start-over" easily, it supports addition subtraction and critical thinking.
|
First, AI capabilities have reached a threshold where natural language specifications can reliably generate working code. This isn't about replacing developers—it's about amplifying their effectiveness by automating the mechanical translation from specification to implementation. It can amplify exploration and creativity, support "start-over" easily, and support addition, subtraction, and critical thinking.
|
||||||
|
|
||||||
Second, software complexity continues to grow exponentially. Modern systems integrate dozens of services, frameworks, and dependencies. Keeping all these pieces aligned with original intent through manual processes becomes increasingly difficult. SDD provides systematic alignment through specification-driven generation. Frameworks may evolve to provide AI-first support, not human-first support, or architect around reusable components.
|
Second, software complexity continues to grow exponentially. Modern systems integrate dozens of services, frameworks, and dependencies. Keeping all these pieces aligned with original intent through manual processes becomes increasingly difficult. SDD provides systematic alignment through specification-driven generation. Frameworks may evolve to provide AI-first support, not human-first support, or architect around reusable components.
|
||||||
|
|
||||||
Third, the pace of change accelerates. Requirements change far more rapidly today than ever before. Pivoting is no longer exceptional—it's expected. Modern product development demands rapid iteration based on user feedback, market conditions, and competitive pressures. Traditional development treats these changes as disruptions. Each pivot requires manually propagating changes through documentation, design, and code. The result is either slow, careful updates that limit velocity, or fast, reckless changes that accumulate technical debt.
|
Third, the pace of change accelerates. Requirements change far more rapidly today than ever before. Pivoting is no longer exceptional—it's expected. Modern product development demands rapid iteration based on user feedback, market conditions, and competitive pressures. Traditional development treats these changes as disruptions. Each pivot requires manually propagating changes through documentation, design, and code. The result is either slow, careful updates that limit velocity, or fast, reckless changes that accumulate technical debt.
|
||||||
|
|
||||||
SDD can support what-if/simulation experiments, "If we need to re-implement or change the application to promote a business need to sell more T-shirts, how would we implement and experiment for that?".
|
SDD can support what-if/simulation experiments: "If we need to re-implement or change the application to promote a business need to sell more T-shirts, how would we implement and experiment for that?"
|
||||||
|
|
||||||
SDD transforms requirement changes from obstacles into normal workflow. When specifications drive implementation, pivots become systematic regenerations rather than manual rewrites. Change a core requirement in the PRD, and affected implementation plans update automatically. Modify a user story, and corresponding API endpoints regenerate. This isn't just about initial development—it's about maintaining engineering velocity through inevitable changes.
|
SDD transforms requirement changes from obstacles into normal workflow. When specifications drive implementation, pivots become systematic regenerations rather than manual rewrites. Change a core requirement in the PRD, and affected implementation plans update automatically. Modify a user story, and corresponding API endpoints regenerate. This isn't just about initial development—it's about maintaining engineering velocity through inevitable changes.
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ client = httpx.Client(verify=ssl_context)
|
|||||||
AI_CHOICES = {
|
AI_CHOICES = {
|
||||||
"copilot": "GitHub Copilot",
|
"copilot": "GitHub Copilot",
|
||||||
"claude": "Claude Code",
|
"claude": "Claude Code",
|
||||||
"gemini": "Gemini CLI"
|
"gemini": "Gemini CLI",
|
||||||
|
"cursor": "Cursor",
|
||||||
|
"qwen": "Qwen Code",
|
||||||
|
"opencode": "opencode"
|
||||||
}
|
}
|
||||||
# Add script type choices
|
# Add script type choices
|
||||||
SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
|
SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
|
||||||
@@ -721,7 +724,7 @@ def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None =
|
|||||||
@app.command()
|
@app.command()
|
||||||
def init(
|
def init(
|
||||||
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here)"),
|
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here)"),
|
||||||
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, or copilot"),
|
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, qwen or opencode"),
|
||||||
script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"),
|
script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"),
|
||||||
ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"),
|
ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"),
|
||||||
no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"),
|
no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"),
|
||||||
@@ -734,7 +737,7 @@ def init(
|
|||||||
|
|
||||||
This command will:
|
This command will:
|
||||||
1. Check that required tools are installed (git is optional)
|
1. Check that required tools are installed (git is optional)
|
||||||
2. Let you choose your AI assistant (Claude Code, Gemini CLI, or GitHub Copilot)
|
2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, Cursor, Qwen Code or opencode)
|
||||||
3. Download the appropriate template from GitHub
|
3. Download the appropriate template from GitHub
|
||||||
4. Extract the template to a new project directory or current directory
|
4. Extract the template to a new project directory or current directory
|
||||||
5. Initialize a fresh git repository (if not --no-git and no existing repo)
|
5. Initialize a fresh git repository (if not --no-git and no existing repo)
|
||||||
@@ -745,6 +748,9 @@ def init(
|
|||||||
specify init my-project --ai claude
|
specify init my-project --ai claude
|
||||||
specify init my-project --ai gemini
|
specify init my-project --ai gemini
|
||||||
specify init my-project --ai copilot --no-git
|
specify init my-project --ai copilot --no-git
|
||||||
|
specify init my-project --ai cursor
|
||||||
|
specify init my-project --ai qwen
|
||||||
|
specify init my-project --ai opencode
|
||||||
specify init --ignore-agent-tools my-project
|
specify init --ignore-agent-tools my-project
|
||||||
specify init --here --ai claude
|
specify init --here --ai claude
|
||||||
specify init --here
|
specify init --here
|
||||||
@@ -792,10 +798,11 @@ def init(
|
|||||||
))
|
))
|
||||||
|
|
||||||
# Check git only if we might need it (not --no-git)
|
# Check git only if we might need it (not --no-git)
|
||||||
git_available = True
|
# Only set to True if the user wants it and the tool is available
|
||||||
|
should_init_git = False
|
||||||
if not no_git:
|
if not no_git:
|
||||||
git_available = check_tool("git", "https://git-scm.com/downloads")
|
should_init_git = check_tool("git", "https://git-scm.com/downloads")
|
||||||
if not git_available:
|
if not should_init_git:
|
||||||
console.print("[yellow]Git not found - will skip repository initialization[/yellow]")
|
console.print("[yellow]Git not found - will skip repository initialization[/yellow]")
|
||||||
|
|
||||||
# AI assistant selection
|
# AI assistant selection
|
||||||
@@ -823,8 +830,16 @@ def init(
|
|||||||
if not check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli"):
|
if not check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli"):
|
||||||
console.print("[red]Error:[/red] Gemini CLI is required for Gemini projects")
|
console.print("[red]Error:[/red] Gemini CLI is required for Gemini projects")
|
||||||
agent_tool_missing = True
|
agent_tool_missing = True
|
||||||
# GitHub Copilot check is not needed as it's typically available in supported IDEs
|
elif selected_ai == "qwen":
|
||||||
|
if not check_tool("qwen", "Install from: https://github.com/QwenLM/qwen-code"):
|
||||||
|
console.print("[red]Error:[/red] Qwen CLI is required for Qwen Code projects")
|
||||||
|
agent_tool_missing = True
|
||||||
|
elif selected_ai == "opencode":
|
||||||
|
if not check_tool("opencode", "Install from: https://opencode.ai"):
|
||||||
|
console.print("[red]Error:[/red] opencode CLI is required for opencode projects")
|
||||||
|
agent_tool_missing = True
|
||||||
|
# GitHub Copilot and Cursor checks are not needed as they're typically available in supported IDEs
|
||||||
|
|
||||||
if agent_tool_missing:
|
if agent_tool_missing:
|
||||||
console.print("\n[red]Required AI tool is missing![/red]")
|
console.print("\n[red]Required AI tool is missing![/red]")
|
||||||
console.print("[yellow]Tip:[/yellow] Use --ignore-agent-tools to skip this check")
|
console.print("[yellow]Tip:[/yellow] Use --ignore-agent-tools to skip this check")
|
||||||
@@ -892,7 +907,7 @@ def init(
|
|||||||
tracker.start("git")
|
tracker.start("git")
|
||||||
if is_git_repo(project_path):
|
if is_git_repo(project_path):
|
||||||
tracker.complete("git", "existing repo detected")
|
tracker.complete("git", "existing repo detected")
|
||||||
elif git_available:
|
elif should_init_git:
|
||||||
if init_git_repo(project_path, quiet=True):
|
if init_git_repo(project_path, quiet=True):
|
||||||
tracker.complete("git", "initialized")
|
tracker.complete("git", "initialized")
|
||||||
else:
|
else:
|
||||||
@@ -949,6 +964,17 @@ def init(
|
|||||||
steps_lines.append(" - See GEMINI.md for all available commands")
|
steps_lines.append(" - See GEMINI.md for all available commands")
|
||||||
elif selected_ai == "copilot":
|
elif selected_ai == "copilot":
|
||||||
steps_lines.append(f"{step_num}. Open in Visual Studio Code and use [bold cyan]/specify[/], [bold cyan]/plan[/], [bold cyan]/tasks[/] commands with GitHub Copilot")
|
steps_lines.append(f"{step_num}. Open in Visual Studio Code and use [bold cyan]/specify[/], [bold cyan]/plan[/], [bold cyan]/tasks[/] commands with GitHub Copilot")
|
||||||
|
elif selected_ai == "qwen":
|
||||||
|
steps_lines.append(f"{step_num}. Use / commands with Qwen CLI")
|
||||||
|
steps_lines.append(" - Run qwen /specify to create specifications")
|
||||||
|
steps_lines.append(" - Run qwen /plan to create implementation plans")
|
||||||
|
steps_lines.append(" - Run qwen /tasks to generate tasks")
|
||||||
|
steps_lines.append(" - See QWEN.md for all available commands")
|
||||||
|
elif selected_ai == "opencode":
|
||||||
|
steps_lines.append(f"{step_num}. Use / commands with opencode")
|
||||||
|
steps_lines.append(" - Use /specify to create specifications")
|
||||||
|
steps_lines.append(" - Use /plan to create implementation plans")
|
||||||
|
steps_lines.append(" - Use /tasks to generate tasks")
|
||||||
|
|
||||||
# Removed script variant step (scripts are transparent to users)
|
# Removed script variant step (scripts are transparent to users)
|
||||||
step_num += 1
|
step_num += 1
|
||||||
@@ -974,11 +1000,22 @@ def check():
|
|||||||
tracker.add("git", "Git version control")
|
tracker.add("git", "Git version control")
|
||||||
tracker.add("claude", "Claude Code CLI")
|
tracker.add("claude", "Claude Code CLI")
|
||||||
tracker.add("gemini", "Gemini CLI")
|
tracker.add("gemini", "Gemini CLI")
|
||||||
|
tracker.add("qwen", "Qwen Code CLI")
|
||||||
|
tracker.add("code", "VS Code (for GitHub Copilot)")
|
||||||
|
tracker.add("cursor-agent", "Cursor IDE agent (optional)")
|
||||||
|
tracker.add("opencode", "opencode")
|
||||||
|
|
||||||
# Check each tool
|
# Check each tool
|
||||||
git_ok = check_tool_for_tracker("git", "https://git-scm.com/downloads", tracker)
|
git_ok = check_tool_for_tracker("git", "https://git-scm.com/downloads", tracker)
|
||||||
claude_ok = check_tool_for_tracker("claude", "https://docs.anthropic.com/en/docs/claude-code/setup", tracker)
|
claude_ok = check_tool_for_tracker("claude", "https://docs.anthropic.com/en/docs/claude-code/setup", tracker)
|
||||||
gemini_ok = check_tool_for_tracker("gemini", "https://github.com/google-gemini/gemini-cli", tracker)
|
gemini_ok = check_tool_for_tracker("gemini", "https://github.com/google-gemini/gemini-cli", tracker)
|
||||||
|
qwen_ok = check_tool_for_tracker("qwen", "https://github.com/QwenLM/qwen-code", tracker)
|
||||||
|
# Check for VS Code (code or code-insiders)
|
||||||
|
code_ok = check_tool_for_tracker("code", "https://code.visualstudio.com/", tracker)
|
||||||
|
if not code_ok:
|
||||||
|
code_ok = check_tool_for_tracker("code-insiders", "https://code.visualstudio.com/insiders/", tracker)
|
||||||
|
cursor_ok = check_tool_for_tracker("cursor-agent", "https://cursor.sh/", tracker)
|
||||||
|
opencode_ok = check_tool_for_tracker("opencode", "https://opencode.ai/", tracker)
|
||||||
|
|
||||||
# Render the final tree
|
# Render the final tree
|
||||||
console.print(tracker.render())
|
console.print(tracker.render())
|
||||||
@@ -989,7 +1026,7 @@ def check():
|
|||||||
# Recommendations
|
# Recommendations
|
||||||
if not git_ok:
|
if not git_ok:
|
||||||
console.print("[dim]Tip: Install git for repository management[/dim]")
|
console.print("[dim]Tip: Install git for repository management[/dim]")
|
||||||
if not (claude_ok or gemini_ok):
|
if not (claude_ok or gemini_ok or cursor_ok or qwen_ok or opencode_ok):
|
||||||
console.print("[dim]Tip: Install an AI assistant for the best experience[/dim]")
|
console.print("[dim]Tip: Install an AI assistant for the best experience[/dim]")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
68
templates/commands/constitution.md
Normal file
68
templates/commands/constitution.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
description: Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync.
|
||||||
|
# (No scripts section: constitution edits are manual authoring assisted by the agent)
|
||||||
|
---
|
||||||
|
|
||||||
|
You are updating the project constitution at `/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.
|
||||||
|
|
||||||
|
Follow this execution flow:
|
||||||
|
|
||||||
|
1. Load the existing constitution template at `/memory/constitution.md`.
|
||||||
|
- Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
|
||||||
|
**IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.
|
||||||
|
|
||||||
|
2. Collect/derive values for placeholders:
|
||||||
|
- If user input (conversation) supplies a value, use it.
|
||||||
|
- Otherwise infer from existing repo context (README, docs, prior constitution versions if embedded).
|
||||||
|
- For governance dates: `RATIFICATION_DATE` is the original adoption date (if unknown ask or mark TODO), `LAST_AMENDED_DATE` is today if changes are made, otherwise keep previous.
|
||||||
|
- `CONSTITUTION_VERSION` must increment according to semantic versioning rules:
|
||||||
|
* MAJOR: Backward incompatible governance/principle removals or redefinitions.
|
||||||
|
* MINOR: New principle/section added or materially expanded guidance.
|
||||||
|
* PATCH: Clarifications, wording, typo fixes, non-semantic refinements.
|
||||||
|
- If version bump type ambiguous, propose reasoning before finalizing.
|
||||||
|
|
||||||
|
3. Draft the updated constitution content:
|
||||||
|
- Replace every placeholder with concrete text (no bracketed tokens left except intentionally retained template slots that the project has chosen not to define yet—explicitly justify any left).
|
||||||
|
- Preserve heading hierarchy and comments can be removed once replaced unless they still add clarifying guidance.
|
||||||
|
- Ensure each Principle section: succinct name line, paragraph (or bullet list) capturing non‑negotiable rules, explicit rationale if not obvious.
|
||||||
|
- Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.
|
||||||
|
|
||||||
|
4. Consistency propagation checklist (convert prior checklist into active validations):
|
||||||
|
- Read `/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
|
||||||
|
- Read `/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
|
||||||
|
- Read `/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
|
||||||
|
- Read each command file in `/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
|
||||||
|
- Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.
|
||||||
|
|
||||||
|
5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
|
||||||
|
- Version change: old → new
|
||||||
|
- List of modified principles (old title → new title if renamed)
|
||||||
|
- Added sections
|
||||||
|
- Removed sections
|
||||||
|
- Templates requiring updates (✅ updated / ⚠ pending) with file paths
|
||||||
|
- Follow-up TODOs if any placeholders intentionally deferred.
|
||||||
|
|
||||||
|
6. Validation before final output:
|
||||||
|
- No remaining unexplained bracket tokens.
|
||||||
|
- Version line matches report.
|
||||||
|
- Dates ISO format YYYY-MM-DD.
|
||||||
|
- Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).
|
||||||
|
|
||||||
|
7. Write the completed constitution back to `/memory/constitution.md` (overwrite).
|
||||||
|
|
||||||
|
8. Output a final summary to the user with:
|
||||||
|
- New version and bump rationale.
|
||||||
|
- Any files flagged for manual follow-up.
|
||||||
|
- Suggested commit message (e.g., `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).
|
||||||
|
|
||||||
|
Formatting & Style Requirements:
|
||||||
|
- Use Markdown headings exactly as in the template (do not demote/promote levels).
|
||||||
|
- Wrap long rationale lines to keep readability (<100 chars ideally) but do not hard enforce with awkward breaks.
|
||||||
|
- Keep a single blank line between sections.
|
||||||
|
- Avoid trailing whitespace.
|
||||||
|
|
||||||
|
If the user supplies partial updates (e.g., only one principle revision), still perform validation and version decision steps.
|
||||||
|
|
||||||
|
If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.
|
||||||
|
|
||||||
|
Do not create a new template; always operate on the existing `/memory/constitution.md` file.
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
---
|
---
|
||||||
description: Execute the implementation planning workflow using the plan template to generate design artifacts.
|
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 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 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:
|
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:
|
2. Read and analyze the feature specification to understand:
|
||||||
- The feature requirements and user stories
|
- The feature requirements and user stories
|
||||||
- Functional and non-functional requirements
|
- Functional and non-functional requirements
|
||||||
@@ -18,7 +19,7 @@ Given the implementation details provided as an argument, do this:
|
|||||||
4. Execute the implementation plan template:
|
4. Execute the implementation plan template:
|
||||||
- Load `/templates/plan-template.md` (already copied to IMPL_PLAN path)
|
- Load `/templates/plan-template.md` (already copied to IMPL_PLAN path)
|
||||||
- Set Input path to FEATURE_SPEC
|
- Set Input path to FEATURE_SPEC
|
||||||
- Run the Execution Flow (main) function steps 1-10
|
- Run the Execution Flow (main) function steps 1-9
|
||||||
- The template is self-contained and executable
|
- The template is self-contained and executable
|
||||||
- Follow error handling and gate checks as specified
|
- Follow error handling and gate checks as specified
|
||||||
- Let the template guide artifact generation in $SPECS_DIR:
|
- Let the template guide artifact generation in $SPECS_DIR:
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
---
|
---
|
||||||
description: Create or update the feature specification from a natural language feature description.
|
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 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 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:
|
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.
|
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.
|
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.
|
4. Report completion with branch name, spec file path, and readiness for the next phase.
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
---
|
---
|
||||||
description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
|
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 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 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:
|
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:
|
2. Load and analyze available design documents:
|
||||||
- Always read plan.md for tech stack and libraries
|
- Always read plan.md for tech stack and libraries
|
||||||
- IF EXISTS: Read data-model.md for entities
|
- IF EXISTS: Read data-model.md for entities
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
# Implementation Plan: [FEATURE]
|
---
|
||||||
|
description: "Implementation plan template for feature development"
|
||||||
|
scripts:
|
||||||
|
sh: scripts/bash/update-agent-context.sh __AGENT__
|
||||||
|
ps: scripts/powershell/update-agent-context.ps1 -AgentType __AGENT__
|
||||||
|
---
|
||||||
|
|
||||||
<!-- VARIANT:sh - Run `/scripts/bash/update-agent-context.sh __AGENT__` for your AI assistant -->
|
# Implementation Plan: [FEATURE]
|
||||||
<!-- VARIANT:ps - Run `/scripts/powershell/update-agent-context.ps1 -AgentType __AGENT__` for your AI assistant -->
|
|
||||||
|
|
||||||
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
|
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
|
||||||
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
|
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
|
||||||
@@ -13,18 +17,19 @@
|
|||||||
2. Fill Technical Context (scan for NEEDS CLARIFICATION)
|
2. Fill Technical Context (scan for NEEDS CLARIFICATION)
|
||||||
→ Detect Project Type from context (web=frontend+backend, mobile=app+api)
|
→ Detect Project Type from context (web=frontend+backend, mobile=app+api)
|
||||||
→ Set Structure Decision based on project type
|
→ Set Structure Decision based on project type
|
||||||
3. Evaluate Constitution Check section below
|
3. Fill the Constitution Check section based on the content of the constitution document.
|
||||||
|
4. Evaluate Constitution Check section below
|
||||||
→ If violations exist: Document in Complexity Tracking
|
→ If violations exist: Document in Complexity Tracking
|
||||||
→ If no justification possible: ERROR "Simplify approach first"
|
→ If no justification possible: ERROR "Simplify approach first"
|
||||||
→ Update Progress Tracking: Initial Constitution Check
|
→ Update Progress Tracking: Initial Constitution Check
|
||||||
4. Execute Phase 0 → research.md
|
5. Execute Phase 0 → research.md
|
||||||
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
|
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
|
||||||
5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI).
|
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, `QWEN.md` for Qwen Code or `AGENTS.md` for opencode).
|
||||||
6. Re-evaluate Constitution Check section
|
7. Re-evaluate Constitution Check section
|
||||||
→ If new violations: Refactor design, return to Phase 1
|
→ If new violations: Refactor design, return to Phase 1
|
||||||
→ Update Progress Tracking: Post-Design Constitution Check
|
→ Update Progress Tracking: Post-Design Constitution Check
|
||||||
7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
|
8. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
|
||||||
8. STOP - Ready for /tasks command
|
9. STOP - Ready for /tasks command
|
||||||
```
|
```
|
||||||
|
|
||||||
**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
|
**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
|
||||||
@@ -48,35 +53,7 @@
|
|||||||
## Constitution Check
|
## Constitution Check
|
||||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||||
|
|
||||||
**Simplicity**:
|
[Gates determined based on constitution file]
|
||||||
- Projects: [#] (max 3 - e.g., api, cli, tests)
|
|
||||||
- Using framework directly? (no wrapper classes)
|
|
||||||
- Single data model? (no DTOs unless serialization differs)
|
|
||||||
- Avoiding patterns? (no Repository/UoW without proven need)
|
|
||||||
|
|
||||||
**Architecture**:
|
|
||||||
- EVERY feature as library? (no direct app code)
|
|
||||||
- Libraries listed: [name + purpose for each]
|
|
||||||
- CLI per library: [commands with --help/--version/--format]
|
|
||||||
- Library docs: llms.txt format planned?
|
|
||||||
|
|
||||||
**Testing (NON-NEGOTIABLE)**:
|
|
||||||
- RED-GREEN-Refactor cycle enforced? (test MUST fail first)
|
|
||||||
- Git commits show tests before implementation?
|
|
||||||
- Order: Contract→Integration→E2E→Unit strictly followed?
|
|
||||||
- Real dependencies used? (actual DBs, not mocks)
|
|
||||||
- Integration tests for: new libraries, contract changes, shared schemas?
|
|
||||||
- FORBIDDEN: Implementation before test, skipping RED phase
|
|
||||||
|
|
||||||
**Observability**:
|
|
||||||
- Structured logging included?
|
|
||||||
- Frontend logs → backend? (unified stream)
|
|
||||||
- Error context sufficient?
|
|
||||||
|
|
||||||
**Versioning**:
|
|
||||||
- Version number assigned? (MAJOR.MINOR.BUILD)
|
|
||||||
- BUILD increments on every change?
|
|
||||||
- Breaking changes handled? (parallel tests, migration plan)
|
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
@@ -174,7 +151,7 @@ ios/ or android/
|
|||||||
- Quickstart test = story validation steps
|
- Quickstart test = story validation steps
|
||||||
|
|
||||||
5. **Update agent file incrementally** (O(1) operation):
|
5. **Update agent file incrementally** (O(1) operation):
|
||||||
VARIANT-INJECT
|
- Run `{SCRIPT}` for your AI assistant
|
||||||
- If exists: Add only NEW tech from current plan
|
- If exists: Add only NEW tech from current plan
|
||||||
- Preserve manual additions between markers
|
- Preserve manual additions between markers
|
||||||
- Update recent changes (keep last 3)
|
- Update recent changes (keep last 3)
|
||||||
@@ -187,7 +164,7 @@ ios/ or android/
|
|||||||
*This section describes what the /tasks command will do - DO NOT execute during /plan*
|
*This section describes what the /tasks command will do - DO NOT execute during /plan*
|
||||||
|
|
||||||
**Task Generation Strategy**:
|
**Task Generation Strategy**:
|
||||||
- Load `/templates/tasks-template.md` as base
|
- Load `.specify/templates/tasks-template.md` as base
|
||||||
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
|
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
|
||||||
- Each contract → contract test task [P]
|
- Each contract → contract test task [P]
|
||||||
- Each entity → model creation task [P]
|
- Each entity → model creation task [P]
|
||||||
@@ -237,4 +214,4 @@ ios/ or android/
|
|||||||
- [ ] Complexity deviations documented
|
- [ ] Complexity deviations documented
|
||||||
|
|
||||||
---
|
---
|
||||||
*Based on Constitution v2.1.1 - See `/memory/constitution.md`*
|
*Based on Constitution v2.1.1 - See `/memory/constitution.md`*
|
||||||
|
|||||||
Reference in New Issue
Block a user