Skip to content

feat: update Bob integration to skills-based layout for Bob 2.0#3415

Open
davidebibm wants to merge 20 commits into
github:mainfrom
davidebibm:feat/update-bob-skills-integration
Open

feat: update Bob integration to skills-based layout for Bob 2.0#3415
davidebibm wants to merge 20 commits into
github:mainfrom
davidebibm:feat/update-bob-skills-integration

Conversation

@davidebibm

@davidebibm davidebibm commented Jul 8, 2026

Copy link
Copy Markdown

Bob 2.0 replaces the command-based workflow with a skills-based layout.

https://bob.ibm.com/blog/bob-v2-release-announcement

Description

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Very simple code generated by Bob but verified by me

Bob 2.0 replaces the command-based workflow (.bob/commands/*.md) with
a skills-based layout (.bob/skills/speckit-<name>/SKILL.md), matching
the pattern used by Claude Code, Codex, and other skills-first agents.

- Switch BobIntegration from MarkdownIntegration to SkillsIntegration
- Update folder/dir from .bob/commands to .bob/skills
- Change extension from .md to /SKILL.md (skills layout)
- Add --skills option (default: True) consistent with Codex pattern
- Update tests to inherit from SkillsIntegrationTests (28 tests pass)
- Bump catalog entry to version 2.0.0 with updated description

Assisted-by: IBM Bob (model: claude-sonnet-4-5, autonomous)
@davidebibm davidebibm requested a review from mnriem as a code owner July 8, 2026 18:26
@davidebibm

Copy link
Copy Markdown
Author

@mnriem please review, we need to make this work with new Bob... Thankyou so much

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

This PR updates the built-in IBM Bob integration to align with Bob 2.0’s skills-based layout, switching installation output from command files to speckit-<name>/SKILL.md skills directories and bumping the integration’s catalog version accordingly.

Changes:

  • Migrate BobIntegration from MarkdownIntegration to SkillsIntegration and update output paths to .bob/skills/.../SKILL.md.
  • Update Bob integration tests to use the shared SkillsIntegrationTests mixin.
  • Bump the Bob entry in integrations/catalog.json to 2.0.0 with an updated description.
Show a summary per file
File Description
src/specify_cli/integrations/bob/__init__.py Switch Bob to SkillsIntegration and update registrar/config output to .bob/skills + /SKILL.md.
tests/integrations/test_integration_bob.py Update base test mixin and expected output directories for the skills layout.
integrations/catalog.json Bump Bob integration version/description to reflect the 2.0.0 skills-based update.

Review details

Tip

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

  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Low

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py

@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.

As this fundamentally changes the layout for any Bob users what is the migration strategy? This will break them once they adopt a new version of Spec Kit so you need to make sure this goes through a deprecation cycle so they can migrate to the new Bob version. E.g make it an opt-in to the new version of Bob first and then in 2 minor releases (X.Y.Z where Y is minor) you can then remove the non-skill variant

@davidebibm

Copy link
Copy Markdown
Author

As this fundamentally changes the layout for any Bob users what is the migration strategy? This will break them once they adopt a new version of Spec Kit so you need to make sure this goes through a deprecation cycle so they can migrate to the new Bob version. E.g make it an opt-in to the new version of Bob first and then in 2 minor releases (X.Y.Z where Y is minor) you can then remove the non-skill variant

Hi @mnriem
this should not break for Bob 1 user cause it was already compatible with skill mode.
Still needed this?

@mnriem

mnriem commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Thanks @davidebibm — but I think we're talking about two different layers, and this still needs to change before it can land.

Your point is about Bob the tool — that Bob 1.x can already read the skills layout. My concern is about Spec Kit's generated output: this PR changes what specify writes for the bob integration from .bob/commands/*.md to .bob/skills/speckit-<name>/SKILL.md. Any project someone already initialized has .bob/commands/*.md on disk. When they upgrade Spec Kit and re-init or switch, that layout is orphaned/replaced. That's a breaking change in our contract regardless of whether the Bob app happens to read both directories.

A hard cutover isn't acceptable here — we shouldn't catch existing users off guard. This needs to go through a proper deprecation cycle:

  1. This release: make skills an opt-in and keep the existing .bob/commands markdown layout as the default. That's real dual-mode — setup() branching between the two layouts, the way Copilot does it — not the --skills flag as written now.
  2. Next cycle: flip the default to skills, with the legacy layout still available.
  3. Cycle after that: remove the legacy markdown mode.

As it stands the --skills flag is a no-op: BobIntegration is hardwired to SkillsIntegration and the MarkdownIntegration variant is deleted, so --skills=False still emits skills. There's no path that produces the old layout, so it doesn't actually provide the opt-in it implies.

Can you rework it along those lines — genuine dual-mode with skills opt-in first — so we phase this in without breaking anyone?

@davidebibm

Copy link
Copy Markdown
Author

Ok, thankyou @mnriem i'll do that

@davidebibm davidebibm requested a review from mnriem July 13, 2026 15:01
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Done, hope this is what you are expecting

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: 3
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
@mnriem

mnriem commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback. You will need to update the description to reflect the reality

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

Copy link
Copy Markdown
Author

@mnriem Addressed Copilot comments and aligned with main

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: 38/38 changed files
  • Comments generated: 4
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/kiro_cli/__init__.py
Comment thread CHANGELOG.md
@mnriem

mnriem commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback and resolve conflicts

@davidebibm davidebibm force-pushed the feat/update-bob-skills-integration branch from 6b3a18c to 674a8db Compare July 14, 2026 14:44
…to ALWAYS_SLASH_AGENTS

- init.py: suppress ai_skills=True when --legacy-commands is passed so
  extensions and presets target .bob/commands, not .bob/skills
- _invocation_style.py: add 'bob' to ALWAYS_SLASH_AGENTS so init next-steps
  and hook invocations always show /speckit-<name> (skills is the default
  layout; no ai_skills flag required)
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Solved Copilot fb and rebased to avoid get Copilot feedback on other devs code 👍

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: 7/7 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated

@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.

Address Copilot feedback. If not applicable, please explain why

@davidebibm davidebibm requested a review from mnriem July 16, 2026 13:00
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Applied Copilot suggestion

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: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py

@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. Note we want to make sure we deliver the correct guidance here so please bear with me on these reviews. Thanks so much!

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: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated

@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. If not applicable, please explain why

@davidebibm

Copy link
Copy Markdown
Author

@mnriem Applied Copilot suggestion

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: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment on lines +131 to +136
registrar_config = {
"dir": ".bob/commands",
"format": "markdown",
"args": "$ARGUMENTS",
"extension": ".md",
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@mnriem Hahhahah oh my gosh, that is the line i have removed to address the previous comment of Copilot.
What it will do if i accept this suggestion? i'll get same comment i've got before :-)
Please do a human check on this.

@mnriem

mnriem commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback. If not applicable, please explain why

@davidebibm

Copy link
Copy Markdown
Author

@mnriem Explained in the comment why do this is will be stupid and useless

@davidebibm davidebibm requested a review from mnriem July 16, 2026 15:50
…-ref separators

Rework the dual-mode handling introduced for Bob 2.0 so an integration's
internal representation never leaks into shared init/install/upgrade code,
and fix the legacy command-reference separator surfaced in review.

Base-class contract:
- Add IntegrationBase.is_skills_mode(parsed_options) — the single hook the
  shared machinery consults to decide whether to persist ai_skills and render
  skill invocations. SkillsIntegration returns True; Copilot honors --skills /
  self._skills_mode; Bob returns `not legacy_commands`.
- Add IntegrationBase.invoke_separator_for_mode(skills_enabled) — resolves the
  command-ref separator from a project's persisted mode for registration paths
  that only have the ai_skills flag (no CLI parsed_options). Default is
  behavior-preserving; Bob maps skills->"-", legacy->".".
- BobIntegration stays on IntegrationBase (mirroring Copilot, the other
  dual-mode agent) and delegates setup() to internal _BobSkillsHelper /
  _BobMarkdownHelper. Removes the _skills_mode method and all
  isinstance(SkillsIntegration) / callable(_skills_mode) probing from
  _helpers.py and init.py.

Fix legacy separator (review feedback): CommandRegistrar.register_commands and
PresetManager._resolve_skill_command_refs previously read the single static
AGENT_CONFIGS[key]["invoke_separator"], so legacy .bob/commands/ extension and
preset command refs rendered /speckit-<cmd> instead of Bob 1.x /speckit.<cmd>.
Both now resolve the separator per project mode via invoke_separator_for_mode.

Tests: add regression coverage for the is_skills_mode / invoke_separator_for_mode
hooks and legacy extension command-ref separators; normalize a width-sensitive
workflow assertion to match its siblings. Full suite green.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

@davidebibm I hope you do not mind me taking it over. I realized there is some additional work that needs to be done to do this cleanly. Stay tuned!

@mnriem mnriem force-pushed the feat/update-bob-skills-integration branch from 1d792d9 to 5a8cb61 Compare July 16, 2026 17:00
@mnriem

mnriem commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Pushed a revision to this branch (force-update of my own earlier commit, tip now 5a8cb61).

What changed since the previous push:

  • Reworked Bob onto IntegrationBase with a polymorphic is_skills_mode(parsed_options) hook plus internal _BobSkillsHelper/_BobMarkdownHelper, so mode selection is config-driven (mirrors Copilot) and no _skills_mode method leaks into shared code paths. Base-class behavior is unchanged for every other integration.
  • Fixed the command-reference separator bug flagged in review: legacy .bob/commands/ was rendering /speckit-specify instead of Bob 1.x /speckit.specify. Introduced invoke_separator_for_mode(skills_enabled) (skills → -, legacy → .) and wired it through agents.py and the preset resolver, so the fix does not regress skills mode.
  • Made a workflow test width-robust (whitespace-normalized assertion).
  • Dropped my earlier extension-skills token fix — main's fix(extensions): resolve __SPECKIT_COMMAND tokens in auto-registered skills #3544 already resolves __SPECKIT_COMMAND_*__ tokens more completely. Removing it is what cleared the merge conflict; this rewrote only my own tip commit, not @davidebibm's.

Testing: full suite green both on the branch tip (4494 passed, 5 skipped) and merged with current main including #3544 (4516 passed, 5 skipped). PR now reports MERGEABLE.


Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

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: 13/13 changed files
  • Comments generated: 3
  • Review effort level: Medium

Comment on lines +147 to +149
def is_skills_mode(self, parsed_options: dict[str, Any] | None = None) -> bool:
"""Bob is skills-first; ``--legacy-commands`` opts out."""
return not (parsed_options or {}).get("legacy_commands", False)
Comment on lines +134 to +143
def is_skills_mode(self, parsed_options: dict[str, Any] | None = None) -> bool:
"""Copilot is skills mode when ``--skills`` was requested.

On the init path ``setup()`` has already recorded the choice in
``self._skills_mode``; on the ``use``/``install`` path (where no
``setup()`` runs) the signal comes from *parsed_options* (#3550).
"""
if parsed_options and parsed_options.get("skills"):
return True
return self._skills_mode
get the correct separator despite sharing one static ``AGENT_CONFIGS``
entry.
"""
return "-" if skills_enabled else "."
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.

3 participants