fix(skills): use symlink-following traversal in _find_skill - #75225
fix(skills): use symlink-following traversal in _find_skill#75225JonthanaHanh wants to merge 1 commit into
Conversation
rglob('SKILL.md') does not descend into directory symlinks, making
symlinked skill directories invisible to skill_manage operations
(create, patch, delete) while the prompt loader (which uses
os.walk(followlinks=True)) still sees them.
Replace rglob with iter_skill_index_files in both _find_skill and
_find_skill_in_other_profiles. iter_skill_index_files already uses
os.walk(followlinks=True) and is the canonical skill enumeration
path used by the prompt builder and sync subsystem.
Fixes NousResearch#75130
|
Thanks for aligning the skill-manager lookup with the established symlink-following discovery path. Current Problems
Suggested changes
Automated hermes-sweeper review. |
Summary34 PRs address or reference this issue complex, but none implements #75130's queue cap, TTL, notification, stale-anchor detection, or conflict handling. Most diffs concern external write roots or symlink-aware skill discovery; #75225 addresses only the measured manager-visibility contributor by replacing two residual rglob lookups with the shared iterator. Related pull requests
DuplicatesReader-discovery chain: #8357, #8769, #9253, #11847, #12624, #14476, and #14668 converge on merged #14230/#14740. Manager-lookup chain: #35213, #35244, #35299, #44210, #54200, #56420, #56423, #60960, and #75225 overlap #67748, while creation-root #21812/#22236/#23562 overlaps the broader #8177 design. Suggested consolidationAuthor action on #75225: add a platform-safe regression that patches SKILL.md through a directory symlink, narrow the claimed scope to non-delete mutations, and retain _validate_delete_target's symlink refusal; it remains only a partial mitigation for #75130, whose queue lifecycle needs a separate fix. Keep #67748 and #8177 open on their distinct salvage paths, close the listed manager-lookup and creation-root competitors as duplicates, and do not reopen the already implemented or salvaged closed PRs. Complex graphflowchart TD
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I35184(["issue #35184 (open)"])
I75130(["issue #75130 (open)"])
subgraph Dup35213 ["PRs duplicating each other"]
P35213["PR #35213 (open)"]
P35244["PR #35244 (open)"]
P44210["PR #44210 (open)"]
P54200["PR #54200 (closed)"]
P56420["PR #56420 (closed)"]
P56423["PR #56423 (open)"]
P60960["PR #60960 (open)"]
P67748["PR #67748 (open)"]
P75225["PR #75225 (open)"]
end
P75225 -->|fixes| I35184
P75225 -->|best fix| I75130
class I35184 open
class I75130 open
class P35213 open
class P35244 open
class P44210 open
class P54200 closed
class P56420 closed
class P56423 open
class P60960 open
class P67748 open
class P75225 open
class P67748 best
class P67748 best
class P67748 best
class P67748 best
class P75225 best
class P75225 target
click I35184 "https://github.com/NousResearch/hermes-agent/issues/35184"
click I75130 "https://github.com/NousResearch/hermes-agent/issues/75130"
click P35213 "https://github.com/NousResearch/hermes-agent/pull/35213"
click P35244 "https://github.com/NousResearch/hermes-agent/pull/35244"
click P44210 "https://github.com/NousResearch/hermes-agent/pull/44210"
click P54200 "https://github.com/NousResearch/hermes-agent/pull/54200"
click P56420 "https://github.com/NousResearch/hermes-agent/pull/56420"
click P56423 "https://github.com/NousResearch/hermes-agent/pull/56423"
click P60960 "https://github.com/NousResearch/hermes-agent/pull/60960"
click P67748 "https://github.com/NousResearch/hermes-agent/pull/67748"
click P75225 "https://github.com/NousResearch/hermes-agent/pull/75225"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 34 pull requests and 8 issues in this complex. Each diff was read against this issue; Assessment working set: 435 kB of PR diffs, 101 kB of issue/PR text, 46 kB of discussion (78 comments), 65 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
Fixes #75130
rglob("SKILL.md")does not descend into directory symlinks, making symlinked skill directories invisible toskill_manageoperations (create, patch, delete) while the prompt loader (which usesos.walk(followlinks=True)) still sees them.The reporter measured:
rglobfound 393 skills,os.walk(followlinks=True)found 399 -- 6 symlinked skills were invisible to the tool.Changes
Replace
rglob("SKILL.md")withiter_skill_index_files(skills_dir, "SKILL.md")in both:_find_skill()(line 657) -- primary skill lookup used by allskill_manageactions_find_skill_in_other_profiles()(line 796) -- cross-profile lookup for error messagesiter_skill_index_filesalready usesos.walk(followlinks=True)and is the canonical skill enumeration path used by the prompt builder and sync subsystem. This makes the tool's visibility match what the model sees.Known remaining sites
The same
rglob("SKILL.md")pattern exists in ~25 other files (skills_sync.py,skills_hub.py,skill_usage.py,profiles.py,gateway/run.py, etc.). These affect skill counting, sync, and usage tracking but not the core skill-manage tool path. A follow-up PR could migrate those toiter_skill_index_filesfor full consistency.Test plan
python -m pytest tests/tools/test_skill_manager_tool.py -xvspassesskill_manage