Skip to content

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

Open
davidebibm wants to merge 23 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 23 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: 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 thread src/specify_cli/integrations/bob/__init__.py
@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 thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/copilot/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py
mnriem and others added 2 commits July 16, 2026 12:23
…separators, extension-skill token resolution

Addresses PR review 4716036212 (3 comments):

1. Bob legacy-install regression: `use`/`switch`/`upgrade` on an existing
   Bob 1.x project (only `.bob/commands/` on disk, no stored
   `legacy_commands`) called `is_skills_mode(None)` -> True and rewrote
   `ai_skills=True`, silently switching extension/command-reference handling
   to the skills layout. `is_skills_mode` now takes an optional `project_root`;
   Bob preserves an already-installed legacy layout until an explicit upgrade
   creates `.bob/skills/`. A fresh project still defaults to skills.

2. Copilot dual-mode separator: `invoke_separator_for_mode` was inherited
   from the base (mode-independent) and returned Copilot's static `.`, so
   preset/extension command refs in a Copilot skills project rendered
   `/speckit.<name>` instead of `/speckit-<name>`. Override it on Copilot to
   track the persisted `ai_skills` state, consistent with
   `build_command_invocation` and `effective_invoke_separator`.

3. Bob extension-skill command-ref tokens: verified that merging main's
   generic `_resolve_command_ref_tokens` (github#3544) resolves Bob's tokens via
   the `CONDITIONAL_SLASH_AGENTS` path (`/speckit-<name>`); added Bob to the
   command-ref regression parametrize plus dedicated Bob use-path tests.

All tests pass (full suite green; merged with current main incl. github#3544).

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

Addressed the three review comments in d929bfb. This push also merges current main into the branch (brings in #3544), so it's now up to date and self-consistent.

1. Bob legacy-install regression (bob/__init__.py) — the real bug. use/switch/upgrade on an existing Bob 1.x project (only .bob/commands/ on disk, no stored legacy_commands) hit is_skills_mode(None)True and rewrote ai_skills: true, silently switching the project to the skills layout. is_skills_mode now accepts an optional project_root; Bob preserves an already-installed legacy layout until an explicit upgrade actually creates .bob/skills/. A fresh project still defaults to skills. Threaded project_root through the init and _update_init_options_for_integration call sites.

2. Copilot dual-mode separator (copilot/__init__.py) — Copilot inherited the mode-independent invoke_separator_for_mode default, returning its static ., so preset/extension command refs in a Copilot skills project rendered /speckit.<name>. Added an override that tracks the persisted ai_skills state (- skills, . default), consistent with build_command_invocation and effective_invoke_separator.

3. Bob extension-skill command-ref tokens — with main merged, the generic _resolve_command_ref_tokens from #3544 resolves Bob's __SPECKIT_COMMAND_*__ tokens via the CONDITIONAL_SLASH_AGENTS path (/speckit-<name>), so no Bob-specific build_command_invocation is needed. Added Bob to the command-ref-token regression parametrize plus dedicated Bob is_skills_mode/use-path tests to lock the behavior in.

Testing: full suite green on the merged result — 4524 passed, 5 skipped, 0 failures.


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

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
…e shared-infra refresh (review github#3415)

The `use`/`switch` paths refresh shared infrastructure via
`_with_integration_setting()` / `_invoke_separator_for_integration()`,
which previously resolved the invoke separator through
`effective_invoke_separator` / `is_skills_mode` WITHOUT a project_root.
For a pre-PR Bob 1.x project (.bob/commands/ on disk, no stored options),
this defaulted to the skills "-" separator and rewrote rendered
shared-template command refs to /speckit-*, even though ai_skills stayed
false. Thread project_root through effective_invoke_separator, the two
runtime helpers, and every call site so Bob's on-disk legacy detection
governs the separator before shared infra is refreshed.

Add a rendered-shared-template regression test covering `use --force`.

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

Addressed review 4716253844 in 8a162b3.

Finding (valid): the legacy-layout detection wasn't applied when use/switch refreshes shared infrastructure. _set_default_integration() refreshed rendered shared templates via _with_integration_setting() / _invoke_separator_for_integration(), both of which resolved the invoke separator through effective_invoke_separator/is_skills_mode without project_root. For a pre-PR Bob 1.x project (.bob/commands/ on disk, no stored options) this defaulted to the skills - separator and rewrote rendered command refs to /speckit-* even though ai_skills stayed false.

Fix: threaded project_root through effective_invoke_separator, the two runtime helpers (with_integration_setting, invoke_separator_for_integration), and every call site, so Bob's on-disk legacy detection governs the separator before shared infra is refreshed. Added an end-to-end regression test (test_use_force_keeps_legacy_command_refs_in_shared_templates) that inits a legacy Bob project, runs integration use bob --force, and asserts rendered shared templates keep /speckit.* (dot) refs.

Full suite green: 4526 passed, 5 skipped.

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

Comment thread src/specify_cli/agents.py
Comment on lines +651 to +653
_sep = _integ.invoke_separator_for_mode(
is_ai_skills_enabled(load_init_options(project_root))
)
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