Skip to content

Stage 5: Skills, Generic & Option-Driven Integrations (#1924)#2052

Merged
mnriem merged 9 commits intogithub:mainfrom
mnriem:issue-1924-stage-5
Apr 2, 2026
Merged

Stage 5: Skills, Generic & Option-Driven Integrations (#1924)#2052
mnriem merged 9 commits intogithub:mainfrom
mnriem:issue-1924-stage-5

Conversation

@mnriem
Copy link
Copy Markdown
Collaborator

@mnriem mnriem commented Apr 1, 2026

Summary

Migrates codex, kimi, agy (Antigravity), and generic to the integration plugin architecture. Adds SkillsIntegration base class for agents that use the speckit-<name>/SKILL.md skills layout.

Part of #1924 — Stage 5 of the integration migration plan.

What changed

New base class

  • SkillsIntegration(IntegrationBase) in base.py — creates speckit-<name>/SKILL.md files matching release ZIP output byte-for-byte (validated against v0.4.4 ZIPs for codex and kimi)

New integrations

Integration Directory Type Options
codex .agents/skills/ SkillsIntegration --skills (default=True)
kimi .kimi/skills/ SkillsIntegration --skills, --migrate-legacy
agy .agent/skills/ SkillsIntegration --skills (default=True)
generic User-specified MarkdownIntegration --commands-dir (required)

Each has scripts/update-context.{sh,ps1} and is registered in INTEGRATION_REGISTRY.

CLI changes

  • --ai <agent> auto-promotes to integration path for all registered agents (including interactive selection — bug fix)
  • --ai-skills / --ai-commands-dir show deprecation notices when used with integration path
  • Next-steps display shows correct skill invocation syntax ($speckit-*, /skill:speckit-*) for skills integrations
  • agy added to CommandRegistrar.AGENT_CONFIGS

Test improvements

  • test_integration_base_skills.py — reusable mixin with 20+ tests including test_complete_file_inventory_sh/_ps
  • Per-agent test files for codex, kimi (with legacy migration), agy, generic
  • Registry completeness updated with Stage 4+5 keys
  • Removed 9 dead-mock tests, moved 4 integration tests to proper locations
  • Fixed all bare project-name tests to use tmp_path (no more directories created in repo root)
  • Fixed 6 pre-existing ANSI escape code test failures in test_extensions.py and test_presets.py

Validation

  • codex: 20/20 files byte-for-byte identical to v0.4.4 ZIP (sh + ps)
  • kimi: 20/20 files byte-for-byte identical to v0.4.4 ZIP (sh + ps)
  • agy: Body content identical (format transition from .agent/commands/*.md.agent/skills/speckit-*/SKILL.md)
  • 1524 tests pass, 0 failures

What's NOT changed

  • AGENT_SKILLS_MIGRATIONS stays in __init__.py behind not use_integration guard (removed in Stage 7)
  • Legacy --offline / download paths untouched (Stage 7)
  • AGENT_CONFIG dict untouched (Stage 7)

Add SkillsIntegration base class and migrate codex, kimi, agy, and
generic to the integration system.

Integrations:
- SkillsIntegration(IntegrationBase) in base.py — creates
  speckit-<name>/SKILL.md layout matching release ZIP output byte-for-byte
- CodexIntegration — .agents/skills/, --skills default=True
- KimiIntegration — .kimi/skills/, --skills + --migrate-legacy options,
  dotted→hyphenated skill directory migration
- AgyIntegration — .agent/skills/, skills-only (commands deprecated v1.20.5)
- GenericIntegration — user-specified --commands-dir, MarkdownIntegration
- All four have update-context.sh/.ps1 scripts
- All four registered in INTEGRATION_REGISTRY

CLI changes:
- --ai <agent> auto-promotes to integration path for all registered agents
- Interactive agent selection also auto-promotes (bug fix)
- --ai-skills and --ai-commands-dir show deprecation notices on integration path
- Next-steps display shows correct skill invocation syntax for skills integrations
- agy added to CommandRegistrar.AGENT_CONFIGS

Tests:
- test_integration_base_skills.py — reusable mixin with setup, frontmatter,
  directory structure, scripts, CLI auto-promote, and complete file inventory
  (sh+ps) tests
- Per-agent test files: test_integration_{codex,kimi,agy,generic}.py
- Kimi legacy migration tests, generic --commands-dir validation
- Registry updated with Stage 5 keys
- Removed 9 dead-mock tests, moved 4 integration tests to proper locations
- Fixed all bare project-name tests to use tmp_path
- Fixed 6 pre-existing ANSI escape code test failures in test_extensions.py
  and test_presets.py

1524 tests pass, 0 failures.
Copilot AI review requested due to automatic review settings April 1, 2026 18:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates additional agents (codex, kimi, agy, generic) onto the integrations plugin architecture by adding a new SkillsIntegration base and wiring up new integration packages, scripts, CLI auto-promotion, and expanded integration test coverage.

Changes:

  • Added SkillsIntegration base class to generate speckit-*/SKILL.md layouts and introduced codex/kimi/agy skills integrations plus a generic option-driven integration.
  • Updated specify init to auto-promote --ai <agent> (including interactive selection) into the integration path and adjusted next-steps output for skills integrations.
  • Expanded/updated tests for new integrations/registry alignment and made CLI-output assertions resilient to ANSI styling.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_presets.py Strip ANSI escape codes before output assertions.
tests/test_extensions.py Strip ANSI escape codes before output assertions.
tests/test_ai_skills.py Reworked legacy download-path tests and updated CLI validation tests to use tmp_path + integration auto-promote behavior.
tests/integrations/test_registry.py Updated required registry keys for Stage 4+5 and excluded generic from registrar alignment checks.
tests/integrations/test_integration_kiro_cli.py Added CLI test ensuring --ai kiro normalizes/auto-promotes to kiro-cli.
tests/integrations/test_integration_kimi.py Added skills-integration tests for kimi, including legacy dotted-skill migration + next-steps assertions.
tests/integrations/test_integration_generic.py Added option-driven integration tests for generic (--commands-dir) including inventories and uninstall semantics.
tests/integrations/test_integration_codex.py Added skills-integration tests for codex + auto-promote assertion.
tests/integrations/test_integration_base_skills.py Introduced reusable mixin for standard SkillsIntegration subclasses (inventory + CLI promotion + manifest tracking).
tests/integrations/test_integration_agy.py Added skills-integration tests for agy + auto-promote assertion.
tests/integrations/test_cli.py Updated init integration CLI tests to use tmp_path.
src/specify_cli/integrations/kimi/scripts/update-context.sh Added Kimi wrapper script delegating to shared update-agent-context.sh.
src/specify_cli/integrations/kimi/scripts/update-context.ps1 Added Kimi wrapper script delegating to shared PowerShell updater.
src/specify_cli/integrations/kimi/init.py Added KimiIntegration (skills) and dotted-skill migration helper.
src/specify_cli/integrations/generic/scripts/update-context.sh Added Generic wrapper script delegating to shared update-agent-context.sh.
src/specify_cli/integrations/generic/scripts/update-context.ps1 Added Generic wrapper script delegating to shared PowerShell updater.
src/specify_cli/integrations/generic/init.py Added GenericIntegration requiring --commands-dir and writing to user-selected command directory.
src/specify_cli/integrations/codex/scripts/update-context.sh Added Codex wrapper script delegating to shared update-agent-context.sh.
src/specify_cli/integrations/codex/scripts/update-context.ps1 Added Codex wrapper script delegating to shared PowerShell updater.
src/specify_cli/integrations/codex/init.py Added CodexIntegration (skills).
src/specify_cli/integrations/agy/scripts/update-context.sh Added Agy wrapper script delegating to shared update-agent-context.sh.
src/specify_cli/integrations/agy/scripts/update-context.ps1 Added Agy wrapper script delegating to shared PowerShell updater.
src/specify_cli/integrations/agy/init.py Added AgyIntegration (skills).
src/specify_cli/integrations/base.py Added SkillsIntegration implementation for generating SKILL.md layout.
src/specify_cli/integrations/init.py Registered new built-in integrations (agy/codex/kimi/generic).
src/specify_cli/agents.py Added agy to CommandRegistrar.AGENT_CONFIGS.
src/specify_cli/init.py Added integration-path deprecation notes, fixed interactive auto-promotion, mapped legacy flags into integration parsed options, and updated next-steps rendering for skills integrations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…and early generic validation

- --ai-skills deprecation message now distinguishes SkillsIntegration
  ("skills are the default") from command-based integrations ("has no effect")
- --ai-commands-dir validation for generic runs even when auto-promoted,
  giving clear CLI error instead of late ValueError from setup()
- Resolves review comments from github#2052
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Remove unused SKILL_DESCRIPTIONS dict from base.py (dead code after
  switching to template descriptions for ZIP parity)
- Narrow YAML parse catch from Exception to yaml.YAMLError
- Remove unused shutil import from test_integration_kimi.py
- Remove unused _REGISTRAR_EXEMPT class attr from test_registry.py
- Reword --ai-commands-dir deprecation to be actionable
- Update generic validation error to mention both --ai and --integration
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Clarify parsed_options forwarding is intentional (all options passed,
  integrations decide what to use)
- Extract _strip_ansi() helper in test_extensions.py and test_presets.py
- Remove unused pytest import (test_cli.py), unused locals (test_integration_base_skills.py)
- Reword --ai-commands-dir deprecation to be actionable without referencing
  the not-yet-implemented --integration-options
@mnriem mnriem requested review from Copilot and removed request for Copilot April 1, 2026 21:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Reorder kimi migration: run super().setup() first so hyphenated
  targets exist, then migrate dotted dirs (prevents user content loss)
- Move _strip_ansi() to shared tests/conftest.py, import from there
  in test_extensions.py, test_presets.py, test_ai_skills.py
- Remove now-unused re imports from all three test files
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Use write_bytes() for LF-only newlines (no CRLF on Windows)
- Add --integration-options CLI parameter — raw string passed through
  to the integration via opts['raw_options']; the integration owns
  parsing of its own options
- GenericIntegration.setup() reads --commands-dir from raw_options
  when not in parsed_options (supports --integration-options="...")
- Skip early --ai-commands-dir validation when --integration-options
  is provided (integration validates in its own setup())
- Remove parse_integration_options from core — integrations parse
  their own options
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/generic/init.py:81

  • The fallback parsing of raw_options uses shlex.split(raw) (POSIX mode by default). On Windows this treats backslashes as escape characters, so a value like --commands-dir .myagent\commands or C:\path\to\cmds can be mis-parsed. If --integration-options is intended to be cross-platform, consider using shlex.split(..., posix=os.name != 'nt') (or a small custom parser that supports --commands-dir=<value> / quoted values) to avoid corrupting paths.
        # If --commands-dir not in parsed_options, check raw_options
        if "commands_dir" not in parsed_options:
            raw = opts.get("raw_options")
            if raw:
                import shlex
                tokens = shlex.split(raw)
                for i, token in enumerate(tokens):
                    if token == "--commands-dir" and i + 1 < len(tokens):
                        parsed_options["commands_dir"] = tokens[i + 1]
                        break

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- GenericIntegration is now stateless: removed self._commands_dir
  instance state, overrides setup() directly to compute destination
  from parsed_options/raw_options on the stack
- commands_dest() raises by design (stateless singleton)
- _quote() in SkillsIntegration now escapes backslashes and double
  quotes to produce valid YAML even with special characters
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Support --commands-dir=value form in raw_options parsing (not just
  --commands-dir value with space separator)
- Normalize CRLF to LF in write_file_and_record() before encoding
- Persist ai_skills=True in init-options.json when using a
  SkillsIntegration, so extensions/presets emit SKILL.md overrides
  correctly even without explicit --ai-skills flag
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mnriem mnriem merged commit 4f9d966 into github:main Apr 2, 2026
12 checks passed
@mnriem mnriem deleted the issue-1924-stage-5 branch April 2, 2026 13:00
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.

2 participants