Repository navigation
feat(skills): add auto-skill curator #7846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
1596751
feat(skills): add auto-skill curator
DragonnZhang d70df62
fix(i18n): translate /curator command descriptions for zh and zh-TW
claude 91699bf
fix(i18n): add English source keys for /curator command
claude fc10834
fix(skills): align curator lifecycle safeguards
DragonnZhang d5a1c70
fix(skills): harden curator trust and name guards
DragonnZhang a0c943a
fix(skills): guard curator mutations by workspace trust
DragonnZhang 2f8b325
test(skills): cover curator stale-to-active reactivation path
claude 6ca1eb9
Merge branch 'main' into dragon/auto-skill-curator
claude 70d1395
test(skills): cover curator rollback and restore-collision paths
claude f35f0fe
test(cli): cover curator command errors and stacked auto-skill usage
claude 171ac3f
fix(skills): reject control-byte auto-skill directory names
claude 1c3c030
fix(skills): guard curator state reads and clarify restore errors
claude 4915a72
fix(skills): close curator TOCTOU reads and preserve seeding baseline
claude 2bf5324
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot c95980b
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot f3814a1
fix(core): harden auto-skill curator per review feedback (#7846)
qwen-code-dev-bot 8d4b0a4
test(core): cover curator restore rollback and re-read guard (#7846)
qwen-code-dev-bot f7e2178
fix(core): record auto-skill usage on re-invocation (#7846)
qwen-code-dev-bot ddfac38
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot 536f3a6
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot 1a3c632
Merge branch 'main' into dragon/auto-skill-curator
wenshao 86f63a4
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot 83e3854
fix(skills): preserve curator read failures
DragonnZhang 2d6c8f9
fix(skills): harden curator lifecycle guards
DragonnZhang 3b8d733
test(skills): cover curator safety paths
DragonnZhang 1bd2238
fix(skills): address curator review findings (#7846)
b753a50
fix(cli): localize curator messages
DragonnZhang fec3a19
Merge branch 'main' into dragon/auto-skill-curator
1829624
test(skills): cover curator usage safeguards
DragonnZhang 77f11c0
fix(skills): address curator review feedback (#7846)
qwen-code-ci-bot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| # Auto-Skill Curator | ||
|
|
||
| ## Problem | ||
|
|
||
| Qwen Code can extract reusable project skills from tool-heavy conversations, | ||
| but accepted auto-skills only accumulate. The existing review agent can create | ||
| or update `source: auto-skill` skills and is explicitly forbidden from deleting | ||
| them. Path gating and `skills.disabled` reduce prompt noise but do not maintain | ||
| the on-disk library. | ||
|
|
||
| ## Scope | ||
|
|
||
| Add a small, deterministic lifecycle manager for project auto-skills: | ||
|
|
||
| - Track successful invocations of project skills whose directory starts with | ||
| `auto-skill-` and whose frontmatter contains `source: auto-skill`. | ||
| - Mark a managed skill stale after 30 days without activity. | ||
| - Archive it after 90 days without activity by moving its whole directory out | ||
| of `.qwen/skills/` into `.qwen/archived-skills/`. | ||
| - Allow individual managed skills to be pinned out of automatic transitions. | ||
| - Run the deterministic pass at most once every 7 days during configuration | ||
| initialization when Auto Skill is enabled and the workspace is trusted. | ||
| - Expose `/curator`, `/curator status`, `/curator run [--dry-run]`, and | ||
| `/curator pin|unpin|restore <directory>` in interactive, non-interactive, | ||
| and ACP command surfaces. | ||
|
|
||
| This first version does not use an LLM, consolidate overlapping skills, manage | ||
| personal/bundled/extension/learned/hand-authored skills, permanently delete | ||
| anything, or introduce configurable thresholds. | ||
|
|
||
| ## Ownership and persistence | ||
|
|
||
| The curator is resolved only from `Config.getProjectRoot()`. Its state lives at | ||
| `<project>/.qwen/skill-curator.json`, and archived packages live at | ||
| `<project>/.qwen/archived-skills/`. There is no fallback to the process's | ||
| primary workspace, home directory, or another active session. This keeps | ||
| daemon and multi-workspace sessions isolated. | ||
|
|
||
| State is keyed by the auto-skill directory name because that is the unit moved | ||
| to and from the archive. Each record stores the frontmatter skill name, | ||
| first-seen time, last successful use, use count, lifecycle state, pin state, | ||
| and optional archive time. Writes are serialized with a cross-process lock and | ||
| committed atomically. | ||
|
|
||
| Corrupt state is a hard, non-mutating failure. The curator must not infer that | ||
| missing usage means inactivity when its persisted evidence cannot be read. | ||
|
|
||
| ## Eligibility and safety | ||
|
|
||
| A directory is curator-managed only when every condition holds: | ||
|
|
||
| 1. It is a direct, non-symlink directory under the project skills root. | ||
| 2. Its name starts with `auto-skill-`. | ||
| 3. It contains a regular, non-symlink `SKILL.md`. | ||
| 4. The opening YAML frontmatter contains exactly `source: auto-skill`. | ||
|
|
||
| This double marker prevents the curator from moving hand-authored, learned, | ||
| extension, bundled, personal, malformed, or symlinked content. Archive and | ||
| restore never overwrite an existing skill. A destination collision skips only | ||
| that package so unrelated maintenance can continue. Archived directory names | ||
| are shown as reserved in the review prompt and rejected by its write permission | ||
| guard, while confirmation staging still snapshots active skills only. | ||
| If state persistence fails after moves, the pass attempts to move every package | ||
| back before surfacing the error. | ||
|
|
||
| Read-only status and dry-run previews remain available in safe mode and | ||
| untrusted workspaces. Applying a maintenance pass, pinning, unpinning, and | ||
| restoring require a trusted workspace outside safe mode. | ||
|
|
||
| ## Activity and transitions | ||
|
|
||
| A successful Skill tool or direct skill slash-command invocation updates an | ||
| eligible auto-skill record best-effort, even while automatic skill generation | ||
| is disabled. This keeps observed activity independent from the switch that | ||
| controls generation and scheduled maintenance. Failed, skill-disabled, or | ||
| hook-blocked invocations do not count. | ||
|
|
||
| For a live skill, activity is the newest of: | ||
|
|
||
| - the persisted last successful invocation; | ||
| - the persisted first-seen time; | ||
| - the persisted restore time; and | ||
| - the skill manifest modification time. | ||
|
|
||
| Including modification time prevents a recently improved skill from being | ||
| archived merely because it has not yet been invoked again. | ||
|
|
||
| The first observation of each eligible skill seeds `firstSeenAt = now` rather | ||
| than inferring inactivity from an old filesystem timestamp. The first automatic | ||
| observation also seeds `lastRunAt`, then waits a full 7-day interval. Explicit | ||
| `/curator run` bypasses the interval but preserves per-skill first-sight grace; | ||
| `--dry-run` reports the same seeding and transition candidates without moving | ||
| directories or changing state. Pinned records bypass stale and archive | ||
| transitions until explicitly unpinned. | ||
|
|
||
| ## Integration points | ||
|
|
||
| - `Config.initialize`: performs the due deterministic pass before | ||
| `SkillManager` scans the filesystem. | ||
| - `SkillTool`: records a successful managed-skill invocation. | ||
| - `SkillCommandLoader` and the interactive/non-interactive command processors: | ||
| record successful direct slash-command invocations; ACP reuses the | ||
| non-interactive processor. | ||
| - `SkillManager`: its existing refresh path is used after manual archive or | ||
| restore so the model and slash-command surfaces immediately match disk. | ||
| - `BuiltinCommandLoader`: publishes the new `/curator` command. | ||
|
|
||
| No other consumer should write curator state or move managed skill packages. | ||
|
|
||
| ## Verification | ||
|
|
||
| Unit tests cover eligibility, first-run seeding, stale/archive thresholds, | ||
| dry-run non-mutation, recent-use protection, recently-modified protection, | ||
| corrupt-state fail-closed behavior, collision handling, restoration, and the | ||
| command surface. Existing Skill tool tests verify that only successful loads | ||
| record usage. Build and typecheck cover the cross-package export and command | ||
| registration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.