|
| 1 | +--- |
| 2 | +name: synthesize-skill |
| 3 | +description: Convert a saved trajectory into a reusable Claude Code skill (SKILL.md + supporting scripts) that future agents can invoke to skip rediscovered work. Use when a session captured a non-trivial workflow worth promoting from a free-text guideline to an executable skill. |
| 4 | +context: fork |
| 5 | +--- |
| 6 | + |
| 7 | +# Skill Synthesizer |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +This skill reads a saved trajectory and produces a **reusable Claude Code skill** — a `SKILL.md` plus any supporting scripts — that captures the *successful* workflow the session discovered. The output goes to `.evolve/skills/<skill-name>/` (canonical, evolve-managed) and `.claude/skills/<skill-name>/` (so Claude Code's skills loader picks it up). Future sessions on the same project can then invoke the skill directly instead of re-deriving the workflow. |
| 12 | + |
| 13 | +This is the **executable** counterpart to the `learn` skill's free-text guidelines: `learn` writes Markdown the next agent has to *read and decide what to do*; `synthesize-skill` writes a skill the next agent can simply *call*. |
| 14 | + |
| 15 | +## When To Use |
| 16 | + |
| 17 | +Use this skill when a trajectory captured: |
| 18 | + |
| 19 | +- A **non-trivial workflow** that succeeded after trial-and-error (the eventual happy path is worth promoting from free-text advice to an invocable artifact). |
| 20 | +- A **reusable script or command sequence** the model wrote during the session — particularly one the agent had to reconstruct over multiple attempts. |
| 21 | +- An environment-specific workaround (a missing system tool, a permissions wrinkle, a fallback pipeline) that future sessions in the same project will hit. |
| 22 | + |
| 23 | +Skip this skill — and let `learn` cover the case with a guideline alone — when: |
| 24 | + |
| 25 | +- The successful path was a single trivial command. |
| 26 | +- The workflow embeds secrets, tokens, or one-off user inputs that can't be safely generalized. |
| 27 | +- A skill with the same trigger already exists in `.evolve/skills/` (use `learn`'s guideline path to refine the existing skill instead of creating a duplicate). |
| 28 | + |
| 29 | +## Workflow |
| 30 | + |
| 31 | +### Step 0: Locate the Trajectory |
| 32 | + |
| 33 | +This skill runs in a forked context. **You cannot see the parent conversation directly** — read the trajectory the parent passed in via `args` or via the `Run /evolve-lite:synthesize-skill on <path>` instruction. |
| 34 | + |
| 35 | +The trajectory path is either: |
| 36 | + |
| 37 | +- supplied directly as `args` to the skill invocation, or |
| 38 | +- stated in the parent's invocation message as `The saved trajectory path is: <path>` — take everything after the colon, strip surrounding whitespace and quotes. |
| 39 | + |
| 40 | +If neither is present, scan `.evolve/trajectories/` for the most recently modified `claude-transcript_<session-id>.jsonl` and use that. If `.evolve/trajectories/` does not exist or is empty, output zero artifacts and exit — do not invent a trajectory. |
| 41 | + |
| 42 | +**Read the trajectory with the `Read` tool — do NOT shell out.** The transcript is JSONL: one JSON object per line. Filter for `"type": "assistant"` and `"type": "human"` records and reconstruct the flow from `message.content`. |
| 43 | + |
| 44 | +### Step 1: Identify the Successful Workflow |
| 45 | + |
| 46 | +Walk the trajectory and locate the **final, working** tool sequence — the one that actually produced the answer. Distinguish it from the trial-and-error leading up to it. |
| 47 | + |
| 48 | +Capture: |
| 49 | + |
| 50 | +- **What the user asked** (the original prompt). |
| 51 | +- **What ultimately worked** — the exact tool calls, scripts, or command sequences that produced the answer. Quote them verbatim from the trajectory. |
| 52 | +- **What didn't work** — the dead-ends. You will use these to write a `Triggers` section so the future agent knows when to reach for this skill *instead of* the failing approaches. |
| 53 | +- **Environment assumptions** — what was missing or had to be installed (e.g. "no exiftool, pip install Pillow needed"). |
| 54 | + |
| 55 | +If no clearly successful workflow is in the trajectory (the session ended without reaching an answer, or the answer came from a single trivial call), output zero artifacts and exit. |
| 56 | + |
| 57 | +### Step 2: Decide a Skill Name and Trigger |
| 58 | + |
| 59 | +The skill **name** must be: |
| 60 | + |
| 61 | +- kebab-case, action-oriented (`extract-exif-metadata`, `parse-cloudwatch-logs`, `restart-stuck-deploy`) |
| 62 | +- specific enough that a future agent reading just the name can guess what it does |
| 63 | +- not a duplicate of any existing entry under `.evolve/skills/` |
| 64 | + |
| 65 | +The skill **description** (one line, in the SKILL.md frontmatter) should describe the *task* the skill solves, not the trajectory it came from. Bad: "Solves the focal-length question from session abc123." Good: "Extract EXIF metadata (focal length, GPS, lens, timestamps) from JPEG/HEIC images using Pillow when system EXIF tools are unavailable." |
| 66 | + |
| 67 | +The **trigger** (in the SKILL.md body, under `## When To Use`) should describe the broad task context, not the narrow original request — same rule as the `learn` skill's guidelines. |
| 68 | + |
| 69 | +Before continuing, list `.evolve/skills/` (use the `Glob` tool, not `find` / `ls`) and confirm your chosen name does not collide with an existing skill. |
| 70 | + |
| 71 | +### Step 3: Draft the SKILL.md |
| 72 | + |
| 73 | +Author a SKILL.md with this exact frontmatter shape — the validator in Step 5 will reject it otherwise: |
| 74 | + |
| 75 | +``` |
| 76 | +--- |
| 77 | +name: <kebab-case-name> |
| 78 | +description: <one-line task description> |
| 79 | +--- |
| 80 | +
|
| 81 | +# <Title Case Name> |
| 82 | +
|
| 83 | +## Overview |
| 84 | +<1–2 sentences: what the skill does and when to use it> |
| 85 | +
|
| 86 | +## When To Use |
| 87 | +- <trigger 1> |
| 88 | +- <trigger 2> |
| 89 | +
|
| 90 | +## Workflow |
| 91 | +<step-by-step instructions for the agent> |
| 92 | +``` |
| 93 | + |
| 94 | +Notes: |
| 95 | + |
| 96 | +- `context: fork` is **omitted** for synthesized skills. They run in the parent context so they can write files into the workspace and report back. |
| 97 | +- Do NOT inline the full successful script into the SKILL.md if it's more than ~10 lines — put it in a sibling `scripts/` file (Step 4) and reference it from the SKILL.md. |
| 98 | +- The Workflow section should describe what to do *to solve the task*, not retell the original session. A future agent reading this should be able to act without ever seeing the trajectory. |
| 99 | + |
| 100 | +### Step 4: Emit Supporting Scripts |
| 101 | + |
| 102 | +If the successful workflow used a non-trivial script (more than a one-liner), write it as a sibling file under `scripts/` of your draft skill directory. Use the **already-validated code from the trajectory** — do not invent variations. Strip incidental one-off inputs (literal file names, IDs, hard-coded outputs) and replace with arguments or stdin where appropriate. |
| 103 | + |
| 104 | +Common shape: |
| 105 | + |
| 106 | +``` |
| 107 | +.evolve/skills/<name>/ |
| 108 | +├── SKILL.md |
| 109 | +└── scripts/ |
| 110 | + └── <action>.py # callable as `python3 scripts/<action>.py <args>` |
| 111 | +``` |
| 112 | + |
| 113 | +If the workflow was a sequence of shell commands rather than a script, encode it as an executable shell script (`scripts/<action>.sh`) so future agents can invoke it as a single unit instead of replaying each command. |
| 114 | + |
| 115 | +If no non-trivial script is needed (the workflow is a sequence of standard tool calls), skip this step — the SKILL.md alone is the skill. |
| 116 | + |
| 117 | +### Step 5: Finalize |
| 118 | + |
| 119 | +Place your draft files (SKILL.md and any scripts) under a temporary directory inside the workspace, e.g. `/tmp/synthesized-<name>/`, then call: |
| 120 | + |
| 121 | +```bash |
| 122 | +python3 ${CLAUDE_PLUGIN_ROOT}/skills/evolve-lite/synthesize-skill/scripts/synthesize.py finalize \ |
| 123 | + --src /tmp/synthesized-<name>/ \ |
| 124 | + --name <kebab-case-name> \ |
| 125 | + --trajectory <saved_trajectory_path> |
| 126 | +``` |
| 127 | + |
| 128 | +The script will: |
| 129 | + |
| 130 | +- Validate the SKILL.md frontmatter (`name` and `description` required; `name` must match `--name`). |
| 131 | +- Reject the skill if a same-named skill already exists in `.evolve/skills/` (overwriting requires `--force`). |
| 132 | +- Copy the directory into both `.evolve/skills/<name>/` (canonical) and `.claude/skills/<name>/` (so Claude Code's skills loader sees it). |
| 133 | +- Append a `synthesize_skill` event to `.evolve/audit.log` recording the new skill, the source trajectory, and the timestamp. |
| 134 | +- Print the two destination paths. |
| 135 | + |
| 136 | +If the validator rejects the draft, fix the SKILL.md and retry — do not edit files in `.evolve/skills/` or `.claude/skills/` directly. |
| 137 | + |
| 138 | +### Step 6: Confirm |
| 139 | + |
| 140 | +After the script returns, list the destination directories with the `Glob` tool to confirm the files landed. Output a short summary: |
| 141 | + |
| 142 | +- The skill name and description. |
| 143 | +- The destination paths. |
| 144 | +- A one-line note on what future sessions should now be able to do that they couldn't before. |
| 145 | + |
| 146 | +## Best Practices |
| 147 | + |
| 148 | +1. **One skill per workflow.** If the trajectory contains two unrelated successful workflows, run synthesis twice with different names — do not pack them into one skill. |
| 149 | +2. **Cite the trajectory.** Include the `--trajectory` flag so the audit log records provenance; future maintainers can trace the skill back to the session that produced it. |
| 150 | +3. **Don't promote one-shots.** A skill is worth synthesizing only if the trigger is plausibly recurring. If the trajectory looks like a one-off, prefer the `learn` skill's guideline path instead. |
| 151 | +4. **Don't paraphrase failure.** The skill describes what *worked*. If you find yourself writing "this skill avoids the problem where exiftool isn't installed," restate it as "uses Pillow to extract EXIF; works in environments without system EXIF tools." Triggers describe *when*, not *what failed*. |
| 152 | +5. **Keep scripts minimal.** Strip incidental log lines, debug prints, and validation that wasn't actually exercised in the trajectory. If a feature wasn't validated, leave it out. |
0 commit comments