11"""IBM Bob integration.
22
3- Bob 2.0 uses the ``.bob/skills/speckit-<name>/SKILL.md`` layout.
4- The legacy ``.bob/commands/`` layout (Bob 1.x) is no longer supported.
3+ Bob 2.0 supports the ``.bob/skills/speckit-<name>/SKILL.md`` layout.
4+ The legacy ``.bob/commands/*.md`` layout (Bob 1.x) remains the default
5+ for this release and will be deprecated in a future Spec Kit release.
6+
7+ Deprecation cycle:
8+ This release: Markdown layout is default; skills layout is opt-in via
9+ ``--integration-options "--skills"``.
10+ Next cycle: Skills layout becomes default; markdown remains opt-in.
11+ Cycle after: Markdown layout removed.
512"""
613
714from __future__ import annotations
815
9- from ..base import IntegrationOption , SkillsIntegration
16+ import warnings
17+ from pathlib import Path
18+ from typing import Any
19+
20+ from ..base import IntegrationBase , IntegrationOption , SkillsIntegration
21+ from ..manifest import IntegrationManifest
22+
23+
24+ def _warn_legacy_markdown_default () -> None :
25+ """Warn that Bob's default markdown scaffold is being phased out."""
26+ warnings .warn (
27+ "Bob legacy markdown mode (.bob/commands/) is deprecated and will stop "
28+ "being the default in a future Spec Kit release; pass "
29+ '--integration-options "--skills" to opt in to Bob skills mode now.' ,
30+ UserWarning ,
31+ stacklevel = 3 ,
32+ )
1033
1134
12- class BobIntegration (SkillsIntegration ):
13- """Integration for IBM Bob IDE."""
35+ class _BobSkillsHelper (SkillsIntegration ):
36+ """Internal helper used when Bob is scaffolded in skills mode.
37+
38+ Not registered in the integration registry — only used as a delegate
39+ by ``BobIntegration`` when ``--skills`` is passed.
40+ """
1441
1542 key = "bob"
1643 config = {
@@ -27,13 +54,101 @@ class BobIntegration(SkillsIntegration):
2754 "extension" : "/SKILL.md" ,
2855 }
2956
57+
58+ class BobIntegration (IntegrationBase ):
59+ """Integration for IBM Bob IDE.
60+
61+ Default mode: installs ``.bob/commands/speckit.<name>.md`` files
62+ (Bob 1.x markdown layout — legacy, will be deprecated).
63+
64+ Skills mode (``--skills``): installs
65+ ``.bob/skills/speckit-<name>/SKILL.md`` files (Bob 2.0 layout).
66+ """
67+
68+ key = "bob"
69+ config = {
70+ "name" : "IBM Bob" ,
71+ "folder" : ".bob/" ,
72+ "commands_subdir" : "commands" ,
73+ "install_url" : None ,
74+ "requires_cli" : False ,
75+ }
76+ registrar_config = {
77+ "dir" : ".bob/commands" ,
78+ "format" : "markdown" ,
79+ "args" : "$ARGUMENTS" ,
80+ "extension" : ".md" ,
81+ }
82+
83+ # Mutable flag set by setup() — indicates the active scaffolding mode.
84+ _skills_mode : bool = False
85+
86+ def effective_invoke_separator (
87+ self , parsed_options : dict [str , Any ] | None = None
88+ ) -> str :
89+ """Return ``"-"`` when skills mode is requested, ``"."`` otherwise."""
90+ if parsed_options and parsed_options .get ("skills" ):
91+ return "-"
92+ if self ._skills_mode :
93+ return "-"
94+ return self .invoke_separator
95+
3096 @classmethod
3197 def options (cls ) -> list [IntegrationOption ]:
3298 return [
3399 IntegrationOption (
34100 "--skills" ,
35101 is_flag = True ,
36- default = True ,
37- help = "Install as agent skills (default for Bob 2.0)" ,
102+ default = False ,
103+ help = (
104+ "Scaffold commands as agent skills "
105+ "(.bob/skills/speckit-<name>/SKILL.md) instead of "
106+ "the legacy .bob/commands/*.md layout"
107+ ),
38108 ),
39109 ]
110+
111+ def setup (
112+ self ,
113+ project_root : Path ,
114+ manifest : IntegrationManifest ,
115+ parsed_options : dict [str , Any ] | None = None ,
116+ ** opts : Any ,
117+ ) -> list [Path ]:
118+ """Install Bob commands.
119+
120+ When ``parsed_options["skills"]`` is truthy, delegates to skills
121+ scaffolding (``.bob/skills/speckit-<name>/SKILL.md``).
122+ Otherwise uses the default ``.bob/commands/speckit.<name>.md`` layout
123+ and emits a deprecation warning.
124+ """
125+ parsed_options = parsed_options or {}
126+ self ._skills_mode = bool (parsed_options .get ("skills" ))
127+ if self ._skills_mode :
128+ return self ._setup_skills (project_root , manifest , parsed_options , ** opts )
129+ if "skills" not in parsed_options :
130+ _warn_legacy_markdown_default ()
131+ return self ._setup_default (project_root , manifest , parsed_options , ** opts )
132+
133+ def _setup_default (
134+ self ,
135+ project_root : Path ,
136+ manifest : IntegrationManifest ,
137+ parsed_options : dict [str , Any ] | None = None ,
138+ ** opts : Any ,
139+ ) -> list [Path ]:
140+ """Default mode: ``.bob/commands/speckit.<name>.md`` layout."""
141+ from ..base import MarkdownIntegration
142+
143+ return MarkdownIntegration .setup (self , project_root , manifest , parsed_options , ** opts )
144+
145+ def _setup_skills (
146+ self ,
147+ project_root : Path ,
148+ manifest : IntegrationManifest ,
149+ parsed_options : dict [str , Any ] | None = None ,
150+ ** opts : Any ,
151+ ) -> list [Path ]:
152+ """Skills mode: delegate to ``_BobSkillsHelper``."""
153+ helper = _BobSkillsHelper ()
154+ return SkillsIntegration .setup (helper , project_root , manifest , parsed_options , ** opts )
0 commit comments