[GH-ISSUE #6451] [Bug] doctor --skill recommends setup that does not select the stale client skill copy #3865

Closed
opened 2026-10-31 00:44:46 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6451

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Setup, packaging, or upgrade

Observed behavior

With a current shared skill and a changed Claude Code personal skill, doctor --skill --format json correctly reports stale identity but does not identify the changed destination. Its remediation is Run rea setup to update the installed REA skill. Both bare setup and setup --skill produce empty dry-run plans in this state. Explicit setup --skill-client claude_code instead previews an installation at the changed destination.

Reproduction

Prepare a fresh checkout at 9eb829aca34be36ff112826337996f6139f82eff:

npm ci && npm run build:cached

From the checkout root, run this isolated fixture. The CLI sequence was executed against the prepared build; dependency installation and rebuilding were not repeated during reproduction. Do not enable set -e, because the stale checks intentionally exit 1.

env -i PATH="$PATH" bash --noprofile --norc <<'SH'
WORK="$(mktemp -d)"
export HOME="$WORK/home"
export USERPROFILE="$HOME"
export XDG_CONFIG_HOME="$HOME/config"
export XDG_CACHE_HOME="$HOME/cache"
export XDG_DATA_HOME="$HOME/data"
mkdir -p "$HOME/.agents/skills" "$HOME/.claude/skills"
cp -R skills/reverse-engineer-anything "$HOME/.agents/skills/"
cp -R skills/reverse-engineer-anything "$HOME/.claude/skills/"

# Control: both copied bundles are current; exit 0, aligned.
node scripts/rea.mjs doctor --skill --format json

printf '\n<!-- older installed revision -->\n' >> \
  "$HOME/.claude/skills/reverse-engineer-anything/references/native-and-artifacts.md"

# Exit 1, stale, generic setup remediation without the affected path.
node scripts/rea.mjs doctor --skill --format json
node scripts/rea.mjs setup --dry-run --format json
node scripts/rea.mjs setup --skill --dry-run --format json
node scripts/rea.mjs setup --skill-client claude_code --dry-run --format json
node scripts/rea.mjs doctor --skill --format json

# Restore only the fixture's changed file; the same doctor passes again.
cp skills/reverse-engineer-anything/references/native-and-artifacts.md \
  "$HOME/.claude/skills/reverse-engineer-anything/references/native-and-artifacts.md"
node scripts/rea.mjs doctor --skill --format json
SH

The stale diagnosis reproduced three times in the same fixture, including after the setup previews. The aligned and restored controls each passed once. The copies were seeded from the built bundle rather than installed through approved setup. All setup calls were previews; no repair apply was executed.

Expected behavior

Doctor should identify the stale installed destination and provide a command that selects it for repair. The doctor contract promises suitable remediation for each failed check, and the installation guide tells callers to follow it.

The destination contract explicitly leaves unselected copies untouched and documents independent --skill-client claude_code refresh. The suggested recovery should respect that selection behavior while allowing callers to repair the copy that failed readiness.

Impact and scope

P2: a valid multi-copy installation can fail readiness while the suggested recovery selects no work and provides no affected path. Files remain intact. Explicitly selecting Claude Code produces the appropriate repair plan, and restoring the changed fixture bytes restores readiness. Approved setup repair, real client loading, other clients and other operating systems were not tested. Population frequency is unknown.

REA version

6.7.0 (source 9eb829aca3)

Runtime and platform

Node.js v26.12.1; macOS 27.0.1; arm64. No analysis engine required.

Target and artifact context

Two regular copies of the bundled seven-file reverse-engineer-anything skill: shared and Claude Code personal. One personal reference file differs by an appended comment. No analysis target or artifact.

Interface

CLI

Earliest failure stage

Setup or provider admission

Relevant output or evidence

Observed output excerpts:

doctor --skill:
  exit 1; healthy=false
  identity.skill.state="stale"
  installed_version="45"; installed_tool_count=220
  skill:identity: "Installed REA skill identity is stale."
  remediation: "Run rea setup to update the installed REA skill."
  no affected destination or path-specific issue

setup --dry-run:
  exit 0; status="planned"; plannedActions=[]
setup --skill --dry-run:
  exit 0; status="planned"; plannedActions=[]
setup --skill-client claude_code --dry-run:
  exit 0; status="planned"
  plannedActions[0].id="install_skill:claude_code"
  target="$HOME/.claude/skills/reverse-engineer-anything"

After restoring only the changed reference from bundled bytes:
  doctor --skill: exit 0; healthy=true; identity.skill.state="aligned"

Both manifests were unchanged, so version 45 and count 220 do not identify which copy contains the differing reference.

Typed outcome or recovery expected

A stale check should name the affected client or destination and give an explicit repair selection, such as rea setup --skill-client claude_code. Its preview should plan work for that destination. Keep aligned copies passing, actual drift failing, and independent setup destinations unchanged unless selected.

Analysis or suspected cause

Source-derived: Doctor.ts passes an undefined skill selection for this unqualified check. SupportedClients.ts maps undefined to all candidate destinations, while an empty selection maps to shared only. Setup.ts derives the absent skill selection from selected clients; the observed setup plans have no selected personal destination.

SetupSkill.ts aggregates canonical status while retaining the first manifest. Ordinary byte differences do not create path issues, so Doctor.ts falls back to generic setup advice and omits the differing destination.

Additional context

Related closed #3208 fixed false missing/stale diagnoses for canonical client installations. Here the changed copy is correctly stale; its recovery selection is missing. Closed #1711 fixed setup's post-install readiness scope. Here explicit skill selection reaches the right destination, while the unqualified suggested recovery does not.

Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6451 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Setup, packaging, or upgrade ### Observed behavior With a current shared skill and a changed Claude Code personal skill, `doctor --skill --format json` correctly reports stale identity but does not identify the changed destination. Its remediation is `Run rea setup to update the installed REA skill.` Both bare setup and `setup --skill` produce empty dry-run plans in this state. Explicit `setup --skill-client claude_code` instead previews an installation at the changed destination. ### Reproduction Prepare a fresh checkout at `9eb829aca34be36ff112826337996f6139f82eff`: ```sh npm ci && npm run build:cached ``` From the checkout root, run this isolated fixture. The CLI sequence was executed against the prepared build; dependency installation and rebuilding were not repeated during reproduction. Do not enable `set -e`, because the stale checks intentionally exit 1. ```sh env -i PATH="$PATH" bash --noprofile --norc <<'SH' WORK="$(mktemp -d)" export HOME="$WORK/home" export USERPROFILE="$HOME" export XDG_CONFIG_HOME="$HOME/config" export XDG_CACHE_HOME="$HOME/cache" export XDG_DATA_HOME="$HOME/data" mkdir -p "$HOME/.agents/skills" "$HOME/.claude/skills" cp -R skills/reverse-engineer-anything "$HOME/.agents/skills/" cp -R skills/reverse-engineer-anything "$HOME/.claude/skills/" # Control: both copied bundles are current; exit 0, aligned. node scripts/rea.mjs doctor --skill --format json printf '\n<!-- older installed revision -->\n' >> \ "$HOME/.claude/skills/reverse-engineer-anything/references/native-and-artifacts.md" # Exit 1, stale, generic setup remediation without the affected path. node scripts/rea.mjs doctor --skill --format json node scripts/rea.mjs setup --dry-run --format json node scripts/rea.mjs setup --skill --dry-run --format json node scripts/rea.mjs setup --skill-client claude_code --dry-run --format json node scripts/rea.mjs doctor --skill --format json # Restore only the fixture's changed file; the same doctor passes again. cp skills/reverse-engineer-anything/references/native-and-artifacts.md \ "$HOME/.claude/skills/reverse-engineer-anything/references/native-and-artifacts.md" node scripts/rea.mjs doctor --skill --format json SH ``` The stale diagnosis reproduced three times in the same fixture, including after the setup previews. The aligned and restored controls each passed once. The copies were seeded from the built bundle rather than installed through approved setup. All setup calls were previews; no repair apply was executed. ### Expected behavior Doctor should identify the stale installed destination and provide a command that selects it for repair. The [doctor contract](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/Doctor.ts#L201) promises suitable remediation for each failed check, and the [installation guide](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/docs/installation.md#L365) tells callers to follow it. The [destination contract](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/docs/installation.md#L149) explicitly leaves unselected copies untouched and documents independent `--skill-client claude_code` refresh. The suggested recovery should respect that selection behavior while allowing callers to repair the copy that failed readiness. ### Impact and scope P2: a valid multi-copy installation can fail readiness while the suggested recovery selects no work and provides no affected path. Files remain intact. Explicitly selecting Claude Code produces the appropriate repair plan, and restoring the changed fixture bytes restores readiness. Approved setup repair, real client loading, other clients and other operating systems were not tested. Population frequency is unknown. ### REA version 6.7.0 (source 9eb829aca34be36ff112826337996f6139f82eff) ### Runtime and platform Node.js v26.12.1; macOS 27.0.1; arm64. No analysis engine required. ### Target and artifact context Two regular copies of the bundled seven-file `reverse-engineer-anything` skill: shared and Claude Code personal. One personal reference file differs by an appended comment. No analysis target or artifact. ### Interface CLI ### Earliest failure stage Setup or provider admission ### Relevant output or evidence Observed output excerpts: ```text doctor --skill: exit 1; healthy=false identity.skill.state="stale" installed_version="45"; installed_tool_count=220 skill:identity: "Installed REA skill identity is stale." remediation: "Run rea setup to update the installed REA skill." no affected destination or path-specific issue setup --dry-run: exit 0; status="planned"; plannedActions=[] setup --skill --dry-run: exit 0; status="planned"; plannedActions=[] setup --skill-client claude_code --dry-run: exit 0; status="planned" plannedActions[0].id="install_skill:claude_code" target="$HOME/.claude/skills/reverse-engineer-anything" After restoring only the changed reference from bundled bytes: doctor --skill: exit 0; healthy=true; identity.skill.state="aligned" ``` Both manifests were unchanged, so version 45 and count 220 do not identify which copy contains the differing reference. ### Typed outcome or recovery expected A stale check should name the affected client or destination and give an explicit repair selection, such as `rea setup --skill-client claude_code`. Its preview should plan work for that destination. Keep aligned copies passing, actual drift failing, and independent setup destinations unchanged unless selected. ### Analysis or suspected cause Source-derived: [Doctor.ts](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/Doctor.ts#L373) passes an undefined skill selection for this unqualified check. [SupportedClients.ts](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/SupportedClients.ts#L820) maps undefined to all candidate destinations, while an empty selection maps to shared only. [Setup.ts](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/Setup.ts#L145) derives the absent skill selection from selected clients; the observed setup plans have no selected personal destination. [SetupSkill.ts](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/SetupSkill.ts#L425) aggregates canonical status while retaining the first manifest. Ordinary byte differences do not create path issues, so [Doctor.ts](https://github.com/morluto/rea/blob/9eb829aca34be36ff112826337996f6139f82eff/src/application/Doctor.ts#L442) falls back to generic setup advice and omits the differing destination. ### Additional context Related closed [#3208](https://github.com/morluto/rea/issues/3208) fixed false missing/stale diagnoses for canonical client installations. Here the changed copy is correctly stale; its recovery selection is missing. Closed [#1711](https://github.com/morluto/rea/issues/1711) fixed setup's post-install readiness scope. Here explicit skill selection reaches the right destination, while the unqualified suggested recovery does not.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3865
No description provided.