Applies accepted candidates with automatic backup and rollback.
When to Use
- Apply approved improvement candidates to target files (automatically creates backups, supports one-click rollback)
- Roll back previous changes (precisely restore via the rollback_pointer in the receipt)
- Use
--dry-runto preview the change effect, and only actually execute after confirming it is correct - Automatically invoked in phase 4 of the orchestrator pipeline
- When field-level merge updates to YAML frontmatter are needed (update_yaml mode)
- When new content needs to be inserted before a specified heading (insert_before mode)
- Batch-execute changes for multiple candidates in the ranking
- Verify whether changes are reversible — each execution produces a receipt, and the receipt contains the complete original content
When NOT to Use
- Score candidates → use
improvement-discriminator(the executor does not make quality judgments) - Gate validation → use
improvement-gate(the executor only executes; only the gate validates results) - Full-process orchestration → use
improvement-orchestrator(the orchestrator uniformly schedules each phase) - Evaluate skill structure → use
improvement-learner - When a candidate has not yet passed discriminator scoring, the executor should not be called directly
- Do not use the executor for batch file renaming or directory structure changes — it only handles single-file content modifications
- Do not call it without ranking.json — the input must be in the standard format produced by the discriminator
- Do not manually edit receipt.json — the receipt contains hash verification, and manual modification will cause rollback to fail
4 Action Types
| Action | Description |
|---|---|
append_markdown_section |
Append a new section to the end of the file |
replace_markdown_section |
Replace an existing section by heading match (exact heading text) |
insert_before_section |
Insert content before a matched heading |
update_yaml_frontmatter |
Merge fields into YAML frontmatter (deep merge, preserves existing keys) |
Applicable scenarios for each action:
- append — Add a completely new section (e.g., add "## Caveats") without affecting existing content
- replace — Rewrite all content of an existing section, matched precisely by heading (case-sensitive)
- insert_before — Insert content before a specified section, suitable for adding "## Design Notes" before "## CLI"
- update_yaml — Merge frontmatter fields; existing fields will be overwritten, and new fields will be added
Why Automatic Backup Matters
Tradeoff: disk space for safety — every apply creates a full copy of the original file.
The reason an automatic backup is made before every change is:
- One bad apply can corrupt the entire skill — If replace_markdown_section matches the wrong heading, it will overwrite critical content. Without a backup, it cannot be recovered.
- Backup is the foundation of rollback — In the receipt,
rollback_pointerpoints to the absolute path of the backup file and the original content hash. During rollback, the hash is verified first to ensure the backup has not been tampered with, and then it is restored. - Backup cost is extremely low — SKILL.md usually does not exceed 10KB, and backup files are stored under
.state/backups/, named by timestamp, and will not interfere with version control. - Audit requirements — The backup chain forms a complete change history, allowing the file state at any point in time to be traced.
Question: Why not use git instead of backups? Because the executor may run in an environment without a git repo (for example, skill testing in a temporary directory), and git commit granularity is too coarse — one orchestrator run may execute multiple candidates, each requiring an independent rollback point.
CLI
execute.py is the core entry point, receiving the ranking artifact and candidate ID, and outputting result.json.
rollback.py is responsible for rollback, receiving receipt.json to restore to the state before the change.
Both commands support --dry-run previewing changes without actually modifying files.
execute.py automatically creates a backup before execution, and the backup path is recorded in the backup_path field of result.json.
It is recommended to always run --dry-run first to confirm high-risk changes (replace/update_yaml).
rollback.py verifies the SHA256 hash of the backup file before restoring, to prevent the backup from being tampered with.
# Apply a single candidate (requires ranking artifact + candidate ID)
python3 scripts/execute.py --input ranking.json --candidate-id CANDIDATE_ID --output result.json
# Rollback a previous change using its receipt
python3 scripts/rollback.py --receipt receipt.json
# Dry-run: preview what rollback would do without modifying files
python3 scripts/rollback.py --receipt receipt.json --dry-run
Each action type maps to a different candidate structure. Examples:
# append_markdown_section: add a new "## Caveats" section at the end
python3 scripts/execute.py --input ranking.json --candidate-id C001 --output result.json
# candidate C001's action = "append_markdown_section", content = "## Caveats\n..."
# replace_markdown_section: overwrite the "## When to Use" section
python3 scripts/execute.py --input ranking.json --candidate-id C002 --output result.json
# candidate C002's action = "replace_markdown_section", heading = "When to Use"
# insert_before_section: insert content before "## CLI"
python3 scripts/execute.py --input ranking.json --candidate-id C003 --output result.json
# candidate C003's action = "insert_before_section", before_heading = "CLI"
# update_yaml_frontmatter: merge {version: "0.2.0"} into frontmatter
python3 scripts/execute.py --input ranking.json --candidate-id C004 --output result.json
# candidate C004's action = "update_yaml_frontmatter", fields = {version: "0.2.0"}
Always preview with --dry-run before executing irreversible changes:
# Dry-run for execute (not just rollback)
python3 scripts/execute.py \
--input ranking.json \
--candidate-id CANDIDATE_ID \
--dry-run \
--output preview.json
# preview.json shows the diff without modifying the target file
Output Artifacts
| Request | Deliverable |
|---|---|
| Execute | JSON with rollback_pointer (original content hash, backup absolute path, timestamp) |
| Rollback | Restored file + confirmation JSON with restore status and hash verification result |
| Dry-run (execute) | JSON diff preview: before/after content, action type, target heading |
| Dry-run (rollback) | JSON showing what would be restored without modifying files |
Core fields of result.json:
status: success / failure / dry_runaction: the executed action type (append/replace/insert_before/update_yaml)target_file: absolute path of the modified filebackup_path: backup file path (used for rollback)content_hash_before/content_hash_after: SHA256 hashes before and after the changerollback_pointer: contains all information needed for restoration; pass it to rollback.py for one-click recovery
Related Skills
- improvement-discriminator: Scores candidates before execution — the executor's input is the ranking sorted by the discriminator
- improvement-gate: Validates results after execution — the gate verifies the result.json produced by the executor
- improvement-orchestrator: Calls executor as stage 4 — in the full pipeline, the executor comes after the evaluator and before the gate
- improvement-generator: Produces the candidates — the generator's output becomes the executor's input after being scored by the discriminator
- improvement-evaluator: Task-based evaluation — the evaluator verifies the feasibility of candidates before the executor
- improvement-learner: 6-dim structural scoring — after the executor applies changes, the learner can re-score to verify quality improvement
- benchmark-store: Pareto front data — after executor changes, the gate uses benchmark data for regression detection
Data flow in the Pipeline: generator → discriminator → evaluator → executor → gate