Skip to content

Commit 6045c92

Browse files
committed
Merge upstream/main into feat/update-check-1320
Drops local duplicates of get_speckit_version + the in-flight update-check helpers from __init__.py; the feature is re-added in _version.py in a follow-up commit so it reuses upstream's _get_installed_version, _fetch_latest_release_tag, and _is_newer from PR #2550.
2 parents 53e20e2 + 81e9ecd commit 6045c92

137 files changed

Lines changed: 14950 additions & 2713 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
# Global code owner
22
* @mnriem
33

4+
# Community catalog files — explicit ownership for when global ownership expands
5+
/extensions/catalog.community.json @mnriem
6+
/integrations/catalog.community.json @mnriem
7+
/presets/catalog.community.json @mnriem
8+

.github/ISSUE_TEMPLATE/agent_request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ body:
88
value: |
99
Thanks for requesting a new agent! Before submitting, please check if the agent is already supported.
1010
11-
**Currently supported agents**: Claude Code, Gemini CLI, GitHub Copilot, Cursor, Qwen Code, opencode, Codex CLI, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy, Qoder CLI, Kiro CLI, Amp, SHAI, Tabnine CLI, Antigravity, IBM Bob, Mistral Vibe, Kimi Code, Trae, Pi Coding Agent, iFlow CLI
11+
**Currently supported agents**: Claude Code, Gemini CLI, GitHub Copilot, Cursor, Qwen Code, opencode, Codex CLI, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy, Qoder CLI, Kiro CLI, Amp, SHAI, Tabnine CLI, Antigravity, IBM Bob, Mistral Vibe, Kimi Code, Trae, Pi Coding Agent, iFlow CLI, Devin for Terminal
1212
1313
- type: input
1414
id: agent-name

.github/ISSUE_TEMPLATE/preset_submission.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,18 @@ body:
9595
validations:
9696
required: true
9797

98+
- type: input
99+
id: required-extensions
100+
attributes:
101+
label: Required Extensions (optional)
102+
description: Comma-separated list of required extension IDs (e.g., aide)
103+
placeholder: "e.g., aide, canon"
104+
98105
- type: textarea
99106
id: templates-provided
100107
attributes:
101108
label: Templates Provided
102-
description: List the template overrides your preset provides
109+
description: List the template overrides your preset provides (enter "None" if command-only)
103110
placeholder: |
104111
- spec-template.md — adds compliance section
105112
- plan-template.md — includes audit checkpoints
@@ -110,10 +117,19 @@ body:
110117
- type: textarea
111118
id: commands-provided
112119
attributes:
113-
label: Commands Provided (optional)
114-
description: List any command overrides your preset provides
120+
label: Commands Provided
121+
description: List the command overrides your preset provides (enter "None" if template-only)
115122
placeholder: |
116123
- speckit.specify.md — customized for compliance workflows
124+
validations:
125+
required: true
126+
127+
- type: input
128+
id: scripts-count
129+
attributes:
130+
label: Number of Scripts (optional)
131+
description: How many scripts does your preset provide? (leave empty if none)
132+
placeholder: "e.g., 1"
117133

118134
- type: textarea
119135
id: tags
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
name: add-community-extension
3+
description: 'Add a community extension to the Spec Kit catalog from a GitHub issue submission. USE FOR: processing extension submission issues, validating catalog entries, updating catalog.community.json and docs/community/extensions.md, creating PRs. DO NOT USE FOR: creating new extensions from scratch, or first-party extension work.'
4+
argument-hint: 'GitHub issue URL or number for the extension submission'
5+
---
6+
7+
# Add Community Extension
8+
9+
Process an extension submission issue and add or update it in the community catalog.
10+
11+
## When to Use
12+
13+
- A new `[Extension]` submission issue is filed
14+
- An existing extension submits an update issue (new version, changed metadata)
15+
- You need to add or update a community extension in `extensions/catalog.community.json` and `docs/community/extensions.md`
16+
17+
## Procedure
18+
19+
### 1. Fetch the submission issue
20+
21+
Read the GitHub issue to extract all metadata:
22+
- Extension ID, name, version, description, author
23+
- Repository URL, download URL, homepage, documentation, changelog
24+
- License, required spec-kit version, optional tool dependencies
25+
- Number of commands and hooks
26+
- Tags
27+
28+
### 2. Validate against publishing rules
29+
30+
Check **all** of the following (per `extensions/EXTENSION-PUBLISHING-GUIDE.md`):
31+
32+
| Check | How |
33+
|-------|-----|
34+
| Repository exists and is public | Fetch the repository URL |
35+
| `extension.yml` manifest present | Confirm in repo file listing |
36+
| README.md present | Confirm in repo file listing |
37+
| LICENSE file present | Confirm in repo file listing |
38+
| GitHub release exists matching version | Check releases on the repo page |
39+
| Download URL is accessible | Verify it follows `archive/refs/tags/vX.Y.Z.zip` pattern and release exists |
40+
| Extension ID is lowercase-with-hyphens only | Regex: `^[a-z][a-z0-9-]*$` |
41+
| Version follows semver | Format: `X.Y.Z` |
42+
| Submission checklists are all checked | Confirm in issue body |
43+
44+
### 3. Determine if this is an add or update
45+
46+
Search `extensions/catalog.community.json` for the extension ID.
47+
48+
- **Not found** → this is a **new addition**. Proceed to step 4.
49+
- **Found** → this is an **update**. Proceed to step 4 but replace the existing entry in-place instead of inserting.
50+
51+
### 4. Add or update `extensions/catalog.community.json`
52+
53+
**New extension:** Insert the entry in **alphabetical order** by extension ID.
54+
55+
**Update:** Replace the existing entry in-place. Update only the fields that changed (typically `version`, `download_url`, `description`, `provides`, `requires`, `tags`, `updated_at`). Preserve `created_at` and `downloads`/`stars` from the existing entry.
56+
57+
Use the existing entries as the format template. Required fields:
58+
59+
```json
60+
{
61+
"<id>": {
62+
"name": "<name>",
63+
"id": "<id>",
64+
"description": "<description>",
65+
"author": "<author>",
66+
"version": "<version>",
67+
"download_url": "<download_url>",
68+
"repository": "<repository>",
69+
"homepage": "<homepage>",
70+
"documentation": "<documentation>",
71+
"changelog": "<changelog>",
72+
"license": "<license>",
73+
"requires": {
74+
"speckit_version": "<speckit_version>"
75+
},
76+
"provides": {
77+
"commands": <N>,
78+
"hooks": <N>
79+
},
80+
"tags": ["<tag1>", "<tag2>"],
81+
"verified": false,
82+
"downloads": 0,
83+
"stars": 0,
84+
"created_at": "<today>T00:00:00Z",
85+
"updated_at": "<today>T00:00:00Z"
86+
}
87+
}
88+
```
89+
90+
If the extension has optional tool dependencies, add a `"tools"` array inside `"requires"`:
91+
92+
```json
93+
"tools": [{ "name": "<tool>", "required": false }]
94+
```
95+
96+
Also update the top-level `"updated_at"` timestamp in the catalog.
97+
98+
After editing, **validate the JSON** by running:
99+
100+
```bash
101+
python3 -c "import json; json.load(open('extensions/catalog.community.json')); print('Valid JSON')"
102+
```
103+
104+
### 5. Add or update `docs/community/extensions.md` community extensions table
105+
106+
**New extension:** Insert a new row into the `# Community Extensions` table in **alphabetical order** by extension name.
107+
108+
**Update:** Find the existing row and update the description or other changed fields in-place.
109+
110+
Determine the category and effect from the extension's behavior:
111+
112+
```
113+
| <Name> | <Description> | `<category>` | <Effect> | [<repo-name>](<repository-url>) |
114+
```
115+
116+
**Category** — one of: `docs`, `code`, `process`, `integration`, `visibility`
117+
**Effect**`Read-only` (produces reports only) or `Read+Write` (modifies project files)
118+
119+
### 6. Commit, push, and open PR
120+
121+
Use `add-` for new extensions, `update-` for updates:
122+
123+
```bash
124+
# New extension
125+
git checkout -b add-<extension-id>-extension
126+
127+
# Update
128+
git checkout -b update-<extension-id>-extension
129+
```
130+
131+
```bash
132+
git add extensions/catalog.community.json docs/community/extensions.md
133+
134+
# New extension
135+
git commit -m "Add <Name> extension to community catalog
136+
137+
Add <id> extension submitted by @<issue-author> to:
138+
- extensions/catalog.community.json (alphabetical order)
139+
- docs/community/extensions.md community extensions table
140+
141+
Closes #<issue-number>"
142+
143+
# Update
144+
git commit -m "Update <Name> extension to v<version>
145+
146+
Update <id> extension submitted by @<issue-author>:
147+
- extensions/catalog.community.json (version, download_url, etc.)
148+
- docs/community/extensions.md community extensions table
149+
150+
Closes #<issue-number>"
151+
152+
git push origin <branch-name>
153+
```
154+
155+
Then create a PR to `upstream` (`github/spec-kit`) with:
156+
- **Title:** `Add <Name> extension to community catalog` (or `Update <Name> extension to v<version>`)
157+
- **Body:** Include validation summary, `Closes #<issue-number>`, and `cc @<issue-author>`
158+
- **Head:** `<fork-owner>:<branch-name>`
159+
- **Base:** `main`
160+
161+
## Common Pitfalls
162+
163+
- **Alphabetical order matters** — entries must be sorted by ID in the JSON and by name in the docs table.
164+
- **Don't forget the catalog `updated_at`** — the top-level timestamp in `catalog.community.json` must be refreshed.
165+
- **Validate JSON after editing** — a trailing comma or missing brace will break the catalog.
166+
- **Use `Closes` not `Fixes`**`Closes #N` is the correct keyword for submission issues.
167+
- **Match the proposed entry but verify** — the issue may include a proposed JSON block, but always validate field values against the actual repository state.
168+
- **Preserve `created_at` on updates** — keep the original `created_at` value; only change `updated_at`.
169+
- **Preserve `downloads` and `stars` on updates** — these reflect usage metrics and must not be reset.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: "Catalog: Auto-assign submission"
2+
3+
on:
4+
issues:
5+
types: [opened, labeled]
6+
7+
jobs:
8+
assign:
9+
if: >
10+
(github.event.action == 'opened' && (
11+
contains(github.event.issue.labels.*.name, 'extension-submission') ||
12+
contains(github.event.issue.labels.*.name, 'preset-submission')
13+
)) ||
14+
(github.event.action == 'labeled' && (
15+
github.event.label.name == 'extension-submission' ||
16+
github.event.label.name == 'preset-submission'
17+
))
18+
runs-on: ubuntu-latest
19+
permissions:
20+
issues: write
21+
steps:
22+
- uses: actions/github-script@v9
23+
with:
24+
script: |
25+
const issue = context.payload.issue;
26+
const assigned = (issue.assignees || []).map(a => a.login);
27+
const marker = '<!-- catalog-assign-bot -->';
28+
29+
// Assign mnriem if not already assigned
30+
if (!assigned.includes('mnriem')) {
31+
try {
32+
await github.rest.issues.addAssignees({
33+
owner: context.repo.owner,
34+
repo: context.repo.repo,
35+
issue_number: context.issue.number,
36+
assignees: ['mnriem'],
37+
});
38+
} catch (e) {
39+
console.log(`Warning: could not assign mnriem: ${e.message}`);
40+
}
41+
}
42+
43+
// Post team notification if not already posted
44+
const comments = await github.paginate(
45+
github.rest.issues.listComments,
46+
{
47+
owner: context.repo.owner,
48+
repo: context.repo.repo,
49+
issue_number: context.issue.number,
50+
}
51+
);
52+
if (!comments.some(c => c.body && c.body.includes(marker))) {
53+
await github.rest.issues.createComment({
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
issue_number: context.issue.number,
57+
body: marker + '\ncc @github/spec-kit-maintainers — new catalog submission for review.',
58+
});
59+
}

.github/workflows/codeql.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ jobs:
1919
language: [ 'actions', 'python' ]
2020
steps:
2121
- name: Checkout repository
22-
uses: actions/checkout@v4
22+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2323

2424
- name: Initialize CodeQL
25-
uses: github/codeql-action/init@v4
25+
uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
2626
with:
2727
languages: ${{ matrix.language }}
2828

2929
- name: Perform CodeQL Analysis
30-
uses: github/codeql-action/analyze@v4
30+
uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
3131
with:
3232
category: "/language:${{ matrix.language }}"

.github/workflows/docs.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ jobs:
3030
runs-on: ubuntu-latest
3131
steps:
3232
- name: Checkout
33-
uses: actions/checkout@v6
33+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
3434
with:
3535
fetch-depth: 0 # Fetch all history for git info
3636

3737
- name: Setup .NET
38-
uses: actions/setup-dotnet@v4
38+
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
3939
with:
4040
dotnet-version: '8.x'
4141

@@ -48,10 +48,10 @@ jobs:
4848
docfx docfx.json
4949
5050
- name: Setup Pages
51-
uses: actions/configure-pages@v6
51+
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6
5252

5353
- name: Upload artifact
54-
uses: actions/upload-pages-artifact@v5
54+
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
5555
with:
5656
path: 'docs/_site'
5757

@@ -66,5 +66,4 @@ jobs:
6666
steps:
6767
- name: Deploy to GitHub Pages
6868
id: deployment
69-
uses: actions/deploy-pages@v5
70-
69+
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- name: Checkout
15-
uses: actions/checkout@v6
15+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
1616

1717
- name: Run markdownlint-cli2
18-
uses: DavidAnson/markdownlint-cli2-action@ce4853d43830c74c1753b39f3cf40f71c2031eb9 # v23
18+
uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23
1919
with:
2020
globs: |
2121
'**/*.md'

.github/workflows/release-trigger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
pull-requests: write
1717
steps:
1818
- name: Checkout repository
19-
uses: actions/checkout@v6
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
2020
with:
2121
fetch-depth: 0
2222
token: ${{ secrets.RELEASE_PAT }}

.github/workflows/release.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
contents: write
1313
steps:
1414
- name: Checkout repository
15-
uses: actions/checkout@v6
15+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
1616
with:
1717
fetch-depth: 0
1818
token: ${{ secrets.GITHUB_TOKEN }}
@@ -86,4 +86,3 @@ jobs:
8686
--notes-file release_notes.md
8787
env:
8888
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
89-

0 commit comments

Comments
 (0)