feat(integrations): add Muse Code (muse) agent integration - #4413
Merged
Conversation
Muse Code is Meta's terminal coding agent (binary: muse). It discovers project skills at .agents/skills/<skill-id>/SKILL.md and invokes them via the /speckit-<command> slash shortcut, so wire it up as a SkillsIntegration sharing the .agents/skills layout with Codex/Zed (multi_install_safe=False, same policy as docker-agent). Includes registry wiring, invocation-style mapping, init next-steps, discovery catalog, integrations doc, agent-context default (AGENTS.md), issue templates, and a dedicated test module.
Collaborator
|
Thank you! |
CrazyBaran
pushed a commit
to CrazyBaran/spec-kit
that referenced
this pull request
Sep 3, 2026
…first parent The guard diffed github.event.pull_request.base.sha against the checked-out pull-request merge commit. Those two are not built from the same base: the payload SHA is the base-branch tip from when the PR was opened and is not refreshed when the base moves, while refs/pull/N/merge is rebuilt against the current tip. Any base-branch drift between the two is then attributed to the PR. Observed on github#4395 itself: base.sha was main as of Sep 1 (3eec154), the merge commit was built on main as of Sep 3 (db64869), and two unbumped bundled-extension changes merged in between (github#4413 touching agent-context, github#4286 touching git) failed the guard on a PR that never touched either. Fetch the merge commit with depth 2 so both parents are available and diff against HEAD^1, which is by construction the base the merge was built on. Fail loudly if HEAD is not a merge commit. The script's CLI is unchanged; a regression test reproduces the trap in a throwaway repo (the stale base blames the drift on the PR, HEAD^1 does not). Refs github#4345 Assisted-by: Claude Code (model: claude-fable-5-1) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
mnriem
pushed a commit
that referenced
this pull request
Sep 9, 2026
…n changes (#4395) * ci(extensions): guard bundled extension changes behind a version bump Bundled extensions only reach existing installs through a version bump: `specify extension update` compares the semver in extensions/catalog.json against the installed copy and reports "Up to date" whenever they match. Content changes shipped without a bump go silently stale on every project that already installed the extension (#4345). This guard turns "please remember to bump" into a merge requirement. - `.github/scripts/check_extension_version_bump.py` fails a PR that changes files under `extensions/<id>/` for a catalog-listed extension without increasing that extension's `extension.yml` version (PEP 440 comparison, the same semantics `extension update` uses), and requires `extensions/catalog.json` to stay in sync with each manifest. Non-catalog extensions (the `selftest` fixture and the `template` scaffold) are exempt. - `extension-version-guard.yml` runs the check on pull requests touching `extensions/**`, diffing the PR base against HEAD. - Contract tests pin the working-tree half of the invariant (catalog/manifest version sync, bundled entries shipping a directory); guard-script tests pin the failure behavior against real throwaway git repositories so a parsing change cannot silently disable the guard while CI stays green. Split out of #4351 (part 3 of the series requested in review); refs #4345. Assisted-by: Claude Code (model: claude-fable-5) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): make the extension version guard usable as a required check and quoting-proof Address Copilot review round 1 on #4395. Workflow: drop the `paths: extensions/**` filter. A required status check that is skipped by path filtering stays in "Expected" state and blocks every PR that does not touch extensions/**, which defeats the point of making the guard a merge requirement. The job now runs on every pull request; the script already reports success when nothing under extensions/ changed, so unrelated PRs pass in one short job. Script: read the changed-path list with `git diff --name-only -z`. With git's default core.quotePath, a path containing non-ASCII or control characters is C-quoted with the quotes included (`"extensions/demo/caf\303\251.txt"`), so its first component was no longer `extensions` and an unbumped change to such a file escaped the guard. NUL-delimited output is emitted verbatim; paths are decoded with surrogateescape so an undecodable byte cannot crash the check, and only the ASCII `extensions/<id>/` prefix is ever interpreted. Tests: pin both behaviors. The non-ASCII case fails against the previous script and passes now; the no-extension-changes case backs the workflow change. core.quotePath is pinned to true in the fixture repo so the regression exercises the quoting path even where a developer's global config disables it. Refs #4345 Assisted-by: Claude Code (model: claude-fable-5-1) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(ci): validate a new extension's version even without a base to compare Address @mnriem's review on #4395. For a brand-new extension the guard returned early at "no base manifest" before ever parsing the head version, and the catalog check only tests string equality. A new extension shipped with e.g. `not-a-version` in both extension.yml and catalog.json therefore passed the guard, although ExtensionManifest rejects a version packaging cannot parse (ValidationError "Invalid version") and `extension update` skips catalog entries whose version is invalid - the extension would be uninstallable and never updatable. Parse the head version before the new-extension early return and fail closed with a dedicated message when it is not PEP 440. The base version is now parsed separately, so an unparseable base still fails with the "could not compare versions" message. Tests: add test_new_extension_with_unparseable_version_fails (fails against the previous script, passes now) and point the existing unparseable-version test at the new head-version message, which fires first for that scenario. Refs #4345 Assisted-by: Claude Code (model: claude-fable-5-1) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(ci): diff the extension version guard against the merge commit's first parent The guard diffed github.event.pull_request.base.sha against the checked-out pull-request merge commit. Those two are not built from the same base: the payload SHA is the base-branch tip from when the PR was opened and is not refreshed when the base moves, while refs/pull/N/merge is rebuilt against the current tip. Any base-branch drift between the two is then attributed to the PR. Observed on #4395 itself: base.sha was main as of Sep 1 (3eec154), the merge commit was built on main as of Sep 3 (db64869), and two unbumped bundled-extension changes merged in between (#4413 touching agent-context, #4286 touching git) failed the guard on a PR that never touched either. Fetch the merge commit with depth 2 so both parents are available and diff against HEAD^1, which is by construction the base the merge was built on. Fail loudly if HEAD is not a merge commit. The script's CLI is unchanged; a regression test reproduces the trap in a throwaway repo (the stale base blames the drift on the PR, HEAD^1 does not). Refs #4345 Assisted-by: Claude Code (model: claude-fable-5-1) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(ci): validate every catalog version, not only those of changed extensions Address the "needs a closer look" items from the Copilot reviews on #4395. Invariant 2 skipped catalog entries without an in-repo directory before parsing their version, and never parsed the in-repo manifest version at all - PEP 440 validation lived only in Invariant 1, which sees just the IDs with changed files under extensions/<id>/. Two gaps followed: - a hosted (catalog-only) entry could carry `"version": "not-a-version"` and pass, although `extension update` skips exactly such entries when packaging.Version fails; - promoting an existing uncataloged directory by adding only its catalog entry never entered Invariant 1, so a matching invalid string in manifest and catalog passed the plain equality check. Invariant 2 now runs over every catalog entry: the catalog version must be a non-empty string that parses as PEP 440, and for entries with an in-repo directory the manifest version must parse as well before the equality check. The catalog-side parse alone closes the promotion gap (a valid catalog string plus equality forces a valid manifest string); the manifest parse makes the failure name the manifest precisely. Tests: `_run_guard` now omits the head argument by default, matching the workflow's one-argument invocation, with a separate test for the optional HEAD_REF; new cases cover the hosted-entry and both promotion shapes (the two invalid ones fail against the previous script) plus a valid promotion that must keep passing. The working-tree contract test gains the matching every-catalog-version-parses check. Refs #4345 Assisted-by: Claude Code (model: claude-fable-5-1) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Jakub Baranowski <cr4zybaran@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
therightstuff
pushed a commit
to therightstuff/agentic-sdlc-spec-kit
that referenced
this pull request
Sep 11, 2026
….0.4+adlc1) 11 commits: release 1.0.4 + 7 post-release. New: muse integration (github#4413), workflow slot step (github#4352), bash branch-name sanitizing parity (github#4286), hyphen in command-ref tokens (github#4356), while/do-while steps validation (github#4149), remove unused scope input (github#4401). 5 conflicts resolved. Assisted-by: opencode (model: glm-5.2, supervised)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Muse Code (Meta's terminal coding agent, binary
muse) as a supported Spec Kit integration under the keymuse.Muse Code discovers project skills at
.agents/skills/<skill-id>/SKILL.mdand invokes them via its slash shortcut (/speckit-<command>), so this wires it up as aSkillsIntegrationsharing the.agents/skillslayout with Codex/Zed, withmulti_install_safe=False(same policy asdocker-agent, which shares that directory). Headless dispatch usesmuse exec "<prompt>"with--model/--json(verified againstmuse exec --help).Test selection reasoning
src/specify_cli/integrations/muse/__init__.py(+ registry wiring)museintegration,specify initscaffoldingsrc/specify_cli/_invocation_style.pysrc/specify_cli/commands/init.pyspecify initnext-steps outputintegrations/catalog.jsonspecify integration search/infodiscoverydocs/reference/integrations.md, issue templates,agent-context-defaults.jsonRequired tests
specify integration search muse/info muse— (catalog discovery)Manual test results
Agent: Muse Code (muse, headless
muse exec) | OS/Shell: Linux/bashspecify init <dir> --integration muse --script shspeckit-*/SKILL.mdskills under.agents/skills/; next-steps show/speckit-*invocationsmuse skills validate ./.agents/skills/speckit-planvalid speckit-planfrom the real Muse Code binary/speckit.specifyheadless viamuse execmuse execcannot start in this sandbox (read-only filesystem blocks the session lock dir); needs a run on a normal checkouttest_every_registered_integration_is_in_catalog)Automated:
tests/integrations/test_integration_muse.py(37 tests, new),tests/integrations/test_registry.py, andtests/test_agent_config_consistency.pyall pass. Full suite: 7481 passed; the only 27 failures are pre-existing PowerShell (test_ps_*) tests that also fail on the clean tree in this environment (nopwsh).