Context
The design spec (docs/superpowers/specs/2026-06-07-skillopt-sleep-claude-code-plugin-design.md, open question 4) poses this as an unresolved fork:
Skill target: evolve a new dedicated skillopt-sleep-managed skill, or also edit your existing hand-written skills in ~/.claude/skills?
The shipped engine took the "new dedicated skill" branch by default (config.py's managed_skill_name: skillopt-sleep-learned, always written to regardless of which skills were actually active during the harvested sessions). Question 4 was never actually decided or closed out — it's still open in the doc.
Problem
Today, cycle.py always resolves a single fixed live_skill_path via cfg.managed_skill_path() and consolidates every mined task against that one skill doc. There's no step that:
- Detects which existing skills (
Skill tool invocations) were actually used in a harvested session, and
- Routes the mined tasks + proposed edits to that skill's real
SKILL.md instead of (or in addition to) the generic managed skill.
There is a partial building block already in the codebase for manually targeting one existing skill — target_skill_path / target_skill_text in config.py and the keyword-relevance filter in mine.py (filter_tasks_for_target) — but it requires the user to hand-configure a single static path up front. It doesn't auto-discover multiple skills touched across sessions and doesn't fan out edits per-skill.
Proposed change
harvest.py: while walking a transcript, record Skill tool-use invocations (skill name) into SessionDigest.skills_used.
types.py: propagate a skill_hint onto mined TaskRecords from the session(s) they came from.
mine.py: group tasks by skill_hint (tasks with no hint fall into the existing catch-all managed skill).
cycle.py: loop over skill groups instead of a single fixed skill — for each, resolve the real on-disk SKILL.md (~/.claude/skills/<name>/SKILL.md or installed-plugin cache path), read it, consolidate against it independently, and stage a proposal for it.
staging.py: support N staged proposed_SKILL.md files per night (one per touched skill) instead of assuming exactly one skill + one memory file; adopt needs to iterate all of them.
- Gate stays per-skill-group so one skill's weak signal doesn't block acceptance for another.
Why
Without this, SkillOpt-Sleep can only ever grow one generic bucket-skill from usage — it can't actually improve the skills people already wrote and use day to day (e.g. code-review, constitution, custom domain skills), which is the more valuable target for most real setups.
Happy to sketch a PR for the harvest + grouping slice (steps 1–3) first as a smaller, testable increment ahead of the staging/adopt fan-out (steps 4–6), if that's a better shape for review.
Context
The design spec (
docs/superpowers/specs/2026-06-07-skillopt-sleep-claude-code-plugin-design.md, open question 4) poses this as an unresolved fork:The shipped engine took the "new dedicated skill" branch by default (
config.py'smanaged_skill_name: skillopt-sleep-learned, always written to regardless of which skills were actually active during the harvested sessions). Question 4 was never actually decided or closed out — it's still open in the doc.Problem
Today,
cycle.pyalways resolves a single fixedlive_skill_pathviacfg.managed_skill_path()and consolidates every mined task against that one skill doc. There's no step that:Skilltool invocations) were actually used in a harvested session, andSKILL.mdinstead of (or in addition to) the generic managed skill.There is a partial building block already in the codebase for manually targeting one existing skill —
target_skill_path/target_skill_textinconfig.pyand the keyword-relevance filter inmine.py(filter_tasks_for_target) — but it requires the user to hand-configure a single static path up front. It doesn't auto-discover multiple skills touched across sessions and doesn't fan out edits per-skill.Proposed change
harvest.py: while walking a transcript, recordSkilltool-use invocations (skill name) intoSessionDigest.skills_used.types.py: propagate askill_hintonto minedTaskRecords from the session(s) they came from.mine.py: group tasks byskill_hint(tasks with no hint fall into the existing catch-all managed skill).cycle.py: loop over skill groups instead of a single fixed skill — for each, resolve the real on-diskSKILL.md(~/.claude/skills/<name>/SKILL.mdor installed-plugin cache path), read it, consolidate against it independently, and stage a proposal for it.staging.py: support N stagedproposed_SKILL.mdfiles per night (one per touched skill) instead of assuming exactly one skill + one memory file;adoptneeds to iterate all of them.Why
Without this, SkillOpt-Sleep can only ever grow one generic bucket-skill from usage — it can't actually improve the skills people already wrote and use day to day (e.g.
code-review,constitution, custom domain skills), which is the more valuable target for most real setups.Happy to sketch a PR for the harvest + grouping slice (steps 1–3) first as a smaller, testable increment ahead of the staging/adopt fan-out (steps 4–6), if that's a better shape for review.