specops-cli 0.0.22__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. specops_cli-0.0.22/.github/workflows/release.yml +59 -0
  2. specops_cli-0.0.22/.github/workflows/scripts/check-release-exists.sh +21 -0
  3. specops_cli-0.0.22/.github/workflows/scripts/create-github-release.sh +54 -0
  4. specops_cli-0.0.22/.github/workflows/scripts/create-release-packages.sh +282 -0
  5. specops_cli-0.0.22/.github/workflows/scripts/generate-release-notes.sh +40 -0
  6. specops_cli-0.0.22/.github/workflows/scripts/get-next-version.sh +24 -0
  7. specops_cli-0.0.22/.gitignore +46 -0
  8. specops_cli-0.0.22/AGENTS.md +430 -0
  9. specops_cli-0.0.22/PKG-INFO +11 -0
  10. specops_cli-0.0.22/README.md +372 -0
  11. specops_cli-0.0.22/STRUCTURE.md +98 -0
  12. specops_cli-0.0.22/memory/constitution.md +459 -0
  13. specops_cli-0.0.22/pyproject.toml +23 -0
  14. specops_cli-0.0.22/scripts/bash/check-prerequisites.sh +166 -0
  15. specops_cli-0.0.22/scripts/bash/common.sh +155 -0
  16. specops_cli-0.0.22/scripts/bash/create-new-feature.sh +297 -0
  17. specops_cli-0.0.22/scripts/bash/setup-plan.sh +60 -0
  18. specops_cli-0.0.22/scripts/bash/update-agent-context.sh +798 -0
  19. specops_cli-0.0.22/spec-driven.md +412 -0
  20. specops_cli-0.0.22/src/specops_cli/__init__.py +1363 -0
  21. specops_cli-0.0.22/templates/agent-file-template.md +30 -0
  22. specops_cli-0.0.22/templates/checklist-template.md +40 -0
  23. specops_cli-0.0.22/templates/commands/analyze.md +187 -0
  24. specops_cli-0.0.22/templates/commands/checklist.md +297 -0
  25. specops_cli-0.0.22/templates/commands/clarify.md +697 -0
  26. specops_cli-0.0.22/templates/commands/constitution.md +307 -0
  27. specops_cli-0.0.22/templates/commands/deploy.md +127 -0
  28. specops_cli-0.0.22/templates/commands/implement.md +148 -0
  29. specops_cli-0.0.22/templates/commands/plan.md +102 -0
  30. specops_cli-0.0.22/templates/commands/specify.md +266 -0
  31. specops_cli-0.0.22/templates/commands/tasks.md +140 -0
  32. specops_cli-0.0.22/templates/commands/taskstoissues.md +33 -0
  33. specops_cli-0.0.22/templates/plan-template.md +141 -0
  34. specops_cli-0.0.22/templates/spec-template.md +124 -0
  35. specops_cli-0.0.22/templates/tasks-template.md +267 -0
  36. specops_cli-0.0.22/templates/vscode-settings.json +13 -0
@@ -0,0 +1,59 @@
1
+ name: Create Release
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ paths:
7
+ - 'memory/**'
8
+ - 'scripts/**'
9
+ - 'templates/**'
10
+ - '.github/workflows/**'
11
+ workflow_dispatch:
12
+
13
+ jobs:
14
+ release:
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: write
18
+ pull-requests: write
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ token: ${{ secrets.GITHUB_TOKEN }}
25
+ - name: Get latest tag
26
+ id: get_tag
27
+ run: |
28
+ chmod +x .github/workflows/scripts/get-next-version.sh
29
+ .github/workflows/scripts/get-next-version.sh
30
+ - name: Check if release already exists
31
+ id: check_release
32
+ run: |
33
+ chmod +x .github/workflows/scripts/check-release-exists.sh
34
+ .github/workflows/scripts/check-release-exists.sh ${{ steps.get_tag.outputs.new_version }}
35
+ env:
36
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+ - name: Create release package variants
38
+ if: steps.check_release.outputs.exists == 'false'
39
+ run: |
40
+ chmod +x .github/workflows/scripts/create-release-packages.sh
41
+ .github/workflows/scripts/create-release-packages.sh ${{ steps.get_tag.outputs.new_version }}
42
+ - name: Generate release notes
43
+ if: steps.check_release.outputs.exists == 'false'
44
+ id: release_notes
45
+ run: |
46
+ chmod +x .github/workflows/scripts/generate-release-notes.sh
47
+ .github/workflows/scripts/generate-release-notes.sh ${{ steps.get_tag.outputs.new_version }} ${{ steps.get_tag.outputs.latest_tag }}
48
+ - name: Create GitHub Release
49
+ if: steps.check_release.outputs.exists == 'false'
50
+ run: |
51
+ chmod +x .github/workflows/scripts/create-github-release.sh
52
+ .github/workflows/scripts/create-github-release.sh ${{ steps.get_tag.outputs.new_version }}
53
+ env:
54
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55
+ - name: Update version in pyproject.toml (for release artifacts only)
56
+ if: steps.check_release.outputs.exists == 'false'
57
+ run: |
58
+ chmod +x .github/workflows/scripts/update-version.sh
59
+ .github/workflows/scripts/update-version.sh ${{ steps.get_tag.outputs.new_version }}
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # check-release-exists.sh
5
+ # Check if a GitHub release already exists for the given version
6
+ # Usage: check-release-exists.sh <version>
7
+
8
+ if [[ $# -ne 1 ]]; then
9
+ echo "Usage: $0 <version>" >&2
10
+ exit 1
11
+ fi
12
+
13
+ VERSION="$1"
14
+
15
+ if gh release view "$VERSION" >/dev/null 2>&1; then
16
+ echo "exists=true" >> $GITHUB_OUTPUT
17
+ echo "Release $VERSION already exists, skipping..."
18
+ else
19
+ echo "exists=false" >> $GITHUB_OUTPUT
20
+ echo "Release $VERSION does not exist, proceeding..."
21
+ fi
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # create-github-release.sh
5
+ # Create a GitHub release with all template zip files
6
+ # Usage: create-github-release.sh <version>
7
+
8
+ if [[ $# -ne 1 ]]; then
9
+ echo "Usage: $0 <version>" >&2
10
+ exit 1
11
+ fi
12
+
13
+ VERSION="$1"
14
+
15
+ # Remove 'v' prefix from version for release title
16
+ VERSION_NO_V=${VERSION#v}
17
+
18
+ gh release create "$VERSION" \
19
+ .genreleases/spec-ops-template-copilot-sh-"$VERSION".zip \
20
+ .genreleases/spec-ops-template-copilot-ps-"$VERSION".zip \
21
+ .genreleases/spec-ops-template-claude-sh-"$VERSION".zip \
22
+ .genreleases/spec-ops-template-claude-ps-"$VERSION".zip \
23
+ .genreleases/spec-ops-template-gemini-sh-"$VERSION".zip \
24
+ .genreleases/spec-ops-template-gemini-ps-"$VERSION".zip \
25
+ .genreleases/spec-ops-template-cursor-agent-sh-"$VERSION".zip \
26
+ .genreleases/spec-ops-template-cursor-agent-ps-"$VERSION".zip \
27
+ .genreleases/spec-ops-template-opencode-sh-"$VERSION".zip \
28
+ .genreleases/spec-ops-template-opencode-ps-"$VERSION".zip \
29
+ .genreleases/spec-ops-template-qwen-sh-"$VERSION".zip \
30
+ .genreleases/spec-ops-template-qwen-ps-"$VERSION".zip \
31
+ .genreleases/spec-ops-template-windsurf-sh-"$VERSION".zip \
32
+ .genreleases/spec-ops-template-windsurf-ps-"$VERSION".zip \
33
+ .genreleases/spec-ops-template-codex-sh-"$VERSION".zip \
34
+ .genreleases/spec-ops-template-codex-ps-"$VERSION".zip \
35
+ .genreleases/spec-ops-template-kilocode-sh-"$VERSION".zip \
36
+ .genreleases/spec-ops-template-kilocode-ps-"$VERSION".zip \
37
+ .genreleases/spec-ops-template-auggie-sh-"$VERSION".zip \
38
+ .genreleases/spec-ops-template-auggie-ps-"$VERSION".zip \
39
+ .genreleases/spec-ops-template-roo-sh-"$VERSION".zip \
40
+ .genreleases/spec-ops-template-roo-ps-"$VERSION".zip \
41
+ .genreleases/spec-ops-template-codebuddy-sh-"$VERSION".zip \
42
+ .genreleases/spec-ops-template-codebuddy-ps-"$VERSION".zip \
43
+ .genreleases/spec-ops-template-qoder-sh-"$VERSION".zip \
44
+ .genreleases/spec-ops-template-qoder-ps-"$VERSION".zip \
45
+ .genreleases/spec-ops-template-amp-sh-"$VERSION".zip \
46
+ .genreleases/spec-ops-template-amp-ps-"$VERSION".zip \
47
+ .genreleases/spec-ops-template-shai-sh-"$VERSION".zip \
48
+ .genreleases/spec-ops-template-shai-ps-"$VERSION".zip \
49
+ .genreleases/spec-ops-template-q-sh-"$VERSION".zip \
50
+ .genreleases/spec-ops-template-q-ps-"$VERSION".zip \
51
+ .genreleases/spec-ops-template-bob-sh-"$VERSION".zip \
52
+ .genreleases/spec-ops-template-bob-ps-"$VERSION".zip \
53
+ --title "Spec Ops Templates - $VERSION_NO_V" \
54
+ --notes-file release_notes.md
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # create-release-packages.sh (workflow-local)
5
+ # Build Spec Ops template release archives for each supported AI assistant and script type.
6
+ # Usage: .github/workflows/scripts/create-release-packages.sh <version>
7
+ # Version argument should include leading 'v'.
8
+ # Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
9
+ # AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex amp shai bob (default: all)
10
+ # SCRIPTS : space or comma separated subset of: sh ps (default: both)
11
+ # Examples:
12
+ # AGENTS=claude SCRIPTS=sh $0 v0.2.0
13
+ # AGENTS="copilot,gemini" $0 v0.2.0
14
+ # SCRIPTS=ps $0 v0.2.0
15
+
16
+ if [[ $# -ne 1 ]]; then
17
+ echo "Usage: $0 <version-with-v-prefix>" >&2
18
+ exit 1
19
+ fi
20
+ NEW_VERSION="$1"
21
+ if [[ ! $NEW_VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
22
+ echo "Version must look like v0.0.0" >&2
23
+ exit 1
24
+ fi
25
+
26
+ echo "Building release packages for $NEW_VERSION"
27
+
28
+ # Create and use .genreleases directory for all build artifacts
29
+ GENRELEASES_DIR=".genreleases"
30
+ mkdir -p "$GENRELEASES_DIR"
31
+ rm -rf "$GENRELEASES_DIR"/* || true
32
+
33
+ rewrite_paths() {
34
+ sed -E \
35
+ -e 's@(/?)memory/@.specops/memory/@g' \
36
+ -e 's@(/?)scripts/@.specops/scripts/@g' \
37
+ -e 's@(/?)templates/@.specops/templates/@g'
38
+ }
39
+
40
+ generate_commands() {
41
+ local agent=$1 ext=$2 arg_format=$3 output_dir=$4 script_variant=$5
42
+ mkdir -p "$output_dir"
43
+ for template in templates/commands/*.md; do
44
+ [[ -f "$template" ]] || continue
45
+ local name description script_command agent_script_command body
46
+ name=$(basename "$template" .md)
47
+
48
+ # Normalize line endings
49
+ file_content=$(tr -d '\r' < "$template")
50
+
51
+ # Extract description and script command from YAML frontmatter
52
+ description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
53
+ script_command=$(printf '%s\n' "$file_content" | awk -v sv="$script_variant" '/^[[:space:]]*'"$script_variant"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, ""); print; exit}')
54
+
55
+ if [[ -z $script_command ]]; then
56
+ echo "Warning: no script command found for $script_variant in $template" >&2
57
+ script_command="(Missing script command for $script_variant)"
58
+ fi
59
+
60
+ # Extract agent_script command from YAML frontmatter if present
61
+ agent_script_command=$(printf '%s\n' "$file_content" | awk '
62
+ /^agent_scripts:$/ { in_agent_scripts=1; next }
63
+ in_agent_scripts && /^[[:space:]]*'"$script_variant"':[[:space:]]*/ {
64
+ sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, "")
65
+ print
66
+ exit
67
+ }
68
+ in_agent_scripts && /^[a-zA-Z]/ { in_agent_scripts=0 }
69
+ ')
70
+
71
+ # Replace {SCRIPT} placeholder with the script command
72
+ body=$(printf '%s\n' "$file_content" | sed "s|{SCRIPT}|${script_command}|g")
73
+
74
+ # Replace {AGENT_SCRIPT} placeholder with the agent script command if found
75
+ if [[ -n $agent_script_command ]]; then
76
+ body=$(printf '%s\n' "$body" | sed "s|{AGENT_SCRIPT}|${agent_script_command}|g")
77
+ fi
78
+
79
+ # Remove the scripts: and agent_scripts: sections from frontmatter while preserving YAML structure
80
+ body=$(printf '%s\n' "$body" | awk '
81
+ /^---$/ { print; if (++dash_count == 1) in_frontmatter=1; else in_frontmatter=0; next }
82
+ in_frontmatter && /^scripts:$/ { skip_scripts=1; next }
83
+ in_frontmatter && /^agent_scripts:$/ { skip_scripts=1; next }
84
+ in_frontmatter && /^[a-zA-Z].*:/ && skip_scripts { skip_scripts=0 }
85
+ in_frontmatter && skip_scripts && /^[[:space:]]/ { next }
86
+ { print }
87
+ ')
88
+
89
+ # Apply other substitutions
90
+ body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
91
+
92
+ case $ext in
93
+ toml)
94
+ body=$(printf '%s\n' "$body" | sed 's/\\/\\\\/g')
95
+ { echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/specops.$name.$ext" ;;
96
+ md)
97
+ echo "$body" > "$output_dir/specops.$name.$ext" ;;
98
+ agent.md)
99
+ echo "$body" > "$output_dir/specops.$name.$ext" ;;
100
+ esac
101
+ done
102
+ }
103
+
104
+ generate_copilot_prompts() {
105
+ local agents_dir=$1 prompts_dir=$2
106
+ mkdir -p "$prompts_dir"
107
+
108
+ # Generate a .prompt.md file for each .agent.md file
109
+ for agent_file in "$agents_dir"/specops.*.agent.md; do
110
+ [[ -f "$agent_file" ]] || continue
111
+
112
+ local basename=$(basename "$agent_file" .agent.md)
113
+ local prompt_file="$prompts_dir/${basename}.prompt.md"
114
+
115
+ # Create prompt file with agent frontmatter
116
+ cat > "$prompt_file" <<EOF
117
+ ---
118
+ agent: ${basename}
119
+ ---
120
+ EOF
121
+ done
122
+ }
123
+
124
+ build_variant() {
125
+ local agent=$1 script=$2
126
+ local base_dir="$GENRELEASES_DIR/sdd-${agent}-package-${script}"
127
+ echo "Building $agent ($script) package..."
128
+ mkdir -p "$base_dir"
129
+
130
+ # Copy base structure but filter scripts by variant
131
+ SPEC_DIR="$base_dir/.specops"
132
+ mkdir -p "$SPEC_DIR"
133
+
134
+ [[ -d memory ]] && { cp -r memory "$SPEC_DIR/"; echo "Copied memory -> .specops"; }
135
+
136
+ # Only copy the relevant script variant directory
137
+ if [[ -d scripts ]]; then
138
+ mkdir -p "$SPEC_DIR/scripts"
139
+ case $script in
140
+ sh)
141
+ [[ -d scripts/bash ]] && { cp -r scripts/bash "$SPEC_DIR/scripts/"; echo "Copied scripts/bash -> .specops/scripts"; }
142
+ # Copy any script files that aren't in variant-specific directories
143
+ find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
144
+ ;;
145
+ ps)
146
+ [[ -d scripts/powershell ]] && { cp -r scripts/powershell "$SPEC_DIR/scripts/"; echo "Copied scripts/powershell -> .specops/scripts"; }
147
+ # Copy any script files that aren't in variant-specific directories
148
+ find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
149
+ ;;
150
+ esac
151
+ fi
152
+
153
+ # Copy templates (excluding commands/ and vscode-settings.json) - macOS compatible
154
+ if [[ -d templates ]]; then
155
+ mkdir -p "$SPEC_DIR/templates"
156
+ find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" | while read -r file; do
157
+ dest_dir="$SPEC_DIR/$(dirname "$file")"
158
+ mkdir -p "$dest_dir"
159
+ cp "$file" "$dest_dir/"
160
+ done
161
+ echo "Copied templates -> .specops/templates"
162
+ fi
163
+
164
+ # NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
165
+ # * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
166
+ # * TOML (gemini, qwen): {{args}}
167
+ # This keeps formats readable without extra abstraction.
168
+
169
+ case $agent in
170
+ claude)
171
+ mkdir -p "$base_dir/.claude/commands"
172
+ generate_commands claude md "\$ARGUMENTS" "$base_dir/.claude/commands" "$script" ;;
173
+ gemini)
174
+ mkdir -p "$base_dir/.gemini/commands"
175
+ generate_commands gemini toml "{{args}}" "$base_dir/.gemini/commands" "$script"
176
+ [[ -f agent_templates/gemini/GEMINI.md ]] && cp agent_templates/gemini/GEMINI.md "$base_dir/GEMINI.md" ;;
177
+ copilot)
178
+ mkdir -p "$base_dir/.github/agents"
179
+ generate_commands copilot agent.md "\$ARGUMENTS" "$base_dir/.github/agents" "$script"
180
+ # Generate companion prompt files
181
+ generate_copilot_prompts "$base_dir/.github/agents" "$base_dir/.github/prompts"
182
+ # Create VS Code workspace settings
183
+ mkdir -p "$base_dir/.vscode"
184
+ [[ -f templates/vscode-settings.json ]] && cp templates/vscode-settings.json "$base_dir/.vscode/settings.json"
185
+ ;;
186
+ cursor-agent)
187
+ mkdir -p "$base_dir/.cursor/commands"
188
+ generate_commands cursor-agent md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
189
+ qwen)
190
+ mkdir -p "$base_dir/.qwen/commands"
191
+ generate_commands qwen toml "{{args}}" "$base_dir/.qwen/commands" "$script"
192
+ [[ -f agent_templates/qwen/QWEN.md ]] && cp agent_templates/qwen/QWEN.md "$base_dir/QWEN.md" ;;
193
+ opencode)
194
+ mkdir -p "$base_dir/.opencode/command"
195
+ generate_commands opencode md "\$ARGUMENTS" "$base_dir/.opencode/command" "$script" ;;
196
+ windsurf)
197
+ mkdir -p "$base_dir/.windsurf/workflows"
198
+ generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
199
+ codex)
200
+ mkdir -p "$base_dir/.codex/prompts"
201
+ generate_commands codex md "\$ARGUMENTS" "$base_dir/.codex/prompts" "$script" ;;
202
+ kilocode)
203
+ mkdir -p "$base_dir/.kilocode/workflows"
204
+ generate_commands kilocode md "\$ARGUMENTS" "$base_dir/.kilocode/workflows" "$script" ;;
205
+ auggie)
206
+ mkdir -p "$base_dir/.augment/commands"
207
+ generate_commands auggie md "\$ARGUMENTS" "$base_dir/.augment/commands" "$script" ;;
208
+ roo)
209
+ mkdir -p "$base_dir/.roo/commands"
210
+ generate_commands roo md "\$ARGUMENTS" "$base_dir/.roo/commands" "$script" ;;
211
+ codebuddy)
212
+ mkdir -p "$base_dir/.codebuddy/commands"
213
+ generate_commands codebuddy md "\$ARGUMENTS" "$base_dir/.codebuddy/commands" "$script" ;;
214
+ qoder)
215
+ mkdir -p "$base_dir/.qoder/commands"
216
+ generate_commands qoder md "\$ARGUMENTS" "$base_dir/.qoder/commands" "$script" ;;
217
+ amp)
218
+ mkdir -p "$base_dir/.agents/commands"
219
+ generate_commands amp md "\$ARGUMENTS" "$base_dir/.agents/commands" "$script" ;;
220
+ shai)
221
+ mkdir -p "$base_dir/.shai/commands"
222
+ generate_commands shai md "\$ARGUMENTS" "$base_dir/.shai/commands" "$script" ;;
223
+ q)
224
+ mkdir -p "$base_dir/.amazonq/prompts"
225
+ generate_commands q md "\$ARGUMENTS" "$base_dir/.amazonq/prompts" "$script" ;;
226
+ bob)
227
+ mkdir -p "$base_dir/.bob/commands"
228
+ generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;;
229
+ esac
230
+ ( cd "$base_dir" && zip -r "../spec-ops-template-${agent}-${script}-${NEW_VERSION}.zip" . )
231
+ echo "Created $GENRELEASES_DIR/spec-ops-template-${agent}-${script}-${NEW_VERSION}.zip"
232
+ }
233
+
234
+ # Determine agent list
235
+ #ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q bob qoder)
236
+ ALL_AGENTS=(claude copilot)
237
+ ALL_SCRIPTS=(sh ps)
238
+
239
+ norm_list() {
240
+ # convert comma+space separated -> line separated unique while preserving order of first occurrence
241
+ tr ',\n' ' ' | awk '{for(i=1;i<=NF;i++){if(!seen[$i]++){printf((out?"\n":"") $i);out=1}}}END{printf("\n")}'
242
+ }
243
+
244
+ validate_subset() {
245
+ local type=$1; shift; local -n allowed=$1; shift; local items=("$@")
246
+ local invalid=0
247
+ for it in "${items[@]}"; do
248
+ local found=0
249
+ for a in "${allowed[@]}"; do [[ $it == "$a" ]] && { found=1; break; }; done
250
+ if [[ $found -eq 0 ]]; then
251
+ echo "Error: unknown $type '$it' (allowed: ${allowed[*]})" >&2
252
+ invalid=1
253
+ fi
254
+ done
255
+ return $invalid
256
+ }
257
+
258
+ if [[ -n ${AGENTS:-} ]]; then
259
+ mapfile -t AGENT_LIST < <(printf '%s' "$AGENTS" | norm_list)
260
+ validate_subset agent ALL_AGENTS "${AGENT_LIST[@]}" || exit 1
261
+ else
262
+ AGENT_LIST=("${ALL_AGENTS[@]}")
263
+ fi
264
+
265
+ if [[ -n ${SCRIPTS:-} ]]; then
266
+ mapfile -t SCRIPT_LIST < <(printf '%s' "$SCRIPTS" | norm_list)
267
+ validate_subset script ALL_SCRIPTS "${SCRIPT_LIST[@]}" || exit 1
268
+ else
269
+ SCRIPT_LIST=("${ALL_SCRIPTS[@]}")
270
+ fi
271
+
272
+ echo "Agents: ${AGENT_LIST[*]}"
273
+ echo "Scripts: ${SCRIPT_LIST[*]}"
274
+
275
+ for agent in "${AGENT_LIST[@]}"; do
276
+ for script in "${SCRIPT_LIST[@]}"; do
277
+ build_variant "$agent" "$script"
278
+ done
279
+ done
280
+
281
+ echo "Archives in $GENRELEASES_DIR:"
282
+ ls -1 "$GENRELEASES_DIR"/spec-ops-template-*-"${NEW_VERSION}".zip
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # generate-release-notes.sh
5
+ # Generate release notes from git history
6
+ # Usage: generate-release-notes.sh <new_version> <last_tag>
7
+
8
+ if [[ $# -ne 2 ]]; then
9
+ echo "Usage: $0 <new_version> <last_tag>" >&2
10
+ exit 1
11
+ fi
12
+
13
+ NEW_VERSION="$1"
14
+ LAST_TAG="$2"
15
+
16
+ # Get commits since last tag
17
+ if [ "$LAST_TAG" = "v0.0.0" ]; then
18
+ # Check how many commits we have and use that as the limit
19
+ COMMIT_COUNT=$(git rev-list --count HEAD)
20
+ if [ "$COMMIT_COUNT" -gt 10 ]; then
21
+ COMMITS=$(git log --oneline --pretty=format:"- %s" HEAD~10..HEAD)
22
+ else
23
+ COMMITS=$(git log --oneline --pretty=format:"- %s" HEAD~$COMMIT_COUNT..HEAD 2>/dev/null || git log --oneline --pretty=format:"- %s")
24
+ fi
25
+ else
26
+ COMMITS=$(git log --oneline --pretty=format:"- %s" $LAST_TAG..HEAD)
27
+ fi
28
+
29
+ # Create release notes
30
+ cat > release_notes.md << EOF
31
+ This is the latest set of releases that you can use with your agent of choice. We recommend using the Specify CLI to scaffold your projects, however you can download these independently and manage them yourself.
32
+
33
+ ## Changelog
34
+
35
+ $COMMITS
36
+
37
+ EOF
38
+
39
+ echo "Generated release notes:"
40
+ cat release_notes.md
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # get-next-version.sh
5
+ # Calculate the next version based on the latest git tag and output GitHub Actions variables
6
+ # Usage: get-next-version.sh
7
+
8
+ # Get the latest tag, or use v0.0.0 if no tags exist
9
+ LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
10
+ echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
11
+
12
+ # Extract version number and increment
13
+ VERSION=$(echo $LATEST_TAG | sed 's/v//')
14
+ IFS='.' read -ra VERSION_PARTS <<< "$VERSION"
15
+ MAJOR=${VERSION_PARTS[0]:-0}
16
+ MINOR=${VERSION_PARTS[1]:-0}
17
+ PATCH=${VERSION_PARTS[2]:-0}
18
+
19
+ # Increment patch version
20
+ PATCH=$((PATCH + 1))
21
+ NEW_VERSION="v$MAJOR.$MINOR.$PATCH"
22
+
23
+ echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
24
+ echo "New version will be: $NEW_VERSION"
@@ -0,0 +1,46 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ ENV/
26
+ env/
27
+ .venv
28
+
29
+ # IDE
30
+ .vscode/
31
+ .idea/
32
+ *.swp
33
+ *.swo
34
+ .DS_Store
35
+ *.tmp
36
+
37
+ # Project specific
38
+ *.log
39
+ .env
40
+ .env.local
41
+ *.lock
42
+
43
+ # Spec Kit-specific files
44
+ .genreleases/
45
+ *.zip
46
+ sdd-*/