* feat(bug-fix): add label-driven bug-fix agentic workflow
Add a `bug-fix` gh-aw workflow as stage 2 of the assess -> fix -> test
bug pipeline, mirroring the existing `bug-assess` stage. It triggers when
a maintainer applies the `bug-fix` label, recovers the slug and remediation
contract from the prior bug-assess assessment comment, applies the fix, and
opens a draft pull request plus a summary comment for human review.
The workflow is intentionally decoupled from Spec Kit specifics: it consumes
the assessment from the issue comment rather than any `.specify/` files, so it
is portable to other repositories running the matching bug-assess stage.
- .github/workflows/bug-fix.md authored and compiled to bug-fix.lock.yml
- Label-gated trigger (github.event.label.name == 'bug-fix')
- Draft PR via create-pull-request safe-output; scoped permissions
- Untrusted-input / URL-safety guardrails consistent with bug-assess
- Maintainer remains the gatekeeper; no unattended automation
Refs #3238
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(bug-fix): tighten bash allowlist and block protected files
Address Copilot review feedback on PR #3258:
- Trim tools.bash to the inspect set plus a small test-runner set
(pytest, npm, go, cargo, dotnet), dropping package-manager/build
tools (pip, npx, pnpm, yarn, mvn, gradle, make, bundle, rake, ruby,
node) to reduce blast radius under prompt injection.
- Set create-pull-request.protected-files.policy: blocked so edits to
sensitive files (dependency manifests, README/CHANGELOG/SECURITY,
etc.) block PR creation, matching the stronger contract used by the
other PR-creating workflows in this repo.
Refs #3238
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(bug-fix): resync lock body_hash after review edits
The Copilot autofix commits edited bug-fix.md (verdict phrasing, Assisted-by
trailer) but did not recompile the lock, leaving body_hash stale. Since the
workflow runs with strict integrity, the runtime-imported bug-fix.md must match
the lock's recorded body_hash. Recompiled with gh-aw v0.79.8 (checkout pin kept
at v7.0.0 to match sibling locks); the only change is the body_hash.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(bug-fix): align add-labels max to 1 and soften next-stage label reference
Address two Copilot review findings:
- add-labels.max: the authored frontmatter said max:1 but the committed lock
enforced max:2 (stale from an earlier frontmatter), and Step 8 said 'max 2
labels total'. The workflow only ever applies ONE status label per run
(fix-proposed | needs-reproduction | fix-blocked | needs-assessment), so 1 is
the correct, tightest contract. Recompiled so the lock now enforces max:1, and
reworded Step 8 to 'exactly one status label per run'.
- bug-test label: Step 7 hard-coded applying a 'bug-test' label that does not
exist in this repo. Since the workflow is portable, reworded to present the
stage-3 bug-test workflow as the planned next stage 'if the repository has it
configured' rather than assuming it exists.
Recompiled with gh-aw v0.79.8; checkout pins kept at v7.0.0 to match sibling
locks. No compile drift.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(bug-fix): set add-labels max to 1 consistently across source and lock
A prior autofix flipped the authored frontmatter add-labels.max back to 2,
re-introducing the mismatch: source said 2, the compiled lock enforced 1, and
Step 8 prose says 'exactly one status label per run'. The workflow only ever
applies a single status label per run (needs-assessment | needs-reproduction |
fix-proposed | fix-blocked), so 1 is the correct, tightest contract and matches
the compiled lock. Set the frontmatter to max:1 so source, lock, and prose all
agree (also avoids the lock staleness guard failing on a frontmatter mismatch).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(bug-fix): relax protected files and number bug-fix branches
Address the two new Copilot review findings:
- was still covering
README.md and CHANGELOG.md, which can legitimately need updates as part of a
prior bug remediation. Add them to the exclude list so the workflow can still
open a PR when the assessment calls for documentation changes, matching the
pattern used by add-community-extension.
- The generated branch name used , but the repo
convention for bug fixes requires so branches are
traceable and aligned with AGENTS.md. Update the branch naming guidance to use
.
Recompiled with gh-aw v0.79.8; lock reflects the protected-files exclusion and
keeps the v7.0.0 checkout pin fixups.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(bug-fix): accept workflow-authored assessment comments from bot/service accounts
Address the open Copilot finding on assessment-author matching.
The workflow previously required the prior assessment comment to be authored by
`github-actions[bot]`. That is too strict for portable repos where bug-assess
may post through a different bot/service account token.
Updated Step 1 to select the most recent assessment comment that appears
workflow-authored by combining:
- bot/service-account authorship, and
- expected bug-assess structure (assessment header plus remediation/files/tests sections).
This keeps the spoof-resistance intent while removing dependence on one fixed
login.
Recompiled with gh-aw v0.79.8 and kept checkout v7.0.0 pin fixups.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(bug-fix): clarify local-check guardrails for dependency fetching
Address Copilot feedback on Step 5 consistency around network-dependent checks.
The workflow previously listed `go test ./...` and `cargo test` as examples
while also forbidding network-dependent commands, which could be ambiguous on
clean runners.
Updated Step 5 to:
- keep those commands as examples only when dependencies are already present
- explicitly disallow dependency-fetch/install commands during verification
(go mod download/go get/cargo fetch/npm|pnpm|yarn install)
Recompiled with gh-aw v0.79.8 and kept checkout v7.0.0 pin fixups.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(bug-fix): make status label application conditional on label existence
Address Copilot feedback about missing status labels causing runtime failures.
The workflow previously instructed unconditional application of
`needs-assessment`, `fix-blocked`, and `fix-proposed`. In repositories where
those labels are not pre-created, `add_labels` fails and can break the run.
Updated Steps 1/3/4/8 to require existence checks before adding those labels:
- add the label only if it exists
- otherwise skip labeling and explicitly note that in the comment
This preserves the status-label UX when labels exist while keeping execution
robust in repos that have not created every optional status label yet.
Recompiled with gh-aw v0.79.8 and kept checkout v7.0.0 pin fixups.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
* feat(workflows): add label-driven bug-test workflow (#3239)
Add the third stage (assess → fix → test) of the semi-automated, human-gated
bug pipeline. The `bug-test` agentic workflow triggers when a maintainer applies
the `bug-test` label, runs the relevant tests in isolation against the fix,
compiles a readable pass/fail report, and posts it back as a single issue
comment.
- Locates the fix under test: linked PR → named fix branch → current checkout
fallback, only ever from origin.
- Stack-agnostic test detection (uv+pytest, npm/pnpm/yarn, go, make) so it is
decoupled from Spec Kit specifics and reusable by other projects.
- Runs tests under a timeout as untrusted code; scoped read-only permissions;
same URL-safety / untrusted-input guardrails as bug-assess.
- Verification mode compares a generated fix against the historical fix for
old/closed bugs to surface discrepancies.
- Optional single result label (tests-passing / tests-failing /
tests-inconclusive).
Compiled bug-test.lock.yml with `gh aw compile`.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(workflows): bump actions/checkout from 6.0.3 to 7.0.0 in bug-test workflow
Align with repo standards (e.g. dependabot PR #3064, other workflows).
Manually pinned in the compiled lock file for consistency.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* chore: retire roo integration — extension shut down (#3167)
Remove the Roo Code integration after the extension was shut down: subpackage,
registry entry, catalog entry, docs, tests, and issue-template options.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: remove stale Roo Code mention in upgrade guide
Assisted-by: GitHub Copilot (model: gpt-5.3-codex, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: remove leftover Roo Code references after merge
Drop roo from presets/ARCHITECTURE.md example and the agent-context
defaults map; these came in from main and were flagged by review.
Assisted-by: GitHub Copilot (model: claude-opus-4.8, autonomous)
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(scripts): portable uppercase for branch-name acronym retention
Branch-name generation keeps short uppercase acronyms (e.g. "AI") by re-checking
the lowercased word against the original description with ${word^^}. That
parameter expansion is bash 4+ only; on macOS's default bash 3.2 it errors with
"bad substitution", so the acronym/short-word retention branch never matches and
those words are dropped ("go AI now" yields 001-now instead of 001-ai-now). Use
tr '[:lower:]' '[:upper:]' instead, which is portable.
Applies to both the core create-new-feature.sh and the git extension's
create-new-feature-branch.sh. The existing
test_branch_name_short_word_case_sensitivity / test_short_word_retention tests
cover this and now pass on bash 3.2 (CI runs on bash 4+/Linux, so they passed
there already).
(Disclosure: an AI coding agent surfaced the failure while running the suite on
macOS and pinned the root cause; fix written and reviewed by me.)
* fix(scripts): portability follow-ups from code review
- core create-new-feature.sh: match the acronym with `grep -qw` (POSIX
whole-word) instead of `\b...\b` (GNU/BSD-only), matching the git extension
and dropping a non-POSIX construct.
- lint: add a CI guard rejecting bash 4+ case-modification expansions in *.sh.
shellcheck assumes bash 4+ from the shebang and can't flag them, and CI has no
bash-3.2 lane, so this prevents silently re-shipping the macOS regression this
PR fixes.
- update a stale PowerShell extension comment that cited the removed bash idiom.
(Disclosure: prompted by an AI code review of the PR; written and reviewed by me.)
* chore: align CI Python matrix with devguide release lifecycle
Run the pytest matrix only on the bugfix (maintenance) releases — 3.13
and 3.14 — instead of 3.11/3.12/3.13, and point the ruff lint job at the
latest interpreter (3.14). The supported floor stays at requires-python
>= 3.11 (oldest non-EOL security release): older security versions are
supported by claim and fixed reactively rather than gated on a wide
per-commit matrix. Also add macos-latest to the OS matrix so macOS
regressions are caught.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: make bash scripts portable to bash 3.2 (macOS system /bin/bash)
Adding macos-latest to the CI matrix surfaced two pre-existing bash 3.2
incompatibilities (macOS ships bash 3.2 as /bin/bash):
1. update-agent-context.sh embedded Python heredocs inside $(...) command
substitution. bash 3.2 mis-parses an apostrophe in a heredoc body
nested in $(...), failing with "unexpected EOF while looking for
matching `''". Removed the apostrophes from the affected $()-nested
heredoc body and documented the constraint to prevent regressions.
2. create-new-feature-branch.sh and create-new-feature.sh used the
bash 4+ ${word^^} uppercase parameter expansion, which errors as a
"bad substitution" on bash 3.2 and caused short uppercase acronyms
(e.g. "GO") to be dropped from derived branch names. Replaced with a
portable `tr '[:lower:]' '[:upper:]'` pipeline.
Verified the full test suite passes under bash 3.2.57 and shellcheck
(--severity=error) is clean.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review feedback on bash 3.2 portability changes
- create-new-feature.sh: replace the non-portable `\b...\b` grep
word-boundary (BSD grep treats `\b` as a backspace, so the acronym
branch could silently fail) with `grep -qw`, matching its twin
create-new-feature-branch.sh, and pipe the description via
`printf '%s'` instead of `echo`.
- create-new-feature-branch.sh: switch the acronym check to
`printf '%s'` as well so both twins are identical and avoid `echo`
on user-provided text.
- update-agent-context.sh: reword the apostrophe-free self-seeding
comment to be clearer and less easy to misread.
Verified under bash 3.2.57 (full bash-script suite green) and
shellcheck --severity=error.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Require preset-usage README with Spec Kit CLI syntax in submissions
Tighten the community preset submission workflow so it validates the
README referenced by the documentation field rather than merely checking
for a root README. The workflow now fails submissions whose linked README
lacks a valid 'specify preset add ...' command and flags monorepo
submissions that point documentation at a generic root README.
- Add a required Documentation URL field to the preset issue template
- Add validation step 2d (documentation README + CLI-syntax check) to
.github/workflows/add-community-preset.md and recompile the lock file
- Document the stricter usage-README requirement and reviewer content
check in presets/PUBLISHING.md
Closes#3103
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Align preset README docs with workflow's actual enforcement
Address PR review feedback on #3104:
- PUBLISHING.md: clarify that only README resolution + a valid
'specify preset add ...' command are mechanically enforced; the
preset-scoped-README and minimum-structure items are reviewer
expectations, not automated checks.
- PUBLISHING.md: state that a missing 'specify preset add ...' command
is a hard validation failure (check 2d), not just 'flagged for changes'.
- preset_submission.yml: require 'specify preset add ...' (not the looser
'specify preset ...') to match the workflow validation.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Tighten preset README validation and docs per PR review
Address PR review feedback on #3104:
- Workflow Step 2c: drop the generic repo-root README.md check so the
README requirement is enforced exactly once, in Step 2d, against the
file the documentation field points to (avoids monorepo false-positive).
- Workflow Step 2d: restrict the documentation URL to GitHub-hosted
README URLs (github.com/.../blob/... or raw.githubusercontent.com/...)
before fetching user-provided input.
- PUBLISHING.md: add the required 'id' field to the example catalog entry.
- preset_submission.yml: fix the Documentation URL placeholder to match
the recommended monorepo presets/<id>/README.md pattern.
- Recompile add-community-preset.lock.yml (body hash only).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refine preset README validation rules per PR review
Address PR review feedback on #3104:
- Workflow Step 2d: broaden the documentation URL allowlist to also
accept github.com/.../raw/... URLs; strip any fragment/query before
fetching so the target is deterministic; clarify that a
'specify preset add --from <url>' command only counts when its URL
matches the submitted Download URL (a different --from URL does not
satisfy the requirement, though other accepted forms still can).
- PUBLISHING.md: show both accepted download URL shapes (tag archive and
release asset) in the README install example instead of implying only
the releases/download form.
- preset_submission.yml: remove the ambiguous generic 'README.md with
description and usage instructions' checkbox; the linked-README
requirement is the single source of truth.
- Recompile add-community-preset.lock.yml (body hash only).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Clarify install-command requirement wording per PR review
Address PR review feedback on #3104: the previous 'matching the download
URL' wording overstated the requirement. Only the 'specify preset add
--from <url>' form needs an exact download-URL match; other accepted
forms ('specify preset add <id>' / '--dev <path>') don't reference the
download URL at all.
- preset_submission.yml: reword the Documentation URL description and the
Submission Requirements checkbox to reflect what's enforced vs preferred.
- PUBLISHING.md: clarify the reviewer note so the exact-match rule is
scoped to the --from form.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Require README.md target and fix release-ZIP wording per PR review
Address PR review feedback on #3104:
- Workflow Step 2d: add an explicit check that the documentation URL path
ends with README.md (case-insensitive) after stripping fragment/query,
so a non-README markdown file is rejected before fetching.
- PUBLISHING.md: reword the release-ZIP note, which conflicted with the
earlier preset structure guidance. The real requirement is that the
README is reachable at the documentation URL before download; it's fine
for the same file to also ship inside the release ZIP.
- Recompile add-community-preset.lock.yml (body hash only).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Use stable unnumbered anchor for Usage README Requirements
Address PR review feedback on #3104: drop the '6.' prefix from the
'Usage README Requirements' heading so its GitHub anchor isn't tied to a
section number (brittle under renumbering, and avoids confusion with the
top-level 'Best Practices' TOC item). Update the Prerequisites cross-link
to the new #usage-readme-requirements anchor.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Align README requirement wording with enforced checks per PR review
Address PR review feedback on #3104:
- PUBLISHING.md: the 'mechanically enforces' summary now lists all Step 2d
checks (GitHub-hosted URL, path ends with README.md, resolves, contains
a valid 'specify preset add ...' command), instead of only two.
- PUBLISHING.md: reword the PR checklist item so a usage README + install
command is the requirement, with preset-scoped README recommended for
monorepos (matches the workflow's flag-not-fail behavior).
- preset_submission.yml: include the full 'specify preset add' prefix on
the --dev and --from forms in the field description and checklist so
submitters copy the exact syntax.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix grammar in Usage README Requirements intro
Address PR review feedback on #3104: remove the incorrect colon after
'the linked README' so the sentence reads naturally.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Avoid lossy raw URL rewrite for slash-containing refs per PR review
Address PR review feedback on #3104: rewriting documentation URLs into the
raw.githubusercontent.com/<owner>/<repo>/<ref>/<path> form can't reliably
represent refs that contain slashes (e.g. a feature/foo branch). Step 2d
now fetches github.com blob URLs by swapping only /blob/ -> /raw/, and
fetches github.com/.../raw/... and raw.githubusercontent.com/... URLs
as-is, instead of reconstructing the raw host form.
Recompile add-community-preset.lock.yml (body hash only).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: pin actions to commit SHAs and add shellcheck
Pin actions/github-script in catalog-assign.yml to a full commit SHA; all
other workflows were already pinned. Add a repo-wide regression test that
every workflow `uses:` ref is pinned to a 40-char commit SHA.
Add a shellcheck job to lint.yml (--severity=error over scripts/bash/*.sh)
and document the local command in CONTRIBUTING.md.
* ci: use repo-standard actions/checkout v7.0.0 in shellcheck job
* ci: shellcheck all tracked shell scripts
Assisted-by: Codex (model: GPT-5, autonomous)
* ci: address workflow hygiene review feedback
Assisted-by: Codex (model: GPT-5, autonomous)
* feat(integrations): add omp support
* Update updated_at timestamp
* refactor(integrations): delegate omp build_exec_args to base, register in issue templates
Inherit MarkdownIntegration.build_exec_args so omp picks up shared CLI
contract changes (requires_cli gating, extra-args ordering, --model
handling) automatically; only specialize the --mode json flag.
Also add Oh My Pi / omp to the issue-template agent lists so
test_issue_template_agent_lists_match_runtime_integrations passes.
* fix(integrations): use --print + positional prompt for omp argv
OMP's CLI parser treats `-p`/`--print` as a boolean (one-shot mode)
and consumes the prompt as a positional message; the previous
inherited `-p <prompt>` shape worked by accident only because `-p`
ignores its next token. Build the argv explicitly with flags first
and the prompt as a trailing positional, matching upstream args.ts.
* feat: add PyPI publishing workflow and readme metadata
- Add readme = "README.md" to pyproject.toml for PyPI project description
- Add manual publish-pypi.yml workflow using trusted publishers (OIDC)
- Update release.yml install instructions to prefer PyPI
The publish workflow is manually triggered after a release, checks out the
specified tag, verifies version consistency, builds with uv, and publishes
using trusted publishing (no API tokens required).
Prerequisites before first use:
- Take ownership of the specify-cli PyPI project (#2908)
- Create a 'pypi' environment in repo settings
- Configure trusted publisher on PyPI for this repo/workflow
Closes#2908
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address PR review feedback on publish workflow
- Add actions: read permission (required for artifact upload/download)
- Move version check after uv install and use uv run python (ensures
Python >=3.11 with tomllib is available regardless of runner image)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use absolute URLs for README images (PyPI compatibility)
PyPI does not host images from the repository, so relative paths like
./media/logo.webp render as broken images. Switch to absolute
raw.githubusercontent.com URLs so images display on both GitHub and PyPI.
Ref: https://github.com/pypi/warehouse/issues/5246
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address second review round
- Convert remaining /media/ image path to absolute URL for PyPI
- Pin release install to specific version (specify-cli==X.Y.Z)
- Align setup-uv to v8.2.0 matching rest of CI
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address third review round
- Use job-level permissions: actions:write on build (for upload-artifact),
actions:read on publish (for download-artifact)
- Include both @latest and pinned version in release notes
- Add note that PyPI may lag behind the GitHub release
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: add contents:read to build job, clarify manual publish
- Build job needs contents:read for checkout (job-level perms replace
workflow-level)
- Clarify that PyPI publishing is manually triggered, not automatic
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: force tag resolution and validate before checkout
Move tag format validation before checkout and use refs/tags/ prefix
to ensure we always check out a tag, not a branch with the same name.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review - links, install cmd, python pin
- Convert all relative .md links in README to absolute GitHub URLs
for PyPI rendering compatibility
- Fix release notes: use 'uv tool install specify-cli' (no @latest)
- Pin Python 3.13 via uv python install for deterministic builds
and use python3 directly instead of uv run
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review - python setup, docs alignment, publish flag
- Use actions/setup-python (pinned v6, Python 3.13) instead of
uv python install for deterministic builds
- Use python instead of python3 for setup-python compatibility
- Remove unsupported --trusted-publishing always flag from uv publish
(OIDC is auto-detected with id-token: write)
- Update README install to lead with PyPI, source as fallback
- Update installation guide: replace PyPI disclaimer with official
package note, add PyPI as primary install method
- Release notes: pin to exact version, clarify PyPI timing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: clarify PyPI availability timing in docs
- README: note source install is useful when PyPI version lags
- Installation guide: explain PyPI follows GitHub releases and may
lag briefly; source installs are always immediately available
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: quote version specifier in release notes install command
uv tool install accepts PEP 508 specifiers when quoted. Add quotes
around 'specify-cli==VERSION' so users can copy-paste directly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use specify-cli@latest consistently
Use @latest to force a fresh PyPI resolve (bypasses uv's cached tool
version), matching the issue acceptance criteria. Source install remains
as fallback when PyPI lags.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: pin release notes to exact version, clarify manual publish
Release notes (versioned changelog) must always reference the specific
release version, not @latest. Use 'specify-cli==VERSION' for
reproducibility.
Also clarify that PyPI publishing is 'performed after' (not 'follows')
each release, making the manual nature clearer.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: keep source install as primary, PyPI as alternative
Until PyPI ownership is fully transferred and first publish is
confirmed, source installs from GitHub remain the primary recommended
method. PyPI install is listed as a convenient alternative.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: align checkout pin, soften PyPI wording, absolute links
- Align actions/checkout to v7.0.0 (same SHA as test.yml/release.yml)
- Remove assertion that PyPI is published by maintainers (ownership
transfer still pending); keep as availability statement
- Use 'once published for this release' wording in release notes
- Convert remaining relative links in README to absolute URLs for
PyPI rendering
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: align docs and release notes with pre-transfer state
- docs/installation.md: qualify PyPI as available 'once official
publishing is enabled' (ownership transfer still pending)
- release.yml: use specify-cli@VERSION syntax (consistent with
README/docs @latest form)
- PR description updated to match
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: revert release notes to match main
The release.yml release notes template should not change in this PR.
PyPI install instructions can be added to release notes in a future
PR once publishing is confirmed working.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: revert README and installation docs to match main
Do not mention PyPI in documentation until the first official PyPI
release has been published. This PR only adds the workflow and readme
metadata in pyproject.toml.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: fail fast if build produces no artifacts
Add if-no-files-found: error to upload-artifact so a missing/empty
dist/ directory fails the build job immediately rather than causing
a confusing failure in the publish job.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: align artifact action pins with repo lockfiles
Update upload-artifact to v7.0.1 and download-artifact to v8.0.1,
matching the pins used in the repo's gh-aw workflow lockfiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The add-community-extension and add-community-preset agentic workflows
never ran for real submissions. Their issue templates auto-applied the
`extension-submission`/`preset-submission` label at creation, which lands
in the `opened` event (not `labeled`), and the external submitter fails
the team-membership activation gate.
Align both with the working bug-assess pattern:
- Add `names: [extension-submission]` / `[preset-submission]` so a
job-level condition gates activation on the specific label.
- Add `github: min-integrity: none` to allow reading external user issues.
- Remove the trigger label from the issue-template auto-labels so a
maintainer applies it during triage — emitting a real `labeled` event
from a team member, which passes activation.
- Recompile lock files with gh aw v0.79.8.
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The committed lock file declared compiler v0.79.8 but contained a github
allow-only guard policy with `"repos": "${GITHUB_REPOSITORY}"`. MCP Gateway
v0.3.25 rejects repo-specific values ("allow-only.repos string must be 'all'
or 'public'"), so the agent job failed at "Start MCP Gateway":
failed to register guard for server "github": invalid server guard policy:
allow-only.repos string must be 'all' or 'public'
Recompiling bug-assess.md with gh-aw v0.79.8 deterministically emits
`"repos": "all"` (the gateway-accepted default when min-integrity is set
without an explicit repos scope), confirming the committed lock was stale.
This also reconciles the manifest setup-action SHA with the value already
used in the workflow body.
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: add bug-assess agentic workflow
Add a gh-aw agentic workflow that triggers when an issue is labeled
`bug-assess`. It assesses the report against the codebase (symptom, suspected
code paths, verdict, severity, remediation) and posts the full assessment.md as
an issue comment, led by a one-line valid?/priority summary. It also applies
severity / needs-reproduction / invalid triage labels.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: disable noop report-as-issue for bug-assess workflow
Set safe-outputs.noop.report-as-issue: false so noop runs on
failures/timeouts no longer create extra report issues, keeping
outputs limited to the issue comment and triage labels.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: clarify bug-assess label filtering is job-level
Reword the Triggering Conditions paragraph to reflect that the
issues:labeled trigger fires for any label and the bug-assess
filtering happens via a job-level condition, not at the trigger.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: tighten bug-assess prompt guardrails
- Add a 65,000-char comment-size limit instruction with explicit
truncation marking so large reports don't fail the safe-outputs
validator.
- Clarify the read-only guardrail: scratch files allowed under
$RUNNER_TEMP, never write into the working tree or commit/push.
- Align the one-line summary verdict vocabulary (Invalid) with the
canonical 'invalid' verdict and Step 8 label rules.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: align bug-assess severity wording and recompile with v0.78.1
- Use 'severity' instead of 'priority' in the Step 7 one-line summary to
match Step 5, the Severity header field, and the severity-* labels.
- Clarify the read-only guardrail: comment + labels are the intended
outputs on success, while the gh-aw harness may separately emit
failure-report artifacts/issues when a run errors or times out.
- Recompile with gh-aw v0.78.1 so the gh-aw-actions/setup pin matches
the repo's other workflow lock files and actions-lock.json.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: add category and effect as first-class fields in extension schema
Add `category` and `effect` as optional fields in the extension schema
(`extension.yml`) and community catalog (`catalog.community.json`).
Schema changes:
- Valid categories: docs, code, process, integration, visibility
- Valid effects: read-only, read-write
- Both fields are optional (backward-compatible with existing extensions)
- Validation raises ValidationError for invalid values when present
Propagation:
- Added `category` and `effect` to all 108 entries in catalog.community.json
(populated from the existing docs/community/extensions.md table)
- Updated extension template with commented category/effect fields
- Updated add-community-extension skill with new JSON template fields
- Updated `specify extension info` CLI output to display category/effect
- Added properties to ExtensionManifest class
Tests:
- test_valid_category: all 5 category values pass
- test_valid_effect: both effect values pass
- test_invalid_category: invalid value raises ValidationError
- test_invalid_effect: invalid value raises ValidationError
- test_category_and_effect_optional: omitting fields still works
Closes#2874
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: make category free-form, keep effect validated
Category is a free-form string (only validated as non-empty when present),
while effect remains restricted to 'read-only' or 'read-write'.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address PR review feedback
- Add type guard before 'in' check for effect to prevent TypeError on
unhashable YAML values (list/dict)
- Comment out category/effect in template so authors must opt in
- Use VALID_EFFECTS constant in test instead of hard-coded values
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: update category docstring to reflect free-form semantics
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: clarify canonical extension effect values
---------
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Add noop: report-as-issue: false to safe-outputs frontmatter in both
add-community-extension and add-community-preset workflows to prevent
them from posting noise comments to the [aw] No-Op Runs tracking issue.
Closes#2747
Both add-community-preset and add-community-extension workflows previously
triggered on issues opened, edited, and labeled events. This caused them to
fire on every new issue and post noisy bot comments explaining the issue
wasn't a submission (see #2739).
Changes:
- Narrow trigger from [opened, edited, labeled] to [labeled] only
- Update prompt instructions to stop silently on non-matching issues
instead of posting a comment
* Add agentic workflows for community catalog submissions
Add GitHub Agentic Workflows that automatically process community
extension and preset submission issues:
- add-community-extension.md: triggered by extension-submission issues,
validates the submission, updates extensions/catalog.community.json
and docs/community/extensions.md, then opens a draft PR
- add-community-preset.md: parallel workflow for preset-submission
issues, updates presets/catalog.community.json and
docs/community/presets.md
Both workflows:
- Trigger on opened, edited, or labeled events (maintainers can
retroactively label pre-existing issues)
- Validate ID format, semver, repo existence, required files, release,
and submission checklists
- Label issues with validation-passed or validation-failed
- Create draft PRs with Closes #N for maintainer review
Also includes gh-aw scaffolding (.github/aw/, .gitattributes lock file
rule, dependabot ignore for gh-aw-actions).
* Suppress whitespace checks on generated .lock.yml files
These files are auto-generated by gh aw compile and contain trailing
whitespace in the ASCII art header and indented YAML blocks that we
cannot control. Add -whitespace attribute to skip git whitespace
checks on them.
* Add Agent Governance extension to community catalog
Add agent-governance extension submitted by @bigsmartben to:
- extensions/catalog.community.json (alphabetical order)
- README.md community extensions table
Closes#2552
* Move community extensions table from README to docs site
- Create docs/community/extensions.md with full extensions table
- Replace ~120-line table in README.md with summary + link to docs site
- Add Extensions entry to docs/toc.yml under Community
- Update add-community-extension SKILL.md references
Simplify the community catalog submission flow to use issue templates
with manual maintainer review (no automation scripts or workflows).
- Add explicit CODEOWNERS entries for catalog.community.json files so
submissions are automatically assigned to a maintainer for review
- Improve preset submission template:
- Add 'Required Extensions' optional field
- Make 'Templates Provided' optional (supports command-only presets)
- Add 'Number of Scripts' optional field
The existing extension and preset issue templates already collect all
required catalog metadata. Maintainers review submissions and manually
update the catalog JSON files.
Closes#2400
* feat(integrations): add Devin for Terminal skills-based integration
- Register DevinIntegration as a SkillsIntegration with .devin/skills/ layout
- Add catalog entry, docs row, and supported-agents listing
- Display /speckit-<command> hyphen syntax in init "Next Steps" panel
(matches Claude/Cursor/Copilot skills mode, since Devin invokes skills
by directory name)
Closes#2346
* fix(devin): implement -p non-interactive dispatch; clarify skills comment
Addresses Copilot review on PR #2364:
- Override build_exec_args() in DevinIntegration to emit
'devin -p <prompt> [--model X]' for non-interactive text dispatch
(verified Devin CLI supports -p / --print). Returns None when
output_json=True since Devin has no structured-output flag, so
CommandStep workflows that require JSON cleanly raise
NotImplementedError instead of crashing on an unknown CLI flag.
requires_cli=True is retained for tool detection.
- Extend the skills-integrations enumeration comment in
specify_cli/__init__.py to include copilot and devin so the
comment matches the code below it.
* fix(devin): always return exec args; document plain-text stdout
Addresses third Copilot review comment on PR #2364.
Returning None from build_exec_args() when output_json=True
incorrectly used the codebase's IDE-only sentinel: workflow
CommandStep checks 'impl.build_exec_args("test") is None' to
detect non-dispatchable integrations (test_workflows.py exercises
this with WindsurfIntegration). The previous implementation made
Devin appear non-dispatchable to all command steps even though it
runs fine via 'devin -p'.
Always return the args list. When output_json is requested, Devin
is still dispatched and returns plain-text stdout instead of
structured JSON; the docstring documents this explicitly.
* docs(devin): include claude in skills-integrations enumeration comment
Addresses Copilot review on PR #2364: the comment listing skills
integrations omitted Claude, which is also a SkillsIntegration
subclass. Updated to keep the comment accurate for future readers.
* test(devin): add build_exec_args regression tests; bump catalog updated_at
Addresses Copilot review on PR #2364, per @mnriem's request to
'address the Copilot feedback, especially the testing ask':
- tests/integrations/test_integration_devin.py: add TestDevinBuildExecArgs
with three regression assertions:
* build_exec_args returns args (not the None IDE-only sentinel)
* --output-format is never emitted, regardless of output_json
* --model flag is passed through correctly
- integrations/catalog.json: bump top-level updated_at to reflect the
Devin entry addition so downstream catalog consumers can detect the
change reliably.
* ci: add windows-latest to test matrix
Add windows-latest to the pytest job OS matrix so tests run on both
Ubuntu and Windows for all Python versions.
Closes#2232
* test: skip bash-specific tests on Windows
Add sys.platform skip markers to all test classes and methods that
execute bash scripts via subprocess, so they are skipped on Windows
where bash is not available. Mixed classes with both bash and pwsh
tests have markers on individual bash methods only.
* test: fix 3 Windows-specific test failures
- test_manifest: use platform-appropriate absolute path (C:\ on Windows
vs /tmp on POSIX) since /tmp is not absolute on Windows
- test_extensions: add agent_scripts.ps entry and platform-conditional
assertions for codex skill fallback variant test
- test_timestamp_branches: use json.dumps() instead of f-string to
properly escape Windows backslash paths in feature.json
* test: extract requires_bash marker and fix PS test skip
Address PR review feedback:
- Define a reusable requires_bash marker in conftest.py and use it
across all 3 test files instead of repeating the skipif inline
- Move test_powershell_scanner_uses_long_tryparse_for_large_prefixes
into its own TestSequentialBranchPowerShell class so it is not
incorrectly skipped on Windows by the class-level bash marker
* test: use runtime bash check instead of platform check
Replace sys.platform == 'win32' with an actual bash invocation test
to handle environments where bash exists but is non-functional (e.g.,
WSL stub on Windows without an installed distro).
* test: reject WSL bash, accept only MSYS/MINGW on Windows
On Windows, verify uname -s reports MSYS, MINGW, or CYGWIN so the WSL
launcher (System32\bash.exe) is rejected — it cannot handle native
Windows paths used by test fixtures. Add SPECKIT_TEST_BASH=1 env var
escape hatch to force-enable bash tests in non-standard setups.
* ci: add comment explaining Windows bash test behavior
* test: early-reject WSL launcher, fix remaining f-string JSON
- Check resolved bash path for System32 before spawning any subprocess
to avoid WSL init prompts and timeout during test collection
- Convert remaining feature_json f-string writes to json.dumps() so
paths with backslashes produce valid JSON on Windows
* test: use bare 'bash' for detection to match test invocation
On Windows, subprocess.run(['bash', ...]) uses CreateProcess which
searches System32 before PATH — finding WSL bash even when
shutil.which('bash') returns Git-for-Windows. Probe with bare 'bash'
(same as test helpers) so the detection matches actual test behavior.