Skip to content

Fix extension skill command reference rendering - #4116

Open
WOLIKIMCHENG wants to merge 3 commits into
github:mainfrom
WOLIKIMCHENG:fix/3451-extension-skill-command-refs
Open

Fix extension skill command reference rendering#4116
WOLIKIMCHENG wants to merge 3 commits into
github:mainfrom
WOLIKIMCHENG:fix/3451-extension-skill-command-refs

Conversation

@WOLIKIMCHENG

Copy link
Copy Markdown
Contributor

Description

Normalizes literal slash-dot command references when extension commands are rendered into generated SKILL.md files for skills-based integrations.

This keeps the existing __SPECKIT_COMMAND_*__ token path intact, and adds coverage for literal references such as /speckit.foo.bar so generated extension skills use the active integration's invocation style ($speckit-foo-bar, /speckit-foo-bar, or /skill:speckit-foo-bar).

Scope is limited to generated extension skills. Bare prose, native skill references, URLs, and file-like references are preserved.

Fixes #3451.

Testing

  • .venv/bin/python -m pytest tests/test_extension_skills.py -q
  • .venv/bin/python -m pytest tests/test_agent_config_consistency.py -q
  • UV_CACHE_DIR=/tmp/spec-kit-uv-cache uvx ruff@0.15.0 check src tests
  • git diff --check -- src/specify_cli/extensions/__init__.py tests/test_extension_skills.py extensions/EXTENSION-USER-GUIDE.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Normalizes literal slash-dot command references in generated extension skills.

Changes:

  • Adds integration-specific command rendering.
  • Preserves native, URL, bare, and selected file-like references.
  • Adds tests and author guidance.
Show a summary per file
File Description
src/specify_cli/extensions/__init__.py Normalizes literal command references.
tests/test_extension_skills.py Tests invocation styles and exclusions.
extensions/EXTENSION-USER-GUIDE.md Documents portable command references.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

src/specify_cli/extensions/init.py:1628

  • The right boundary both accepts a following / and rejects every following ., so /speckit.foo.bar/scripts/run.sh is incorrectly rewritten even though it is path-like, while the ordinary sentence Run /speckit.foo.bar. is not rewritten at all. Reject / as a path continuation, but treat . as a continuation only when another identifier segment follows.
                    r"(?![A-Za-z0-9_.-])"
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/specify_cli/extensions/__init__.py Outdated
Comment on lines +1613 to +1620
if command_name.rsplit(".", 1)[-1] in {
"json",
"md",
"toml",
"txt",
"yaml",
"yml",
}:

@mnriem mnriem left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback

@kinchengni

Copy link
Copy Markdown

Updated to address the review feedback: command reference rewriting now uses the manifest-declared command names and aliases instead of suffix-based exclusions, with coverage for .json command aliases, path continuations, and trailing punctuation.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

selected_ai, frontmatter, body, self.project_root, extension_id=manifest.id
)
body = _resolve_command_ref_tokens(body)
body = _normalize_literal_slash_command_refs(body)
@mnriem

mnriem commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

src/specify_cli/extensions/init.py:1615

  • This fallback rendering path has the same incomplete whitelist: only the current manifest's names are eligible. A generated extension skill that references a core command such as /speckit.tasks (see extensions/template/commands/example.md:204) or another installed extension remains dotted and is still unusable for Codex/Kimi; the regex also excludes the single-suffix core form. Include core/installed commands and match speckit.<name>, or normalize all isolated slash-dot invocations.

This issue also appears on line 1630 of the same file.

            known_command_names = {
                cmd["name"]
                for cmd in manifest.commands
                if isinstance(cmd.get("name"), str)
            }

src/specify_cli/extensions/init.py:1635

  • This regex still rewrites known commands embedded in URL query/fragment values. For example, https://example.test/redirect?next=/speckit.foo.bar passes the lookbehind at = and becomes an invalid URL, contradicting the stated URL-preservation scope. Detect and skip complete URL tokens (including query and fragment content) before replacing command references.
            return re.sub(
                (
                    r"(?<![\w$:/-])"
                    r"/(?P<command>speckit\.[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+)"
                    r"(?!/)"
                ),

src/specify_cli/agents.py:718

  • The boundary check does not actually preserve all URLs as promised: in https://example.test/redirect?next=/speckit.foo.bar, the slash is preceded by =, so a known command is rewritten and the URL is corrupted (for example to next=$speckit-foo-bar). Exclude matches within complete URL tokens rather than relying only on the immediately preceding character.
            return re.sub(
                (
                    r"(?<![\w$:/-])"
                    r"/(?P<command>speckit\.[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+)"
                    r"(?!/)"
                ),
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/specify_cli/agents.py
Comment on lines +694 to +698
known_command_names = {
command["name"]
for command in commands
if isinstance(command.get("name"), str)
}
@mnriem

mnriem commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Extension command references not rewritten for skills-based integrations (Codex), breaking cross-command invocation

4 participants