myco:operate-skill-lifecycle-pipeline · git:20260625.1d84427 · 2026-06-25 · sha256 13d35e8dd95952aa

myco:operate-skill-lifecycle-pipeline git:20260625.1d84427A

Immutable. This exact content is served forever at /api/v1/blob/13d35e8dd95952aa.

---
name: myco:operate-skill-lifecycle-pipeline
description: Use this skill when working with Myco's skill lifecycle system — whether generating a new skill from an approved candidate, reviewing the candidate queue, updating a stale skill, retiring an outdated one, or debugging why a skill wasn't triggered. Activates whenever you touch vault_skill_candidates, vault_skill_records, or vault_write_skill — or whenever the user asks about skills, the Skills dashboard, skill generation tasks, or the .agents/skills/ directory. Apply this skill even if the user doesn't explicitly say "skill lifecycle" — any time a task involves producing or updating a SKILL.md file, evaluating candidates, or managing skill status, this procedure applies.
managed_by: myco
user-invocable: true
allowed-tools:
  - Read
  - Edit
  - Write
  - Bash
  - Grep
  - Glob
---

# Operating the Myco Skill Lifecycle Pipeline

Hands-on reference for managing skill candidates, skill records, and SKILL.md files using Myco's agent tools and Skills dashboard.

## Pipeline Architecture and Scheduling

**Asymmetric scheduling defaults** reflect a deliberate progressive disclosure model:
- `skill-survey` is `enabled: true` (auto-runs during idle, discovers candidates without user intervention)
- `skill-generate` and `skill-evolve` are `enabled: false` (require explicit opt-in)

This prevents runaway generation costs while ensuring candidate discovery happens automatically.

**Survey quality transformation:** The survey pipeline now runs cluster-first (grouping related spores before proposing candidates), producing 5 domain-scoped candidates vs the old pipeline's 102 candidates with 74.5% dismissed. This dramatically improves signal-to-noise ratio.

## Tool Reference

### vault_skill_candidates
Manages skill candidates — knowledge clusters identified as potential skills.

```
// List by status
vault_skill_candidates(action: "list", status: "identified"|"approved"|"dismissed"|"generated")

// Get single candidate
vault_skill_candidates(action: "get", id: "<uuid>")

// Approve a candidate
vault_skill_candidates(action: "update", id: "<uuid>", status: "approved", rationale: "...")

// Create a candidate manually
vault_skill_candidates(action: "create", topic: "...", rationale: "...")
```

Status lifecycle: `identified` → `approved` → `generated`. Dismiss with `status: "dismissed"`.

**UI Labels:** In the Skills dashboard, "Approved" status is labeled "Awaiting generation" for clarity. Use the combined "Approved & generated" filter to see the full pipeline progress.

### vault_skill_records
Manages materialized skill records (the DB representation of files on disk).

```
// List active/stale/retired skills
vault_skill_records(action: "list", status: "active"|"stale"|"retired")

// Get a specific skill (by name or UUID)
vault_skill_records(action: "get", id: "<name-or-uuid>")

// Retire a skill
vault_skill_records(action: "update", id: "<uuid>", status: "retired")
```

### vault_write_skill
**Staging-based workflow:** `vault_write_skill` now writes to `.myco/staging/skills/<candidate_id>/SKILL.md` as a provisional draft. The skill remains in staging until promoted via `vault_finalize_skill` (human approval required).

```
vault_write_skill(
  name: "kebab-case-name",           // directory name — no myco: prefix here
  display_name: "Title",
  description: "triggering description",
  content: "<full SKILL.md with frontmatter>",
  source_ids: "id1,id2",             // optional: comma-separated spore IDs
  rationale: "what changed",         // optional: written into lineage
  candidate_id: "<uuid>"             // required for staging workflow
)
```

**Quality gate enforces at write time:**
- YAML frontmatter with all required fields
- `name: myco:<name>` prefix
- `managed_by: myco`
- `user-invocable` field present
- `allowed-tools` containing **Claude Code tool names only** — vault_* names are rejected
- ≤500 lines total

**Security enforcement:** Agents cannot self-promote skills from staging to live. The `vault_finalize_skill` tool requires human review and explicit approval.

### vault_finalize_skill
Promotes a staged skill draft to the live `.agents/skills/` directory and creates the corresponding skill record.

```
vault_finalize_skill(candidate_id: "<uuid>")
```

This tool is human-only — agents cannot call it directly. It provides the final quality gate and audit trail via `approved_at` timestamps.

## Producing a SKILL.md File

### From an approved candidate (staging workflow)

1. Get the candidate: `vault_skill_candidates(action: "get", id: "<uuid>")`
2. Search for related spores: `vault_search_semantic(query: "<topic>", limit: 10)`
3. Write to staging: use `vault_write_skill` with `candidate_id` parameter
4. **Human review required:** The skill remains in `.myco/staging/` until promoted
5. After promotion, the candidate status automatically updates to `generated`

### Updating an existing skill

1. Get current record: `vault_skill_records(action: "get", id: "<name>")`
2. Read the file at the `path` field to see current content
3. Identify what changed — update only the affected sections
4. Write with `rationale` describing what was updated
5. **Direct write to live:** Skill updates bypass staging and write directly to `.agents/skills/`

**Critical when updating:** Check `allowed-tools` in the existing frontmatter **before** carrying it forward. If it contains vault_* names (vault_create_spore, vault_search_semantic, vault_write_skill, etc.), replace them with Claude Code tools. The gate will reject the write otherwise. See Contamination section below.

### Hand-authoring skills in feature PRs

When manually creating or editing skills during development (e.g., in a feature branch), additional symlink setup is required for discoverability in Claude Code and Cursor:

1. Create or edit the skill in `.agents/skills/<name>/SKILL.md` as usual
2. Create symlinks for editor discovery:
   ```bash
   # For Claude Code
   mkdir -p .claude/skills/
   ln -sf ../../.agents/skills/<name> .claude/skills/<name>
   
   # For Cursor  
   mkdir -p .cursor/skills/
   ln -sf ../../.agents/skills/<name> .cursor/skills/<name>
   ```
3. Commit both the skill and the symlinks to your feature branch
4. The symlinks ensure the skill is discoverable during manual authoring sessions

**Without these symlinks,** hand-authored skills remain invisible to Claude Code and Cursor even though they exist in `.agents/skills/`. The editors only scan their respective skill directories (`.claude/skills/` and `.cursor/skills/`) during session startup.

### Splitting an oversized skill

1. Identify distinct procedures in the current skill
2. Write each as a new focused skill with its own name and description
3. Retire the parent: `vault_skill_records(action: "update", status: "retired")`

### Retiring a skill

```
vault_skill_records(action: "update", id: "<uuid>", status: "retired")
```

Retiring preserves the record and lineage but removes the skill from the active pool. Use when a skill has been superseded by focused replacements or the procedure is no longer applicable.

## Frontmatter Requirements

Every SKILL.md must contain all six required fields in its YAML frontmatter:

| Field | Requirement |
|---|---|
| `name` | `myco:<kebab-case-name>` — must match directory name |
| `description` | Triggering description — primary matching signal for Claude Code |
| `managed_by` | Always `myco` |
| `user-invocable` | Always `true` for developer-facing skills |
| `allowed-tools` | Claude Code tools only: `Read`, `Edit`, `Write`, `Bash`, `Grep`, `Glob` |

**Omitting any of these fields causes a vault_write_skill rejection**, even if the field was present in a prior version. Mid-session rewrites that regenerate frontmatter from scratch are a common source of silent omissions.

## Diagnosing vault_write_skill Rejections

**3-gate dedup check runs before any file is written:** (1) same-name match routes to the evolve path rather than rejecting outright, (2) fulfilled-candidate guard rejects if the `candidate_id` already links to a different skill, (3) Jaccard description similarity gate rejects at threshold 0.4. If the DB write fails after the file is created, the file is atomically removed to prevent orphans.

The tool returns a descriptive error identifying the failing constraint:

| Error | Fix |
|---|---|
| `allowed-tools contains vault_* names` | Replace with Claude Code tools: `Read, Edit, Write, Bash, Grep, Glob` |
| `missing managed_by: myco` | Add `managed_by: myco` to frontmatter |
| `missing user-invocable` | Add `user-invocable: true` to frontmatter |
| `missing name with myco: prefix` | Ensure `name: myco:<skill-name>` in frontmatter |
| `name contains path traversal` | Remove `/`, `\`, or `..` from the name parameter |
| `exceeds 500 lines` | Trim content or split into sub-skills |
| `Candidate ... is already fulfilled by skill "..."` | The `candidate_id` is already linked to a different skill. Write to that skill's name to evolve it, or omit `candidate_id`. |
| `Description overlaps with existing active skill "..." (Jaccard X.XX, threshold 0.4)` | Proposed description is too similar to an existing skill. Reframe to cover a distinct procedure, or write to the existing skill's name to evolve it. |

### allowed-tools Contamination

The vault_write_skill gate was added specifically because of a silent propagation bug: when skill evolution tasks preserve existing frontmatter fields, they faithfully copy vault_* names from a contaminated skill into every subsequent evolution. The preservation rule is not a validator.

**Contamination propagation path:**
1. A skill has vault_* names in `allowed-tools` (e.g., generated when the spec was wrong)
2. skill-evolve is run; the LLM preserves all frontmatter fields as instructed
3. The evolved version carries the bad values forward
4. vault_write_skill now rejects at write time — the error surfaces the bug

**How to fix a contaminated skill:** Read the current `allowed-tools` in the file, replace any vault_* names with `Read, Edit, Write, Bash, Grep, Glob`, and rewrite via vault_write_skill.

## Structural Enforcement vs Prompt Rules

**Security hardening pattern:** The pipeline now uses structural gates instead of advisory prompt rules. Three coordinated bug fixes closed gaps between prompt suggestions and actual enforcement:

1. **Agent self-promotion blocked:** Agents cannot call `vault_finalize_skill` directly
2. **Quality gates enforced at write-time:** Invalid frontmatter is rejected, not just warned about
3. **Audit trail required:** `approved_at` timestamps track human approval events

This follows the principle: **Enforce constraints in tools, not prompts.** Prompts are suggestions; tools are gates.

## Debugging Why a Skill Wasn't Triggered

Skills are loaded by Claude Code when the frontmatter `description` matches the current session context. Diagnosis checklist:

1. **File present?** Check `.agents/skills/<name>/SKILL.md` exists on disk
2. **`user-invocable: true`?** Open the file and verify this field is present and true
3. **Description broad enough?** The description is the only matching signal. Too narrow = fewer matches. Compare it to the actual task context.
4. **Description degraded?** Check if the skill was evolved in the last run — the rewrite may have shortened the description (see Over-Evolution section below). Compare with the previous generation.
5. **allowed-tools correct?** Confirm `allowed-tools` lists Claude Code tools only
6. **Still in staging?** Check if the skill is stuck in `.myco/staging/` awaiting promotion
7. **Symlinks present?** For hand-authored skills, verify `.claude/skills/` and `.cursor/skills/` symlinks exist

## Diagnosing skill-evolve Over-Evolution

**Symptom:** A skill was classified STALE and rewritten, but the result is worse — shorter description, missing sections, generic phrasing — with no new factual content added.

**Root cause:** skill-evolve classified STALE on cosmetic phrasing differences rather than a substantive factual change. Without an explicit bias-toward-CURRENT directive, LLM rewrites interpret any new context as justification to refactor. This creates a regression loop:
- Descriptions get shorter → triggering coverage silently degrades
- Detailed sections get consolidated → diagnostic value lost (e.g., machine_id regression steps, budget sizing math)
- Phrasing becomes generic → precision lost

The rewritten skill passes all validation checks but is structurally degraded.

**Fix steps:**
1. Check skill evolution task configuration — it must have an explicit "bias toward CURRENT unless there is a substantive factual change" instruction and a "do NOT restructure sections that are still correct" directive
2. Identify the previous generation via vault_skill_records lineage
3. Compare the description — if shortened, triggering coverage is degraded
4. Rewrite to restore description coverage plus any actual new knowledge

**The standard for STALE:** A new behavior, a fixed bug, a changed API, or a discovered gotcha that the current skill gets factually wrong. Cosmetic phrasing differences are not sufficient.

## skill-evolve Watermark Behavior

**Pre-filtering and no-op semantics:** The skill-evolve system uses watermark timestamps to optimize runs and prevent redundant processing:

- **Run-level deduplication:** Skills already assessed in the current run (matching `skill_evolve_last_run` timestamp) are automatically excluded from assessment to prevent duplicate analysis within a single execution
- **Knowledge watermark filtering:** Only skills with new knowledge since their `last_assessed_at` timestamp are eligible for evolution, creating an efficient change-detection mechanism  
- **No-op run detection:** When no skills qualify for evolution after pre-filtering (either due to recent assessment or lack of new knowledge), the entire run becomes a no-op — the agent reports completion without making any changes
- **Watermark rotation:** The `last_assessed_at` watermark is updated even when a skill is classified as CURRENT, ensuring proper rotation coverage in subsequent runs and preventing the same skill from being unnecessarily re-assessed

**Practical implications:** This watermark system explains why skill-evolve runs often complete quickly with "no changes needed" — either all candidate skills have already been assessed, or new vault knowledge doesn't warrant updates. The system is designed to be efficient and avoid redundant work, making frequent skill-evolve runs safe and cost-effective.

## Budget Sizing for skill-evolve Runs

skill-evolve runs are multiplicative in agent turn cost. Each STALE skill rewrite costs ~8–10 turns (read + knowledge searches + write). Size the budget for worst-case STALE count:

```
Assess phase: ~1.5 turns/skill × (number of active skills)
Evolve phase: ~10 turns/rewrite × (number of STALE skills)
Task maxTurns: sum of phase budgets + ~5 turns overhead
```

**Recommended configuration for up to 3 STALE skills:**
Task-level configuration pattern follows the standard phased executor structure with maxTurns and timeoutSeconds at the task level, and per-phase budget allocation within individual phase configurations.

```
Task level: maxTurns: 60, timeoutSeconds: 1800
Assess phase: maxTurns: 20
Evolve phase: maxTurns: 35
```

**Silent failure mode:** If `maxTurns` is too low, the run ends "normally" but stops mid-rewrite with no error message. Always verify that the expected STALE skills were actually updated — check their generation number and `updated_at` after the run.