feat(sleep): group mined tasks by skill hint with catch-all fallback - #184
feat(sleep): group mined tasks by skill hint with catch-all fallback#184bogdanbaciu21 wants to merge 3 commits into
Conversation
Add a backward-compatible SessionDigest.skills_used field and populate it from well-formed Claude Skill tool-use blocks only. tools_used behavior and legacy digest payload loading are unchanged. Refs microsoft#120
Add an optional TaskRecord.skill_hint and a session_skill_hint helper. A session with exactly one harvested skill names it; absent or ambiguous hints stay empty so those tasks remain in the existing catch-all path. Refs microsoft#120
Add group_tasks_by_skill_hint: a deterministic helper that groups mined tasks by their optional skill hint in first-seen order, merges duplicate task ids once, and routes missing, conflicting, or partial hint evidence to the configured managed skill. Refs microsoft#120
There was a problem hiding this comment.
Pull request overview
This PR adds the remaining “grouping primitive” needed to route mined sleep-engine tasks per skill, using harvested Skill tool invocations as evidence, while keeping ambiguous or hint-less tasks in the existing managed-skill catch-all.
Changes:
- Add
SessionDigest.skills_usedharvesting from ClaudeSkilltool-use blocks and propagate a derivedTaskRecord.skill_hintinto both heuristic and LLM miners. - Introduce
mine.group_tasks_by_skill_hint(tasks, managed_skill_name)to deterministically group (and deduplicate) tasks by unambiguous skill hint, with a managed-skill fallback. - Add focused unit tests covering harvesting, hint propagation, dedup semantics, and grouping behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/test_sleep_skill_hint.py | Adds unit tests for skill_hint propagation, serialization, and dedup behavior. |
| tests/test_sleep_skill_harvest.py | Adds unit tests for harvesting Claude Skill tool invocations into skills_used. |
| tests/test_sleep_engine.py | Adds coverage for group_tasks_by_skill_hint behavior and ordering guarantees. |
| skillopt_sleep/types.py | Extends core dataclasses with SessionDigest.skills_used and TaskRecord.skill_hint. |
| skillopt_sleep/mine.py | Adds session_skill_hint, propagates hints in heuristic mining, extends dedup_tasks, and introduces group_tasks_by_skill_hint. |
| skillopt_sleep/llm_miner.py | Propagates session-derived skill_hint into LLM-mined tasks. |
| skillopt_sleep/harvest.py | Extracts Skill targets from tool-use blocks and persists them into digests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # ambiguous, so drop back to the catch-all path | ||
| if not ex.skill_hint: | ||
| ex.skill_hint = t.skill_hint | ||
| elif t.skill_hint and t.skill_hint != ex.skill_hint: | ||
| ex.skill_hint = "" |
|
Thanks for the welcome on #120. To keep review load bounded and follow the incremental shape Yif-Yang suggested, I'm closing this PR for now and will reopen it once #182 (the harvesting slice) lands or the maintainer asks for the next slice. The branch stays on my fork so this can be re-opened as-is. Happy to restructure if a different cadence is preferred. |
Summary
Third review-sized slice of #120: the grouping primitive, so mined tasks can be
routed per skill while everything without clear evidence stays in the existing
managed-skill catch-all.
Adds
mine.group_tasks_by_skill_hint(tasks, managed_skill_name), adeterministic, side-effect-free helper returning ordinary insertion-ordered
dicts/lists:
dedup_tasksmerge semantics(source sessions unioned, best outcome kept);
on the same non-empty hint;
unhinted observations for one ID all route to
managed_skill_name;managed_skill_namelands in that one group, never a duplicate.Nothing else changes:
mine(),filter_tasks_for_target(), cycle, gates,staging, and adoption are untouched, and the caller supplies the configured
managed-skill name rather than the helper resolving paths or reading skill files.
Tests
python -m pytest -q tests/test_sleep_engine.py -k group_tasks_by_skill_hint→ 8 passedpython -m py_compile skillopt_sleep/mine.py tests/test_sleep_engine.py→ cleanpython -m pytest -q→ 588 passed, 7 skipped (basemainat8304e6c:556 passed, 7 skipped)
Covered: empty input, legacy hint-less tasks, blank hint, interleaved
alpha/beta/alphaordering, duplicate ID merge, conflicting hints, partialhint evidence, and a hint equal to the managed skill name.
Refs #120