You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 85f0c50
Browse filesBrowse the repository at this point in the historyBrowse files
fix(md): return skill bodies from list_by_cluster; correct docs
Security review of 1b8cf11 + add842d found the list_by_cluster fix was
incomplete: it stopped its own enumeration from dropping a skill whose
directory suffix wasn't a sanitizer fixpoint, but the caller
(_hydrate_algo_skills) still re-read each selected skill by
fm.name via read_main, which re-derives (and re-sanitizes) a path from
that name and drops it there instead. Reproduced on a real
filesystem: skill_My Skill/ enumerates fine, but
read_main("My Skill") re-derives to skill_My_Skill/ and misses. The
drop moved one layer downstream; existing_relevant_skills was empty
before and after the prior fix.
Fix: list_by_cluster now returns (frontmatter, body) pairs instead of
frontmatter alone, so the caller never needs a second, name-based
read. _select_existing_skills / _rank_skills_by_relevance updated to
carry (fm, body) tuples through selection; _hydrate_algo_skills is
deleted — the body is already in hand, so there's nothing left for it
to do. This closes the drop for real, removes the second disk read
(the 2n-read concern carried since Task 4), and makes "the reader
never derives a path" true end-to-end rather than true only for
list_by_cluster's own enumeration step.
New end-to-end regression test
(test_select_existing_skills... / test_existing_skills_reaches_llm_for_skill_whose_directory_has_a_space)
seeds a skill_My Skill/ directory directly on disk (bypassing the
writer) and runs the real extract_agent_skill strategy against it,
asserting the skill reaches existing_relevant_skills with non-empty
content — the property the previous commit's test docstring claimed
but the code didn't yet deliver. The reader-level regression test
gained the same body assertion.
Also, per review:
- path_safety.py: corrected the NFC docstring claim, which was wrong
for the ~1,082 Unicode composition-exclusion codepoints (e.g.
Devanagari क़/ख़, U+0958/U+0959) — NFC decomposes an
already-precomposed exclusion character instead of preserving it, so
the combining mark is stripped either way. Scoped the claim to
"best-effort for the common case", not a guarantee for every script.
New test pins this directly.
- Dropped the e2e test's unused _reset_rerank_capability_singleton
fixture parameter: the reviewer adjudicated the earlier instruction
conflict the other way — ordering is only meaningful between
fixtures that touch the same state, and this fixture never reads or
writes the rerank capability at all.
- Widened the skill-name collision documentation (SkillPathMixin.sanitize_skill_name,
CHANGELOG) beyond dropped-punctuation / space-collapse / truncation
to the larger case: every combining mark is non-\w and is stripped
regardless of script, so e.g. Devanagari "किताब" and "कताब" both
collapse to "कतब" (same for Thai tone marks, Hebrew niqqud, Arabic
harakat).
- Corrected the collision justification: because _persist_skill
sanitizes before frontmatter construction, the LLM sees the
already-sanitized name in existing_relevant_skills, so a colliding
raw name is an *affirmative* decision that two skills are different,
not a probable intended update. The decision to accept collisions
still stands, but on its real grounds: a disambiguating suffix would
break the fm.name == directory-suffix identity the reader/writer
seam relies on, and detecting-and-raising would reintroduce the
dead-letter DoS.
- Merged two consecutive "# -- Internals --" banners in
agent_skill_reader.py into one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments