Skip to content

Route to Fable by default, isolate the helper from MCP, and make the test suite runnable without ripgrep - #3

Open
danimola88 wants to merge 3 commits into
codejunkie99:mainfrom
danimola88:fix/route-to-fable-and-isolate-mcp
Open

Route to Fable by default, isolate the helper from MCP, and make the test suite runnable without ripgrep#3
danimola88 wants to merge 3 commits into
codejunkie99:mainfrom
danimola88:fix/route-to-fable-and-isolate-mcp

Conversation

@danimola88

@danimola88 danimola88 commented Sep 5, 2026

Copy link
Copy Markdown

Three independent fixes found while installing the skill on a clean machine. Each is verified against the live claude CLI, not inferred.

1. The helper does not call Fable — it calls the user's default model and labels it as Fable

ask_fable.sh builds its candidate list from settings.json and stats-cache.json and breaks at the first model that answers. The first candidate is whatever .model the user has configured. On my machine that is Opus, so:

$ printf '%s' "..." | ask_fable.sh
Fable 5.1 speaks (opus[1m]):

SKILL.md then instructs Codex to display that verbatim under the Fable 5.1 speaks: heading. So the single guarantee the skill exists to provide is silently false, and the output attributes an Opus answer to Fable. SKILL.md already says "Do not relabel ordinary Codex or worker-agent output as Fable speech" — this is the helper doing exactly that.

The fix tries the fable and claude-fable-5-1 aliases first, keeps the existing discovery as a fallback, and labels honestly: if no Fable model was callable, the output says so on stderr and is no longer printed under the Fable heading.

2. --tools "" does not isolate the call — the user's MCP servers still load

That flag only disables the built-in tools. MCP servers come from the user's own config and start regardless. Same invocation the helper makes, asking the model to list its connected MCP servers:

result
as shipped Gmail, Google Calendar, Higgsfield, Slack, context7, playwright, polarpanel
with --strict-mcp-config NINGUNO (none)

Every Fable call was starting seven servers, and a planning-only prompt was getting live reach into mail and chat. Adding --strict-mcp-config matches what --tools "" was already trying to express.

3. tests/test_skill.sh cannot run without ripgrep

rg is called unconditionally while xmllint is properly guarded with command -v. The README calls these "dependency-light checks" and does not list ripgrep. On a machine without it the suite aborts at the first routing-string check:

./tests/test_skill.sh: line 29: rg: command not found
FAIL: missing required routing string: Claude Fable 5.1

Worth noting for the credential scan specifically: the negative checks are written as if rg ...; then fail, so a missing or erroring rg reads as "clean" rather than as an error. Here an earlier || fail aborts first, so it fails loudly — but the shape is fragile for a security check.

The fix wraps the three search shapes in helpers backed by ripgrep when present and grep otherwise. Also removes the backslashes from awk's /"[^\"]+"/ classes, which gawk warns about on every run.

Verification

  • Suite passes with ripgrep and with PATH=/usr/bin:/bin (no ripgrep). Same result both ways.
  • Negative control: a planted AKIA…-shaped string is still caught in both modes.
  • Post-fix smoke test reports Fable 5.1 speaks (fable): and the model confirms it sees no MCP servers.
  • No change to install.sh, the SVG, or the routing policy.

🤖 Generated with Claude Code

Note

Route to Fable aliases by default in ask_fable.sh, pass --strict-mcp-config, and make tests ripgrep-optional

  • When no FABLE_MODEL or FABLE_MODEL_CANDIDATES is set, ask_fable.sh now tries local Fable aliases before falling back to models discovered from Claude settings and usage-cache files
  • Every Claude candidate invocation now includes --strict-mcp-config, isolating the helper from MCP
  • Responses from a model whose name does not contain lowercase fable produce a stderr warning and a heading labeled as orchestration output rather than Fable 5.1
  • Replaces direct rg calls in test_skill.sh with match_fixed, show_matches, and scan_tree helpers that fall back to grep when ripgrep is unavailable
  • Risk: non-Fable models can still be selected when Fable candidates fail, and their output is now explicitly relabeled rather than presented as Fable; check the response formatter in ask_fable.sh if downstream consumers rely on the Fable-branded heading

Macroscope summarized 556c569.

danimola88 and others added 3 commits September 5, 2026 13:34
The model discovery derives candidates from settings.json and stats-cache.json
and stops at the first one that answers. The first candidate is whatever
`.model` the user has configured, so on a machine whose default is Opus the
helper runs Opus and prints "Fable 5.1 speaks (opus[1m])". SKILL.md then tells
Codex to display that verbatim under the "Fable 5.1 speaks:" heading, so the
one thing the skill exists to guarantee -- that Fable did the orchestrating --
is silently false, and the output misattributes the answer to Fable.

Try the `fable` and `claude-fable-5-1` aliases first and keep discovery as a
fallback, then label the output with what actually answered: a non-Fable
fallback is reported on stderr and no longer claims to be Fable speaking.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`--tools ""` only disables Claude Code's built-in tools. MCP servers come from
the user's own configuration and are still started, so every Fable call spins
up whatever the user has connected. Measured on a machine with seven servers,
the same invocation the helper makes reports:

  without --strict-mcp-config: Gmail, Google Calendar, Higgsfield, Slack,
                               context7, playwright, polarpanel
  with    --strict-mcp-config: none

That is slower and more expensive on every call, and it hands a planning-only
prompt live reach into the user's mail and chat for no benefit -- the helper
needs no tools at all, which is what `--tools ""` was already trying to say.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_skill.sh calls `rg` unconditionally while guarding `xmllint` with
command -v, so on a machine without ripgrep the suite aborts at the first
routing-string check and never runs any of the later checks. The README
describes these as "dependency-light checks" and does not list ripgrep as a
requirement.

Wrap the three search shapes in helpers that use ripgrep when present and grep
otherwise. Verified both paths: the suite passes with and without ripgrep on
PATH, and a planted AKIA-shaped string is still caught in both modes.

Also drop the backslashes in awk's /"[^\"]+"/ character classes. Inside a
single-quoted awk program \" is not an escape, and gawk warns on every run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant