Skill sourcing

Skills are guidance, not gates — but a skill nobody listens to is noise. Sourcing is the loop that turns adherence + activation history into proposals: retire skills that aren't followed, propose skills for behaviors that recur without one.

Why mine

M0.7 closed the activation and adherence loops. M0.8 closes the catalog loop:

DirectionQuestion it answers
RetireWhich currently-registered skills consistently fail to be followed?
ProposeWhich agent behaviors recur across tasks but aren't represented as a skill?

Proposals, not changes

Sourcing emits structured suggestions. A human (or autopilot in a future milestone) decides whether to apply them. xc skills mine never edits registry.ts for you.

Signals it reads

SignalSourceImplication
Adherence rate per skillflow-events.jsonlLow rate over a window → retirement candidate
Activation vs. adherence ratioflow-events.jsonlActivated but never observably followed → strong retirement signal
Recurring tool patternsflow-events.jsonlHigh-frequency pattern with no covering skill → proposal candidate

Thresholds (M0.8 defaults)

SignalDefault threshold
adherence-lowrate < 0.5 over ≥ 10 adherence events for that skill
never-followed(activations − adherence verdicts) / activations > 0.8 over ≥ 20 activations
unmatched-patterntool bucket fired ≥ 25 times within the window

Override the lookback window with --window N. The defaults bias toward few false positives — sourcing only fires when the signal is hard to argue with.

CLI

bash
xc skills mine                          # human report
xc skills mine --json                   # structured (CI-friendly)
xc skills mine --window 500             # wider lookback
xc skills mine --diff-since 2026-05-01  # only new since this date
xc skills mine --exit-code-on-proposal  # CI mode — non-zero when proposals exist

Proposal shape

ts
interface SkillProposal {
  id: string                              // deterministic — re-runs are idempotent
  createdAt: string                       // ISO date
  kind: 'retire' | 'propose'
  skill: string                           // existing id, or slug for a proposed one
  confidence: number                      // 0..1
  reason: string                          // human-readable, ≤ 120 chars
  signal: {
    type: 'adherence-low' | 'never-followed' | 'unmatched-pattern' | 'commit-convention'
    metric: number
    sampleSize: number
  }
  evidence: ReadonlyArray<{ summary: string }>
  suggested: {
    scaffold?: { id, name, description, detectHint, matchHint, promptOutline }
    retirementCommand?: string
  }
}

Persistence

Each new proposal is appended to .xcoder/cache/skill-proposals.jsonl. IDs are derived from (kind, skill, signal.type, day), so re-running on the same data the same day does not duplicate. A long-running pattern can re-surface tomorrow if it persists.

How to act on a proposal

  • Retire: apply the printed retirementCommand manually — drop the skill from packages/xcoder/src/skills/registry.ts. Run xc skills bench after to confirm fixture coverage still holds.
  • Propose: the proposal includes a scaffold block — id, name, description, detect/match hints, and a prompt outline. Hand-write the skill in packages/xcoder/src/skills/<id>.ts, register it, and add at least one fixture row that exercises its match().

Out of scope (M0.8)

  • Agentic refinement — the model proposing skill bodies. (M0.9.)
  • Auto-applying skill scaffolds — committed registry edits. New skills always require human review.
  • Cross-repo trend mining — proposals derived from multiple repos at once. Slots into M1 (Context Engine).

Next