Skip to content

Skill lifecycle phase 1: typed frontmatter, usage tracking, plumbing fixes - #621

Merged
jamiepine merged 3 commits into
mainfrom
jamiepine/skill-lifecycle
Aug 8, 2026
Merged

Skill lifecycle phase 1: typed frontmatter, usage tracking, plumbing fixes#621
jamiepine merged 3 commits into
mainfrom
jamiepine/skill-lifecycle

Conversation

@jamiepine

Copy link
Copy Markdown
Member

Phase 1 of the skill lifecycle design (docs/design-docs/skill-lifecycle.md, included in this PR). This lays the foundations for the self-improvement loop — typed skill metadata, per-skill provenance/usage tracking, and a pile of fixes in the existing skill plumbing. The mutation tool, reflection branch, and curation land in later phases.

Typed frontmatter

The hand-rolled frontmatter parser is gone. SKILL.md frontmatter now parses through serde_yaml into a typed struct, so YAML lists and multiline scalars actually work:

#[derive(Debug, Clone, Default, Deserialize)]
pub struct SkillFrontmatter {
    pub name: Option<String>,
    pub description: Option<String>,
    pub platforms: Option<Vec<Platform>>,   // hard gate vs host OS; absent = all
    pub tags: Option<Vec<String>>,
    pub related_skills: Option<Vec<String>>,
    pub source_repo: Option<String>,
}

Unknown fields are ignored (skills from other ecosystems carry version, author, etc.), and unknown platform values deserialize to Platform::Other — the skill is skipped on this host rather than failing to parse. Skills gated to another platform don't load at all.

Skill directories can now carry support subdirs (references/, templates/, scripts/, assets/); their files are excluded from discovery and returned by read_skill as linked_files. Hidden directories (.archive, .git, ...) are excluded from discovery.

skill_usage table

New per-agent migration tracking provenance and usage per skill: created_by ('user' | 'agent' | 'installed'), lifecycle state, pinned, read/patch counters, timestamps. Skills on disk with no row get seeded on first sight with created_at = now (a fresh install shouldn't look 90 days stale) and created_by = 'user' (the origin that protects them from future auto-curation). The registry installer marks its skills 'installed'; read_skill bumps read_count and reactivates stale skills. WriteOrigin is defined here too — Phase 2's skill_manage rails dispatch on it.

Fixes in passing

  • API skill mutations (install/remove/upload) now reload the live SkillSet deterministically instead of hoping the file watcher notices (reload_after_skill_change). Instance-level installs reload every running agent.
  • The watcher creates skills roots before watching them, so a skills dir created after startup is still covered, and classifies changed paths by prefix against the actual watched roots instead of contains("skills").
  • skills_search was formatting the HTTP status slot with body.len(). Now it's the status.
  • read_skill output is capped at the standard 50 KB tool budget.
  • Skill descriptions are truncated to 80 chars in prompt indexes (budget enforcement on write paths comes with skill_manage).

Toolset changes

  • skills_search and install_skill are now on the channel toolset, completing the port out of the deprecated cortex-chat server (tools.rs TODO). config_inspect is the last unique tool left there.
  • Branches get the skill index in their system prompt (they previously had none) plus read_skill, so a branch can consult procedure before delegating — and it's the substrate the Phase 3 reflection branch builds on.

Testing

New unit tests for YAML list/multiline parsing, platform tolerance, description truncation, and the usage store (seeding idempotence, read-count/reactivation, installed-provenance override, row removal) — the store tests run the real migration against in-memory SQLite.

Plan for the self-improvement loop: outcome -> skill pump on a reflection
branch, curation in cortex maintenance, one origin-scoped skill_manage tool,
and provenance/usage tracking in per-agent SQLite. Studied against the
Hermes agent implementation and a live 126-skill corpus. Supersedes
skill-authoring.md. Five build phases, this doc is the spec for all of them.
Phase 1 of docs/design-docs/skill-lifecycle.md:

- Replace the hand-rolled frontmatter parser with serde_yaml into a typed
  SkillFrontmatter (platforms hard-gate against the host OS, tags,
  related_skills). Unknown fields and unknown platform values are tolerated.
- Support subdirs (references/templates/scripts/assets) surface as
  linked_files from read_skill; hidden dirs excluded from discovery.
- New skill_usage table + SkillUsageStore: created_by provenance, lifecycle
  state, read/patch counters. Rows seed on first sight, installer marks
  'installed', read_skill bumps read_count and reactivates stale skills.
  WriteOrigin defined for the phase-2 skill_manage rails.
- API skill mutations reload the live SkillSet deterministically instead of
  relying on the file watcher; instance installs reload all agents.
- Watcher creates skills roots before watching and classifies changes by
  prefix against watched roots instead of contains("skills").
- skills_search HTTP errors report the status instead of body.len().
- read_skill output capped at the 50KB tool budget; index descriptions
  truncated to 80 chars.
- skills_search/install_skill ported to the channel toolset (cortex-chat
  TODO); branches get the skill index fragment and read_skill.
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9dd6f509-bb35-48ba-a3a7-67b260ebd582

📥 Commits

Reviewing files that changed from the base of the PR and between c8c3f4d and 6f818cf.

📒 Files selected for processing (4)
  • src/api/skills.rs
  • src/skills.rs
  • src/skills/builtin.rs
  • src/skills/usage.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/api/skills.rs
  • src/skills/usage.rs

Walkthrough

This change defines the skill lifecycle, adds typed metadata and SQLite usage tracking, integrates skill reloads with runtime initialization and mutations, and exposes skill metadata and tools through branch and channel workflows.

Changes

Skill lifecycle

Layer / File(s) Summary
Lifecycle design and rollout
docs/design-docs/skill-lifecycle.md
Defines metadata, mutation, usage, reflection, curation, API, configuration, rollout phases, and non-goals.
Typed skill metadata and discovery
src/skills.rs, src/skills/builtin.rs, src/skills/installer.rs
Adds typed YAML frontmatter, platform filtering, support-file discovery, related-skill metadata, bounded descriptions, and hidden-directory exclusion.
Usage persistence and provenance
migrations/20260808000001_skill_usage.sql, src/skills/usage.rs
Adds SQLite storage for skill provenance, lifecycle state, read counters, installation tracking, archival fields, and removal.
Runtime initialization and mutation reloads
src/config/runtime.rs, src/config/watcher.rs, src/api/agents.rs, src/api/skills.rs, src/main.rs, src/tools/install_skill.rs
Attaches usage stores, seeds configured skills, reloads affected agents after mutations, records provenance, and watches exact skill roots.
Branch prompts and skill tools
src/prompts/*, prompts/en/*, src/agent/channel_dispatch.rs, src/tools.rs, src/tools/read_skill.rs, src/tools/skills_search.rs
Adds available-skill prompt rendering, branch skill reading, channel skill tools, usage recording, metadata output, and corrected HTTP errors.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: typed frontmatter, usage tracking, and related Phase 1 plumbing fixes.
Description check ✅ Passed The description directly explains the typed frontmatter, usage tracking, plumbing fixes, tool changes, and tests included in the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jamiepine/skill-lifecycle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jamiepine
jamiepine marked this pull request as ready for review August 8, 2026 09:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/skills.rs`:
- Around line 190-195: Preserve effective skill provenance across all listed
sites in src/api/skills.rs:190-195, src/api/skills.rs:288-290,
src/api/skills.rs:337-345, and src/api/skills.rs:501-501. In the installation
flow, reconcile usage from the reloaded SkillSet and call record_installed only
for skills whose instance source is effective; do not mark workspace-overridden
skills as installed. During removal, retain and reconcile the usage row when an
instance or builtin fallback becomes effective. For direct API uploads, record
user provenance through the appropriate usage API instead of record_installed.

In `@src/skills.rs`:
- Around line 360-362: Update index_description to enforce DESCRIPTION_BUDGET by
Unicode character count rather than byte length, replacing
truncate_utf8_ellipsis with the appropriate character-aware truncation helper.
Add a Unicode test covering multibyte descriptions that remain within the
character budget.
- Around line 62-87: Update the platform matching logic that uses Platform::host
and the deserialized platform list so Platform::Other never satisfies the
contains check; compare only known variants (Linux, Macos, and Windows). Add a
test covering an unknown frontmatter platform on an unsupported host, asserting
the skill is not loaded.
- Around line 488-498: Update the linked-file traversal around the directory
read and entry iteration to ignore only NotFound errors for optional support
directories, while logging or propagating all other I/O failures. Replace the
silent `let Ok(...) else { continue }` and `while let Ok(...)` handling without
changing successful directory and file discovery behavior.

In `@src/skills/builtin.rs`:
- Around line 36-50: Update parse_builtin to apply the existing platform matcher
to frontmatter.platforms before constructing Skill, returning the same skip
behavior used for filesystem skills when the host is unsupported. Add a test
covering that a platform-specific built-in skill is excluded on a non-matching
host.

In `@src/skills/usage.rs`:
- Around line 111-115: Update the INSERT conflict-update clause in the skill
usage installation query to set origin_conversation_id to NULL alongside
created_by = 'installed', ensuring installation removes prior agent provenance.
Add a conflict test covering an existing agent-created row and verify its origin
conversation is cleared after installation.

In `@src/tools.rs`:
- Around line 782-783: The cleanup calls for SkillsSearchTool::NAME and
InstallSkillTool::NAME silently discard remove_tool failures; update this
removal flow to handle each Result by logging unexpected errors or propagating
them, while preserving the existing cleanup behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d559efed-2563-4fbf-9160-a8231c66a416

📥 Commits

Reviewing files that changed from the base of the PR and between 29ed4d6 and c8c3f4d.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
  • Cargo.toml is excluded by !**/*.toml
📒 Files selected for processing (20)
  • docs/design-docs/skill-lifecycle.md
  • migrations/20260808000001_skill_usage.sql
  • prompts/en/branch.md.j2
  • prompts/en/fragments/skills_branch.md.j2
  • src/agent/channel_dispatch.rs
  • src/api/agents.rs
  • src/api/skills.rs
  • src/config/runtime.rs
  • src/config/watcher.rs
  • src/main.rs
  • src/prompts/engine.rs
  • src/prompts/text.rs
  • src/skills.rs
  • src/skills/builtin.rs
  • src/skills/installer.rs
  • src/skills/usage.rs
  • src/tools.rs
  • src/tools/install_skill.rs
  • src/tools/read_skill.rs
  • src/tools/skills_search.rs

Comment thread src/api/skills.rs
Comment thread src/skills.rs
Comment thread src/skills.rs
Comment thread src/skills.rs Outdated
Comment thread src/skills/builtin.rs
Comment thread src/skills/usage.rs
Comment thread src/tools.rs
- Platform::Other never matches the host: a skill gated to unrecognized
  platforms stays off every host, and an unrecognized host OS fails gates
  instead of passing them. Built-in skills now respect the same gate.
- Description budget applied by character count, not bytes.
- linked_files discovery logs I/O errors instead of discarding them
  (NotFound stays silent — support dirs are optional).
- record_installed clears origin_conversation_id when replacing an
  agent-created row.
- Uploaded skills seed as 'user' provenance instead of 'installed' —
  they're user-provided, not registry installs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant