Commit Graph

1217 Commits

Author SHA1 Message Date
Manfred Riem
3850fd1a92 chore: release 0.11.2, begin 0.11.3.dev0 development (#3059)
* chore: bump version to 0.11.2

* chore: begin 0.11.3.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-18 08:21:45 -05:00
github-actions[bot]
2c69954227 Update Linear Integration extension to v0.6.0 (#3047)
Update linear extension submitted by @ashbrener:
- extensions/catalog.community.json (version 0.5.0 → 0.6.0, download_url, updated_at)

Closes #3031

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-18 08:19:04 -05:00
Manfred Riem
2dd1ca4fb6 fix: align community submission workflows with bug-assess label trigger (#3046)
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>
2026-06-17 18:00:09 -05:00
Manfred Riem
ee8b3580dd fix(bug-assess): recompile lock so github guard repos is 'all' (#3036)
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>
2026-06-17 17:03:16 -05:00
Copilot
9775c2719e fix(bug-assess): set min-integrity: none to allow reading external user issues (#3030)
* Initial plan

* chore: initial plan for bug-assess integrity fix

* fix: add min-integrity: none to bug-assess workflow to allow reading external user issues

* 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>

* 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>

* 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>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-17 16:26:17 -05:00
Manfred Riem
6db449fc16 feat: add bug-assess agentic workflow (#3023)
* 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>
2026-06-17 15:01:34 -05:00
Ben Buttigieg
0c29d890ab feat: add /speckit.converge command (#3001)
* Add /speckit.converge SDD artifacts and project scaffolding

Dogfood the converge feature through Spec Kit's own workflow:

- spec.md, plan.md, tasks.md, research, data-model, contracts, quickstart
- requirements checklist for the feature
- ratified constitution v1.0.0 (.specify/memory)
- Specify project scaffolding (.specify/, .github agent + prompt files)

Defines a built-in /speckit.converge command that assesses spec/plan/tasks
against the codebase and appends remaining work as new tasks (no git, no
change tracking, append-only). Implementation not yet started.

Excludes unrelated working-tree changes to agents.py, extensions.py,
test_extensions.py, catalog.community.json, and README.md.

* Implement /speckit.converge command

Add the built-in converge command that assesses the codebase against a
feature's spec.md, plan.md, and tasks.md and appends remaining unbuilt work
as new traceable tasks to tasks.md (append-only; no git, no change tracking).

- templates/commands/converge.md: full command body (load artifacts, assess
  code, classify findings missing/partial/contradicts/unrequested, append
  '## Phase N — Convergence' tasks with source-ref + gap-type, read-only
  guardrails, converged branch, handoff, before/after_converge hooks)
- Register converge as a core command across all enumeration sites
  (SKILL_DESCRIPTIONS, _FALLBACK_CORE_COMMAND_NAMES, ARGUMENT_HINTS, and the
  integration test command lists incl. copilot/generic file inventories)
- init.py Next Steps panel + README Core Commands table
- tasks.md: T001-T024 complete (T025 manual quickstart pending)

Full suite green: 2343 passed.

* Record quickstart validation results for /speckit.converge (T025)

All six quickstart scenarios validated (GitHub Copilot agent, macOS/zsh):
S1 gap->appended traceable task, S2 implement+re-converge, S3 converged leaves
tasks.md unchanged, S4 read-only boundaries, S5 missing-prereq stop, S6 cross-
integration install (copilot + windsurf). Automated suite: 2343 passed.

* Record 2026-06-16 re-verification results for /speckit.converge (T025)

* 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 integration upgrade deleting settings.json and dropping script +x

Two upgrade-path bugs surfaced during converge E2E validation:

- copilot upgrade stale-deleted .vscode/settings.json because setup() only tracks the file when it creates it; on upgrade the pre-existing file is merged and left untracked, so Phase 2 stale cleanup removed it. Add an integration-level stale_cleanup_exclusions() hook (CopilotIntegration returns {.vscode/settings.json}) and subtract it from stale_keys.

- shared .specify/scripts/*.sh lost their execute bit because the managed refresh rewrites them with the bundled source mode (often 0o644) and nothing restored perms. Call ensure_executable_scripts() after the managed-refresh block (POSIX only).

Add regression tests in TestIntegrationUpgrade covering both fixes (validated to fail without the fixes).

* fix: resolve markdownlint errors in PR files

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: clean up runtime state files from PR

Remove .specify state files that are per-project runtime artifacts:
- feature.json, init-options.json, integration.json
- manifest files, extension registry, bug artifacts

These are generated by 'specify init' and should not be committed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: fold converge artifacts from #3003 and #3005

- Add speckit.converge Copilot agent and prompt files (#3003)
- Add regression test for Claude argument hints (#3005)
- Remove invalid converge entry from Claude argument hints
- Fix documentation removing branch-prefix fallback claims

Supersedes: #3003, #3005

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove non-converge specify scaffolding from PR

Remove .specify/ artifacts, non-converge .github/agents and prompts,
and copilot-instructions.md that were generated by 'specify init'
and are not part of the converge command feature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove SDD spec artifacts from PR

Remove specs/001-converge-command/ — the spec/plan/tasks/research SDD
artifacts produced while building this feature. spec-kit does not track
a specs/ directory on main (those are outputs of running the workflow on
the repo, not part of the shipped tool).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove generated Copilot converge command files

Remove .github/agents/speckit.converge.agent.md and
.github/prompts/speckit.converge.prompt.md — these are generated by
'specify init --integration copilot' from templates/commands/converge.md
(all __SPECKIT_COMMAND_*__/{SCRIPT} tokens are resolved). main tracks no
.github/agents or .github/prompts files; the template is the source of truth.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: split out unrelated integration-upgrade fix

Move the stale_cleanup_exclusions / executable-bit upgrade fix
(base.py, copilot, _migrate_commands.py, test_integration_subcommand.py)
out of this PR into its own change. This PR is now scoped purely to the
/speckit.converge command.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: add converge to core command template ordering

converge is a core command in SKILL_DESCRIPTIONS but was missing from
_CORE_COMMAND_TEMPLATE_ORDER, so it sorted with the fallback rank. Add it
after 'implement' to keep core-command ordering consistent across
integrations.

Addresses review feedback on #3001.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: make converge findings example neutral

Replace the self-referential sample evidence text in the Convergence
Findings table with a neutral placeholder so agents are less likely to copy
nonsensical template-specific findings into real output.

Co-authored-by: Copilot <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>

* docs: clarify converge scope and hook outcome wording

- Remove FR-specific parenthetical from code-scope rule so it doesn't imply
  a hard FR-001 reference exists in every feature
- Replace unsupported 'pass outcome to hook context' instruction with explicit
  in-session outcome reporting before hook listing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: align converge task example with tasks format

Use  (no colon) in the convergence task example so it
matches tasks-template formatting and downstream expectations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarification of usage

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>

* docs: align converge phase/task-id format with tasks template

- Use  (colon) for consistency with tasks template
- Clarify appended task IDs must be zero-padded ( style)
- Update checklist example to a concrete zero-padded ID ()

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: standardize converge phase heading format

Use  consistently in converge.md (including the
append-only contract section) to match Step 7 and tasks template style.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 14:47:00 -05:00
Ben Buttigieg
84db931f18 fix: preserve .vscode/settings.json and script +x bit on integration upgrade (#3020)
* fix: preserve .vscode/settings.json and script +x bit on integration upgrade

During 'specify integration upgrade', Phase 2 stale-cleanup removes files
present in the old manifest but absent from the new one. Copilot's setup()
merges into an existing .vscode/settings.json and stops tracking it, so the
file was being deleted on upgrade (destroying user settings). Add a
stale_cleanup_exclusions() hook that integrations use to protect such
conditionally-tracked merge targets. Also restore the executable bit on
shared .sh scripts after the managed-refresh step on POSIX.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address review on stale-cleanup fix

- Normalize stale_cleanup_exclusions() to POSIX before subtracting from
  manifest keys, so exclusions built with os.path.join / backslashes still
  match on Windows.
- Strengthen test_upgrade_preserves_existing_vscode_settings to add a
  user-defined key and assert it survives the upgrade (via --force, exercising
  the merge + stale-cleanup path) instead of the brittle after == before check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 14:22:04 -05:00
Huy Do
affbf5ead5 feat(workflows): add from_json expression filter (#2961)
* feat(workflows): add from_json expression filter

Step outputs captured as strings could never become typed values in
templates - the filter set was default/join/map/contains only, so e.g.
a fan-out items: could never consume a step's JSON stdout. Add an
arg-less from_json pipe filter with parse-or-raise semantics: invalid
JSON or non-string input raises a clear ValueError rather than passing
through silently.

Fixes #2960

* fix(expressions): make from_json strict — reject any arguments

Address review (#2961): from_json('x') and from_json() previously fell through to a silent passthrough of the unparsed value. Reject any parenthesized form with a clear error so mis-wired templates fail loudly. Rename test to ...parses_object (JSON under test is an object) and add coverage for the strict no-arguments behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(workflows): document the from_json expression filter

Address Copilot review: the user-facing filter references omitted the
newly added `from_json` filter. Add it to the ARCHITECTURE.md filter table
(with the `{{ steps.emit.output.stdout | from_json }}` example) and to the
filter enumerations in workflows/README.md and docs/reference/workflows.md
so the docs match the evaluator's capabilities.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(workflows): make from_json strictness reject trailing tokens; fix docstring

Address Copilot review:
- Strictness only rejected parenthesized forms, so typos like
  `| from_json)` or `| from_json extra` still fell through to the
  unknown-filter path and silently returned the unparsed value. Match on
  the leading filter token and require the whole filter to be exactly
  `from_json`, so every mis-wired form raises. Extend the rejection test to
  cover the trailing-token cases.
- The module docstring claimed "no imports", which is misleading now that
  the module imports `json`. Reword to state the actual sandbox guarantee:
  templates cannot do file I/O, import modules, or run arbitrary code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-17 13:43:26 -05:00
Copilot
00bff788c9 Add init workflow step to bootstrap projects like specify init (#2838)
* Initial plan

* Add init workflow step to bootstrap projects like `specify init`

* Address review: simplify stderr capture and extract VALID_SCRIPT_TYPES

* Address review: fail fast on non-empty dir, stdout fallback, README force fix

* Populate exit_code/stdout/stderr in non-empty-dir fast-fail

* fix: address three unresolved review comments in InitStep

- Use `with os.scandir(...)` context manager so the iterator is always
  closed even when `any()` short-circuits, preventing file-descriptor
  leaks in long-running workflow runs.
- Guard `os.chdir(prev_cwd)` in the `finally` block with a try/except
  so an `OSError` (e.g. directory deleted) doesn't bypass returning
  the captured `StepResult`.
- Reject non-string `script` values in `validate()` with a clear error
  message, rather than silently passing them through to become
  `--script True` at runtime.

* Potential fix for pull request finding 'Empty except'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* fix: remove no_git and branch_numbering options removed upstream

The --no-git and --branch-numbering flags were removed from `specify init`
on main. Update InitStep to drop these unsupported config fields and fix
tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address review — integration defaults, integration_options, engine-owned dirs

- Apply DEFAULT_INIT_INTEGRATION fallback when neither step config nor
  workflow context provides an integration, so output.integration always
  reflects the actual integration used.
- Add integration_options config field to support --integration-options
  passthrough (required for generic integration and --skills mode).
- Exclude .specify/ from the non-empty directory fast-fail check so that
  here: true works when the engine has already created its run-state
  directory before steps execute.
- Note: mix_stderr=False is not needed — Click 8.2+ captures stderr
  separately by default and the existing try/except handles access.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: implicitly add --force when only engine-owned dirs exist

When the workflow engine creates .specify/workflows/runs/ before steps
execute, the directory is technically non-empty. Previously, specify init
would prompt for confirmation (hanging in unattended mode) unless the
user explicitly set force: true. Now the step detects that only
engine-owned directories (.specify/) are present and implicitly adds
--force so init proceeds without user interaction.

Also fixes the test to exercise the implicit-force path rather than
passing force: True explicitly (which bypassed the check entirely).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: derive VALID_SCRIPT_TYPES from shared constant, fail fast on OSError, include all resolved fields in output

- Derive VALID_SCRIPT_TYPES from SCRIPT_TYPE_CHOICES in _agent_config
  so the valid set cannot drift from the specify init CLI.
- Fail fast with a clear error when os.scandir() raises OSError (e.g.
  permission denied) instead of silently treating the directory as empty.
- Include preset, force, and ignore_agent_tools in all output dicts
  (both fast-fail and normal paths) for consistent interpolation and
  debugging downstream.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: populate stderr from stdout on older Click, fix force comment wording

- When Click does not expose result.stderr (older versions where stderr
  is mixed into stdout), use stdout as stderr on non-zero exit so
  workflows can consistently read steps.<id>.output.stderr for errors.
- Update README inline comment for force: wording to say 'when target
  directory already exists' rather than 'non-empty directory', matching
  the actual specify init behavior for the project: form.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: build argv flags before early returns, use any() for dir scan

- Move argv flag-building (--integration, --script, --preset,
  --ignore-agent-tools) before the non-empty-dir and OSError early
  returns so output['argv'] always reflects the complete command.
- --force is appended after the check since it may be set implicitly.
- Replace list comprehension with any() generator expression to
  short-circuit without allocating a full list of DirEntry objects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: only treat .specify as engine-owned when it is a real directory

A file or symlink named .specify should not be excluded from the
non-empty check. Use entry.is_dir(follow_symlinks=False) to ensure
only an actual directory is considered engine-owned content.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: guard implicit force for engine dirs only, fix integration fallback order

- Only set implicit --force when engine-owned directories (.specify/)
  are actually present. A completely empty directory no longer gets
  --force added unnecessarily.
- Fix integration resolution precedence: resolve step config expression
  first, then fall back to workflow default (also resolved), then to
  DEFAULT_INIT_INTEGRATION. Previously, a step expression resolving to
  falsy would bypass the workflow default entirely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 11:46:51 -05:00
Manfred Riem
bc5bf55258 chore: release 0.11.1, begin 0.11.2.dev0 development (#3022)
* chore: bump version to 0.11.1

* chore: begin 0.11.2.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-17 11:02:59 -05:00
Manfred Riem
9dfa53d2e9 chore: ignore Copilot dogfooding scaffolding in .gitignore (#3019)
* chore: ignore Copilot dogfooding scaffolding in .gitignore

Ignore the directories and files generated by
`specify init --integration copilot` so the dogfooding scaffolding used
during Spec Kit feature development isn't accidentally committed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: fix gitignore trailing whitespace in comment

Remove trailing whitespace and extra comment-only lines in the Copilot dogfooding ignore block.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 10:27:20 -05:00
Jiandong
cedbf484d7 docs: clarify Taskify specify command (#3016) 2026-06-17 08:30:23 -05:00
WOLIKIMCHENG
75df458c37 docs: document evolving specs in existing projects (#2902)
* docs: document evolving specs in existing projects

* docs: reframe evolving specs guide around persistence models

* docs: address evolving specs guide feedback

* docs: address evolving specs review feedback

* docs: require explicit integration in evolving specs update command

---------

Co-authored-by: root <kinsonnee@gmail.com>
2026-06-17 08:17:01 -05:00
Huy Do
071f784dfa feat(workflows): opt-in output_format: json exposes parsed shell stdout as output.data (#2963)
* feat(workflows): opt-in output_format: json exposes parsed shell stdout as output.data

No step that runs external code could hand a typed value to a later
step, so e.g. a fan-out could never consume a runtime-computed
collection. With output_format: json declared, stdout is parsed and
exposed under output.data (raw keys unchanged); a parse failure fails
the step with a clear error. Without the key, behavior is unchanged.

Reference implementation for the proposal in #2962.

Addresses #2962

* test(shell): emit JSON via sys.executable for cross-platform output_format tests

Address review (#2963): replace non-portable echo '{...}' (Windows cmd.exe keeps the single quotes, breaking JSON) with the established '"{py}" "{script}"' pattern using sys.executable + a temp script, so the output_format tests pass on the Windows CI matrix. Also make the validate test's run inert (exit 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-17 08:09:17 -05:00
Huy Do
1ee2b626a8 fix: non-zero exit code when a workflow run ends failed or aborted (#2959)
* fix: non-zero exit code when a workflow run ends failed or aborted

workflow run and workflow resume printed Status: failed (or emitted the
--json payload) and exited 0, so scripts and CI could not rely on the
process exit code. Map terminal outcomes: failed|aborted -> 1,
completed|paused -> 0, on both the text and --json paths.

The previous exit-0-on-failed behavior was pinned by
test_workflow_run_failing_yaml_without_project; the pin is updated to
the new contract.

Fixes #2958

* test: portable exit-code step commands + cover resume failed->exit-1

Address review (#2959): replace non-portable run: 'true'/'false' with 'exit 0'/'exit 1' (Windows cmd.exe has no true/false builtins under shell=True), and add an end-to-end 'workflow resume' test asserting a resumed failed run exits non-zero.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-17 08:02:00 -05:00
Seiya Kojima
811a3aa447 fix(skills): preserve non-ASCII characters in skill frontmatter (#2917)
* fix(skills): preserve non-ASCII chars in skill frontmatter

Skill SKILL.md frontmatter descriptions containing non-ASCII
characters were escaped to \uXXXX / \xXX sequences because
yaml.safe_dump() was called without allow_unicode=True.

- Add allow_unicode=True to the 7 skill/command frontmatter
  safe_dump sites (extensions, presets, claude integration)
- Add regression tests for the render and extension-install paths

Follows the approach of #1936; encoding="utf-8" is already set on
the affected write paths, so no encoding change is needed here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(_utils): add dump_frontmatter helper

Centralize skill/command frontmatter YAML serialization into a single
_utils.dump_frontmatter helper so no call site can drop allow_unicode or
diverge on formatting. Route the 7 existing sites through it and drop a
now-unused local yaml import.

Switch the extension test fixtures to yaml.safe_dump for parity with the
production safe-dump/safe-load codepaths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 07:57:54 -05:00
Jina Park
de18d21b1c fix: prevent extension self-install from deleting source dir (#2990) (#2991)
* fix: prevent extension self-install from deleting source dir (#2990)

`specify extension add <path> --dev --force` permanently deleted the
extension directory without registering it when the source path resolved
to the extension's own install location (`.specify/extensions/<id>`).

With `--force`, `install_from_directory()` removed the existing
installation (the source) and then `shutil.copytree()` tried to copy from
the now-deleted directory, destroying it and crashing.

Add a guard that fails fast with a clear ValidationError when the resolved
source path equals the install destination, before any destructive
operation runs. Includes a regression test asserting the directory and its
contents survive.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: harden extension self-install guard

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 07:56:17 -05:00
Manfred Riem
75aee19c6e fix: disable Rich Live transient mode on Windows to prevent PS 5.1 hang (#2938)
* fix: disable Rich Live transient mode on Windows to prevent PS 5.1 hang

PowerShell 5.1's legacy console host does not reliably support VT escape
sequences. Rich's Live(transient=True) attempts cursor restoration on
context exit, which hangs indefinitely on that console.

Set transient=False when sys.platform == 'win32' in both init.py (progress
tracker) and _console.py (select_with_arrows). The only cosmetic effect is
that progress output remains visible after completion on Windows.

Fixes #2927

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: address review feedback on test quality

- Use captured['transient'] instead of .get() for clearer KeyError on failure
- Source guards now assert both the platform check AND transient=_transient usage
- Remove unused imports (MagicMock retained as it's used, removed pytest)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: use regex in source guards for resilience to formatting changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: use single DOTALL regex to verify assignment flows into Live()

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: skip duplicate tracker print on Windows when transient=False

When transient is False, Rich leaves the Live output on screen. The
subsequent console.print(tracker.render()) would duplicate it. Gate
it behind _transient so Windows users see the tracker exactly once.

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>
2026-06-17 06:48:42 -05:00
Thorsten Hindermann
ae23a84677 Update a11y-governance preset to v0.4.0 (#2981) 2026-06-17 06:44:32 -05:00
Manfred Riem
3e69233adb chore: release 0.11.0, begin 0.11.1.dev0 development (#3012)
* chore: bump version to 0.11.0

* chore: begin 0.11.1.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-16 18:07:28 -05:00
Copilot
c52ccd7dc7 Add workflow step catalog — community-installable step types (#2394)
* Initial plan

* Add workflow step catalog: StepRegistry, StepCatalog, CLI commands, and tests

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/2885e646-477d-4df8-b9a3-06d8cb29e748

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Potential fix for pull request finding 'An assert statement has a side-effect'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Address PR review: path traversal, cache robustness, collision check, failed-to-load display

- Add resolve()+relative_to() path traversal guards in workflow_step_add and
  workflow_step_remove to prevent directory escape via step_id
- Harden _is_url_cache_valid in both StepCatalog and WorkflowCatalog to
  coerce fetched_at to float and catch TypeError/ValueError
- Check STEP_REGISTRY and StepRegistry before installing to prevent
  collisions with built-in step types or already-installed steps
- Show 'Custom (installed, failed to load)' section in workflow step list
  for steps in the registry that failed to load into STEP_REGISTRY

* Fix StepRegistry shape validation and StepCatalog empty-YAML handling

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/0dca6393-f5a9-40de-bb5c-77ba6af033d2

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Polish: rename _default to default_registry, strengthen unreadable-file test

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/0dca6393-f5a9-40de-bb5c-77ba6af033d2

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Address PR review: atomic install, hostname validation, cache resilience, no dynamic imports in list/info

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/3e18fef0-e2e6-4b3e-9e8d-9adb1e5e464e

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Fix shutil.move with existing step_dir: remove before move to avoid subdirectory nesting

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/3e18fef0-e2e6-4b3e-9e8d-9adb1e5e464e

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Call load_custom_steps at execution time; enforce hostname in _safe_fetch and _validate_url

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/73865880-fb25-4061-a43e-4e4b4d1c4de6

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Wrap YAML parsing in try/except; atomic step install via os.rename() under same fs

Agent-Logs-Url: https://github.com/github/spec-kit/sessions/ff915bc5-ec7e-4e6a-b505-35f5795250df

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Validate YAML root is a dict in _load_catalog_config and workflow_step_add; fix WorkflowCatalog hostname validation

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* Fix load_custom_steps() package imports and add reserved step ID validation

* Move _re/_sys imports out of loop and _RESERVED_STEP_IDS to module level

* Address review: collision-resistant module names, extra_files support, remove orphan dir

* Harden extra_files: warn on non-dict, resolve symlinks in path traversal check

* Switch _safe_fetch and StepCatalog._fetch_single_catalog to use open_url for auth consistency

* Harden step_id validation against path-segment tricks; raise on StepRegistry.save() OSError

* Clean up sys.modules on broken step packages; handle StepValidationError in step add/remove

* Address review thread: int-coerce priorities, sys.modules cleanup, _require_specify_project, registry-first remove

* fix: normalize workflow step catalog metadata fallbacks

* fix: address latest workflow step and catalog review findings

* Handle non-string extra_files keys in workflow step add

* Harden StepRegistry symlink reads and extra_files path/URL validation

* Harden custom step loader and step remove against symlinks and OSError

* Fix StepCatalog.search() to coerce non-string fields before joining

* Fix WorkflowCatalog YAML parsing error handling and isinstance checks

* Harden step registry save and custom step/catalog ID handling

* Harden cache validation and staging OSError handling

* Address review: reorder symlink guard and split mixed test

- Move symlink-parent check before is_dir() in load_custom_steps() so
  we never stat an external target through a symlink
- Split test_get_merged_steps_normalizes_list_ids_to_strings into two
  focused tests: one for list-id normalization, one for get_step_info
  return values

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review: symlink-before-stat in loader, restore registry on rmtree failure

- load_custom_steps(): check is_symlink() before is_dir() on step
  directories so symlinked entries are skipped without statting external
  targets
- workflow_step_remove: restore the registry entry when shutil.rmtree()
  fails so filesystem and registry state stay consistent and a future
  'step add' isn't blocked

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden step_id validation and file-write error handling

- _validate_step_id_or_exit: reject whitespace-only/padded IDs,
  Windows-invalid characters (<>:"|?*), control characters, trailing
  dots/spaces, and Windows reserved device names (con, nul, etc.)
- Wrap step.yml/__init__.py staging writes in OSError handler
- Wrap extra_files disk writes (mkdir + write_bytes) in OSError handler
  that names the failing relative path
- Registry rollback on rmtree failure: restore verbatim metadata and
  emit a warning if the restore itself fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review: cache symlink guard, verbatim registry rollback, Windows test fix

- StepCatalog: add _is_cache_path_safe() guard that checks for symlinks
  in .specify/workflows/steps/.cache path; skip cache reads and writes
  when any component is symlinked to prevent writes outside project root
- Registry rollback: write metadata directly to registry.data['steps']
  and call save() instead of using add() which overwrites timestamps
- temp_dir fixture: use ignore_errors=True on Windows to avoid flaky
  teardown from locked file handles (WinError 32)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Simplify exec_module call by removing redundant nested try/except

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix empty YAML tolerance in WorkflowCatalog.add_catalog, scope ignore_errors to Windows

- WorkflowCatalog.add_catalog(): treat None from yaml.safe_load() (empty
  file) as an empty mapping instead of raising 'corrupted'
- temp_dir fixture: limit ignore_errors to sys.platform == 'win32' so
  real cleanup issues surface on non-Windows platforms

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Chain exceptions in _load_catalog_config for both catalog classes

Add 'from exc' to preserve root cause in tracebacks while keeping
clean user-facing messages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make default catalog tests hermetic by isolating HOME

Monkeypatch Path.home() to project_dir and clear catalog env vars so
tests don't break on machines with a real ~/.specify/step-catalogs.yml
or ~/.specify/workflow-catalogs.yml.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix falsy ID handling in _get_merged_steps for list-based catalogs

Check for None explicitly instead of using 'or' which drops valid
falsy IDs like 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Compare reserved step IDs case-insensitively for filesystem safety

On case-insensitive filesystems (Windows, common macOS), variants like
STEP-REGISTRY.JSON would collide with the actual registry file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add explanatory comments to intentional empty except blocks

Document why cache-read failures are silently ignored in both
WorkflowCatalog and StepCatalog _fetch_single_catalog methods.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 18:03:45 -05:00
Pascal THUET
9cd20c6c25 feat(dev): add integration scaffolder (#2685)
* feat(dev): add integration scaffolder

* fix(dev): address integration scaffold review feedback

* fix(dev): address scaffold follow-up review

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(dev): default scaffolded integrations to multi_install_safe = False

The scaffold template emitted `multi_install_safe = True` alongside a
placeholder `context_file = "AGENTS.md"`. Registered as-is, that violates the
registry contract (test_safe_integrations_have_distinct_context_files): codex
already pairs AGENTS.md with multi_install_safe = True, so the generated
boilerplate would collide on first registration.

Default the scaffold to False (matching IntegrationBase) so generated code is
registry-test-friendly out of the box; contributors opt in once they pick a
unique context_file. Aligns the generated test skeleton and both scaffold
tests, which previously contradicted each other (one expected True, one False).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): harden scaffold writes and accept case-insensitive --type

- Guard scaffold_integration() against symlinked target directories: walk
  each path component under the repo root and refuse symlinked dirs, then
  confirm the write destination resolves inside the repo (mirrors the
  manifest directory guard). Prevents scaffolding outside the repo when a
  contributor's integrations/tests path is symlinked.
- Make the `--type` click.Choice case-insensitive so `--type YAML` is
  accepted, matching scaffold_integration()'s strip()/lower() normalization
  instead of rejecting at the CLI layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): report scaffold filesystem failures as a clean CLI error

The `dev integration scaffold` command only caught FileExistsError/ValueError,
so an OSError raised during mkdir()/write_text() (permission denied, read-only
checkout, a path component that is a file, ...) bubbled up as a traceback
instead of a clean error + exit code. Broaden the handler to OSError (which
also covers FileExistsError) and add coverage for the filesystem-error path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): move scaffold command under integration

* fix(dev): roll back partial scaffold writes

* fix(dev): correct lint docs and generated test docstring

- local-development.md: ruff check src/ is enforced in CI, not absent
- scaffolded test docstring: drop misleading 'scaffold' wording

* fix(scaffold): create only leaf integration directory

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:48:40 -05:00
Maksim Kudriavtsev
497ca074ed Add Command Density preset to community catalog (#3006) 2026-06-16 17:40:20 -05:00
Alicia Sykes
6d057b6239 fix(tests): don't run PowerShell tests via WSL-interop powershell.exe (#2971)
* fix(tests): don't run PowerShell tests via WSL-interop powershell.exe

* fix(tests): applies copilot feedback, with rename
2026-06-16 17:36:24 -05:00
Ahmet TOK
1150d32aee Add Zed integration (#2780)
* feat: add Zed integration

* fix: update integrations stats grid to 31 for consistency

* fix: address Copilot review feedback

- Remove non-actionable --skills flag from ZedIntegration (Zed is always
  skills-based, like Agy)
- Align zed_skill_mode predicate with ai_skills for consistency across
  init output and hook rendering
- Consolidate claude/cursor/zed slash-skill return blocks in
  _render_hook_invocation to reduce duplication
- Override test_options_include_skills_flag for Zed (no --skills flag)

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: address Copilot review round 2

- Make zed_skill_mode unconditional in hook rendering (Zed is always
  skills-based, no --skills option)
- Add test_init_persists_ai_skills_for_zed that exercises the actual
  CLI init path and verifies HookExecutor renders /speckit-plan
  without manual init-options manipulation

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: address copilot review feedback for zed integration

- Update integration count from 31 to 33 in docs/index.md (32 integrations + Generic)
- Make zed_skill_mode unconditional to match extensions.py behavior
- Consolidate slash-skill integrations into a set for consistency
- Move os import to module level in test_integration_zed.py

* fix: refine slash-skill logic and ai-skills validation

- Fix slash-skill integrations: Claude/Cursor require ai_skills=true; Zed/Agy/Devin are always skills
- Allow --ai-skills with --integration (not just --ai) to fix validation error

* fix: remove unused variables and update ai-skills help text

- Add agy_skill_mode and devin_skill_mode variables to fix F841 lint error
- Use all skill mode variables in the slash-skill conditional check
- Update --ai-skills help text to reflect it works with --integration too

* fix: add trae_skill_mode to hook invocation for consistency

Trae is a SkillsIntegration like Zed/Agy/Devin, so it should also be treated
as always-skills-based in hook invocation rendering.

* fix: make Agy always skills-based for consistency

AgyIntegration is a SkillsIntegration subclass with no --skills option,
so it should be treated as always skills-based (like Zed, Devin, Trae).
This aligns init.py skill mode detection with extensions.py hook rendering.

* fix: gate agy_skill_mode and refactor _render_hook_invocation to use sets

Addressed Copilot review comments:

- Restored _is_skills_integration guard on agy_skill_mode in init.py
  to be defensive about runtime integration type.
- Refactored _render_hook_invocation() in extensions.py to use
  always_slash/conditional_slash frozensets instead of individual
  per-agent booleans, eliminating unused variables (F841) and making
  it harder for conditions to drift between integrations.
- Centralized slash-skill determination so adding a new unconditional
  slash-skill integration is a one-key addition.

* fix: address latest Copilot review comments

- Added copilot to CONDITIONAL_SLASH_AGENTS for consistent
  hook invocation rendering with init.py
- Moved always_slash/conditional_slash frozensets to module
  scope to avoid per-call reallocation
- Replaced manual os.chdir() with monkeypatch.chdir() in test
- Overrode test_options_include_skills_flag for Zed (no --skills)

* fix: address latest Copilot review comments

- Removed redundant local import yaml in _register_extension_skills
  (yaml is already imported at module scope)
- Split --ai-skills usage hint into two separate print statements
  for better readability
- Changed integrations count from '33' to '30+' to avoid future drift

* fix: re-add _is_skills_integration definition lost in merge

The _is_skills_integration variable was accidentally dropped during the
web UI merge resolution of upstream/main's removal of legacy --ai flags.
Re-added the definition via isinstance(resolved_integration, SkillsIntegration)
check so that skill-mode booleans work correctly.

* fix: gate zed_skill_mode on _is_skills_integration for consistency

Aligns zed_skill_mode with the other skills-based agents (codex, claude,
cursor-agent, copilot) which all use _is_skills_integration gating.
Since ZedIntegration extends SkillsIntegration, behavior is unchanged.

* fix: remove unused claude_skill_mode and cursor_skill_mode locals in _render_hook_invocation

These variables became unused after the refactor to ALWAYS_SLASH_AGENTS /
CONDITIONAL_SLASH_AGENTS sets. Claude and Cursor-Agent are now handled by the
CONDITIONAL_SLASH_AGENTS path, so the separate boolean locals are dead code.

Fixes ruff F841 and addresses Copilot review feedback that was repeated across
multiple review rounds.

* fix: align agy/trae invocation format in init next-steps with hook rendering and build_command_invocation

- Moved agy and trae from '-<name>' (dollar/Codex format) to
  '/speckit-<name>' (slash format) in _display_cmd() to match:
  - HookExecutor._render_hook_invocation() (ALWAYS_SLASH_AGENTS for trae,
    CONDITIONAL_SLASH_AGENTS for agy)
  - SkillsIntegration.build_command_invocation() (default: /speckit-<name>)
- The '$' prefix is specific to Codex; all other skills agents use '/'.

* fix: address Copilot review comments on hook invocation consistency

- Add is_slash_skills_agent() helper to extensions.py to centralize the
  agent-to-invocation-format mapping, reducing drift risk between
  HookExecutor._render_hook_invocation() and init.py _display_cmd()
- Use the shared helper in both locations; init.py now imports and
  delegates to is_slash_skills_agent() instead of maintaining its own
  per-agent boolean matrix
- Fix test_hooks_render_skill_invocation to use ai_skills=False,
  proving Zed renders /speckit-<name> unconditionally
- Add parameterized TestSlashSkillsSets covering all agents in
  ALWAYS_SLASH_AGENTS and CONDITIONAL_SLASH_AGENTS with ai_skills
  both true and false

* fix: address Copilot review comments on type safety and test API

- Make is_slash_skills_agent() accept str | None to match its call sites
  (init_options.get("ai") can return None)
- Refactor TestSlashSkillsSets to use public execute_hook() API instead of
  private _render_hook_invocation() method

* fix: address Copilot review comments on typing and naming clarity

- Add from __future__ import annotations to extensions.py so PEP 604
  unions (str | None) are safe regardless of Python version
- Add clarifying _ai_skills_enabled local variable in init.py's
  _display_cmd() to make the semantic meaning explicit when passing it
  to is_slash_skills_agent()

* fix: move invocation-style logic into shared _invocation_style module

- Extract ALWAYS_SLASH_AGENTS, CONDITIONAL_SLASH_AGENTS, and
  is_slash_skills_agent() from extensions.py into new _invocation_style.py
  module, eliminating the awkward init.py -> extensions.py import
  dependency for invocation-style decision logic
- Both HookExecutor._render_hook_invocation() and init.py _display_cmd()
  now import from the shared module instead of one subsystem importing
  from the other
- Revert /SKILL.md change: the leading slash is semantically significant
  (path component vs filename suffix)

* fix: add None guard before i.options() in test_options_include_skills_flag

get_integration() returns IntegrationBase | None, so i.options()
is a type error without a None check.

* fix: override test_options_include_skills_flag for Zed (always skills, no --skills flag)

Zed is always skills-based and doesn't expose a --skills option.
Override the inherited base test to assert --skills is absent.

* fix: rename test and skip inherited test_options_include_skills_flag for Zed

- Skip inherited test_options_include_skills_flag (not applicable — Zed
  is always skills-based with no --skills flag)
- Add test_options_do_not_include_skills_flag with correct name matching
  the assertion (--skills is absent)

* fix: add defensive non-string check in is_slash_skills_agent

Reject non-string values for selected_ai to prevent TypeError from
set membership checks when persisted init-options contain corrupted
data (e.g. list or dict instead of string).

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-16 17:29:08 -05:00
Thorsten Hindermann
0fad994e86 Update architecture-governance preset to v0.5.0 (#2929)
* Update architecture-governance preset to v0.3.0

* Update architecture-governance preset to v0.4.0

* Update architecture-governance preset to v0.5.0

* Address Copilot wording feedback for architecture preset
2026-06-16 17:20:28 -05:00
Manfred Riem
b1348d1f01 Update Superpowers Implementation Bridge extension to v1.1.0 (#3011)
Update speckit-superpowers-bridge extension submitted by @lihan3238:
- extensions/catalog.community.json (version, download_url)

Closes #3009

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 17:09:33 -05:00
Thorsten Hindermann
79b3f6733a Update isaqb-architecture-governance preset to v0.2.0 (#2984)
* Update isaqb-architecture-governance preset to v0.2.0

* Address Copilot wording feedback for isaqb preset
2026-06-16 16:42:43 -05:00
Thorsten Hindermann
6c098ce1e0 Update security-governance preset to v0.6.0 (#2932)
* Update security-governance preset to v0.5.0

* Update security-governance preset to v0.6.0
2026-06-16 16:10:27 -05:00
Eldar Shlomi
00c15bc54c chore: update CITATION.cff to v0.10.2 (2026-06-11) (#2966)
CITATION.cff was created at v0.7.3 (2026-04-17) and has not been
updated since. The latest stable release is v0.10.2, released on
2026-06-11. This brings the citation metadata in sync with the
published release so tools that ingest CITATION.cff (Zenodo, GitHub's
"Cite this repository" widget, citation managers) surface the correct
version.

Verification:
- `gh release list --repo github/spec-kit --limit 1` → v0.10.2 / 2026-06-11
- CHANGELOG.md `## [0.10.2] - 2026-06-11` confirms the date
- pyproject.toml `version = "0.10.3.dev0"` confirms 0.10.2 is latest stable

AI-assisted contribution.
2026-06-16 15:56:35 -05:00
Manfred Riem
3b6b6f9f33 chore: release 0.10.4, begin 0.10.5.dev0 development (#3010)
* chore: bump version to 0.10.4

* chore: begin 0.10.5.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-16 15:36:00 -05:00
Huy Do
36fd5f6f49 fix: fail loudly when a fan-out 'items' expression does not resolve to a list (#2957)
A non-list result from the items expression is a wiring error (the
template did not resolve to a collection); silently fanning out over
zero items hides it until a confusing downstream failure. Fail the
step with an error naming the expression instead. An explicit empty
list remains valid input.

Fixes #2956
2026-06-16 15:33:11 -05:00
darion-yaphet
f20e8ee6f7 refactor: move preset command handlers to presets/_commands.py (PR-6/8) (#2826)
* refactor(presets): convert presets.py module to presets/ package

Pure structural move to mirror integrations/. presets.py becomes
presets/__init__.py with relative imports rebased one level deeper.
No behavior change; public import surface (from .presets import ...)
preserved. Prepares for co-locating preset command handlers in PR-6/8.

* refactor: move preset command handlers to presets/_commands.py (PR-6/8)

Cut the preset_app / preset_catalog_app Typer groups and all 12 command
handlers out of __init__.py into presets/_commands.py, exposing register(app)
— mirrors the integration co-location from PR-5. __init__.py now registers
via _register_preset_cmds(app), dropping ~620 lines (3282 -> 2663).

Handlers lazy-import root helpers (_require_specify_project, get_speckit_version,
_locate_bundled_preset, _display_project_path) via 'from .. import' so test
monkeypatching of specify_cli.<helper> keeps working. _locate_bundled_preset
kept as an explicit re-export in __init__.py for that resolution path.

CLI surface and public imports unchanged. Full suite: 3162 passed, 40 skipped.
2026-06-16 14:52:12 -05:00
Thorsten Hindermann
3b6c4e7419 Update agent-parity-governance preset to v0.3.0 (#2982) 2026-06-16 14:04:55 -05:00
Thorsten Hindermann
04c74eef49 Update cross-platform-governance preset to v0.2.0 (#2983)
* Update cross-platform-governance preset to v0.2.0

* Address Copilot wording feedback for cross-platform preset
2026-06-16 13:58:02 -05:00
Manfred Riem
194fd08bd8 Add Data Model Diagram extension to community catalog (#2922)
* Add Data Model Diagram extension to community catalog

Add data-model-diagram extension submitted by @benizzio to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #2920

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix author field to match extension.yml manifest

Use the full author name from extension.yml rather than GitHub username.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align entry timestamps with catalog updated_at date

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>
2026-06-16 13:44:52 -05:00
Manfred Riem
b22834bd4a Add Spec Kit TLDR extension to community catalog (#3007)
Add tldr extension submitted by @qurore to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #2987

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 13:30:03 -05:00
Manfred Riem
860a49edb1 docs: add guide for handling complex features (#3004)
* docs: add guide for handling complex features

Add a Concepts page documenting strategies for dealing with large or
complex features where context window exhaustion degrades agent
performance during implementation. Covers limiting tasks per run,
sub-agent delegation, combining both, and decomposing into smaller
specs, with a guideline table for choosing an approach.

Closes #2986

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: address review feedback on complex features guide

Use task IDs (T001-T010) instead of bare numbers to match the tasks.md
template format, and add the combined scoping + delegation approach to
the selection table for completeness.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: align complex features guide with command naming conventions

Use the full /speckit.implement command name throughout, match the
command template wording ('must consider'), and use the product names
GitHub Copilot CLI and the GitHub Copilot extension for VS Code.

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>
2026-06-16 13:20:36 -05:00
Manfred Riem
7a3710242c Add Loop Engineering extension to community catalog (#3002)
Add loop extension submitted by @formin to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #2977

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 10:10:03 -05:00
Manfred Riem
97d5376fc7 Update MemoryLint extension to v1.5.1 (#3000)
Update memorylint extension submitted by @RbBtSn0w:
- extensions/catalog.community.json (version, download_url, description, provides)
- docs/community/extensions.md community extensions table

Closes #2974

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 09:56:48 -05:00
Manfred Riem
4d871d7a5b chore: release 0.10.3, begin 0.10.4.dev0 development (#2999)
* chore: bump version to 0.10.3

* chore: begin 0.10.4.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-16 09:40:48 -05:00
Manfred Riem
33fefde268 Update Superpowers Bridge extension to v1.6.0 (#2998)
* Update Superpowers Bridge extension to v1.6.0

Update superb extension submitted by @RbBtSn0w:
- extensions/catalog.community.json (version, download_url, description, provides, updated_at)
- docs/community/extensions.md community extensions table

Closes #2973

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align superb catalog author and tags with v1.6.0 manifest

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>
2026-06-16 09:34:35 -05:00
Manfred Riem
70f9242be9 Add Improve Extension to community catalog (#2997)
Add improve extension submitted by @d0whc3r to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #2972

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 09:16:56 -05:00
Manfred Riem
7c1d4212db Update Product Forge extension to v1.7.0 (#2996)
Update product-forge extension submitted by @VaiYav:
- extensions/catalog.community.json (version, download_url, description, tags, documentation, updated_at)
- docs/community/extensions.md community extensions table

Closes #2967

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 09:03:35 -05:00
Manfred Riem
4f5c4971c0 Update Linear Integration extension to v0.5.0 (#2995)
Update linear extension submitted by @ashbrener:
- extensions/catalog.community.json (version, download_url, updated_at)

Closes #2953

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 08:35:05 -05:00
Manfred Riem
13b8db2d87 Update Superpowers Implementation Bridge extension to v1.0.3 (#2993)
Update speckit-superpowers-bridge extension submitted by @lihan3238:
- extensions/catalog.community.json (version, download_url, updated_at)

Closes #2945

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-16 07:52:07 -05:00
Ben Lawson
68980c9a4e Update Ralph community extension to v1.1.1 (#2861) 2026-06-16 06:54:26 -05:00
Manfred Riem
1b0556c711 Update Linear Integration extension to v0.4.0 (#2942)
Update linear extension submitted by @ashbrener:
- extensions/catalog.community.json (version, download_url, changelog, updated_at)

Closes #2931

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-11 10:10:24 -05:00
Manfred Riem
f2710f32cf Update DocGuard — CDD Enforcement to v0.26.0 (#2941)
Update docguard extension submitted by @raccioly:
- extensions/catalog.community.json (version, download_url, updated_at)

Closes #2928

Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-11 09:18:11 -05:00