Skip to content

Commit dea23f0

Browse files
committed
PR comments fix: keep old Bob 1 commands till next release
1 parent e893245 commit dea23f0

2 files changed

Lines changed: 389 additions & 13 deletions

File tree

src/specify_cli/integrations/bob/__init__.py

Lines changed: 122 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,43 @@
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

714
from __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

Comments
 (0)