design detector probes IMPECCABLE_SKILL: absent for every Claude Code plugin install of impeccable
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
`bin/gstack-design-detect.ts` looks for impeccable under `//skills/impeccable/`, but the normal way to get impeccable today is as a Claude Code plugin, which installs somewhere that pattern never reaches. Every plugin install therefore probes as `IMPECCABLE_SKILL: absent`, and the launcher and sibling-engine discovery in the same loop miss it too.
## Observed
gstack 1.84.1.0, Linux, impeccable plugin 4.3.1 installed via the Claude Code plugin marketplace.
```
$ bun ~/.claude/skills/gstack/bin/gstack-design-detect.ts probe
IMPECCABLE_READY: /home/dgrant/.impeccable/bin/0.1.5/impeccable
IMPECCABLE_SKILL: absent
IMPECCABLE_HOOK: absent
IMPECCABLE_IGNORED_RULES:
IMPECCABLE_IGNORED_FILES:
IMPECCABLE_IGNORED_VALUES:
IMPECCABLE_ENGINE_UNTESTED: 0.1.5
```
The skill is installed and its 23 `/impeccable ` commands are live in the session. `IMPECCABLE_SKILL: absent` is wrong.
## Why
`SKILL_ROOTS` (`bin/gstack-design-detect.ts:163`) is `['.claude', '.agents', '.cursor', '.gemini', '.github', '.opencode']`, and the loop at :311 tests `path.join(root, sub, 'skills', 'impeccable', 'SKILL.md')` for each of repoRoot, cwd and HOME. That resolves to `~/.claude/skills/impeccable/SKILL.md`.
A plugin install puts it at:
```
~/.claude/plugins/cache/impeccable/impeccable/4.3.1/skills/impeccable/SKILL.md
~/.claude/plugins/cache/impeccable/impeccable/4.3.1/skills/impeccable/scripts/impeccable # the launcher
```
`~/.claude/skills/impeccable/` does not exist and is not created by a plugin install — the manifest points Claude Code at `./skills/` inside the versioned plugin cache directory. The path segment `plugins/cache////` sits between the `SKILL_ROOTS` entry and the `skills/` the probe expects, so no amount of the existing pattern matches.
Three things in that one loop miss, not just the flag:
1. `p.skillPresent` stays false.
2. `p.launcher` stays null, so the `NOT_CACHED` state and its `DESIGN_DETECTOR_HINT` can never fire for a plugin user — the probe goes straight from "no engine" to `NOT_AVAILABLE` and the install offer, even though the user already has impeccable's own launcher on disk.
3. The sibling-engine candidate under `path.dirname(launcher)` is never considered.
## Consequence
Cosmetic but load-bearing for the interop story. The handoff lines are gated on `IMPECCABLE_SKILL: present`:
- `ship/sections/review-army.md:101` — "When the probe printed `IMPECCABLE_SKILL: present`, end each NEEDS INPUT detector row with the `handoff=` command"
- `design-review/SKILL.md:856` and `:1699` — same gate on deferred findings
- generated from `scripts/resolvers/design.ts:60` and `:892`, so `/review`, `/ship` and `/design-review` are all affected
So a plugin user gets the `FINDING-NNN [rule-id]` rows but never the `/impeccable typeset|layout|colorize|…` handoff that the v1.84.0.0 release notes describe as the point of the integration — and they have the skill installed and could act on it immediately. Detection itself is unaffected: scans run and findings are correct.
## Related: the engine was found by coincidence
On this machine `IMPECCABLE_READY` resolved even though gstack never installed anything — `design_detector_install_prompted=false` and `grep -c impeccable ~/.gstack/security/egress.jsonl` is 0. impeccable's own launcher had put the engine at `~/.impeccable/bin/0.1.5/impeccable`, which happens to be the exact cache layout gstack reserves for its own download, so the HOME-cache step matched by luck rather than through the plugin.
Two things follow from that. `IMPECCABLE_ENGINE_UNTESTED: 0.1.5` fires on every plugin user whose own launcher keeps the engine current, since gstack's fixtures pin 0.1.3. And a plugin user who says yes to the install offer gets a second, older engine written into the directory their launcher already manages.
## Reproduce
Install impeccable as a Claude Code plugin (`/plugin marketplace add pbakaus/impeccable` then install), with no `~/.claude/skills/impeccable/`, and run `gstack-design-detect probe`.
Contributor guide
Research direction
Start in bin/gstack-design-detect.ts at SKILL_ROOTS and the detection loop around line 311, then reproduce with the probe command and a Claude Code plugin install. Trace how the plugin-cache path affects skillPresent, launcher, and sibling-engine discovery; done means plugin users report the skill and launcher correctly without being offered an unnecessary install, while the existing probe behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, devtools, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100