edit-manifest — Claude Code skill: what it does, how to install
Adds a predict-verify loop for agent harness edits. It records expected outcomes for prompt or rule tweaks in a manifest, then validates them in subsequent sessions.
npx skills add chrono-meta/forge-harness --skill edit-manifest -a claude-codeWhat edit-manifest does
The skill instruments changes to SKILL.md, rules/*.md, and CLAUDE.md. Whenever an asset updates, it creates a record pairing the change with a falsifiable prediction and a concrete verification method. All entries append directly to tracks/_meta/edit_manifest.yaml.
During the verify phase, the skill reads unresolved entries and scores actual performance against the declared expectations. Edits that yield measurable improvements pass the validation gate; rejected candidates stay in a local buffer instead of disappearing. Predictions lacking clear verification criteria are flagged as untestable.
Automatic invocation at edit time is not yet linked to the main commit gate, so running the record step manually after updating harness files is necessary. Status handling relies on a strict grep-friendly vocabulary: pending, verified, falsified, and untestable.
What it helps with
- log testable hypotheses for agent prompt and rule changes
- evaluate harness edits against real session outcomes
- filter out ineffective tweaks using a validation gate
- maintain an append-only change history in YAML format
Example prompts for the agent
- Check the edit manifest to verify pending changes
- Show rejected edits from the buffer
- Record this edit in the manifest
How to install edit-manifest
1Skills CLI (Vercel)
npx skills add chrono-meta/forge-harness --skill edit-manifest -a claude-code2Manually: put the files in place
~/.claude/skills/edit-manifest/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/edit-manifest/
1Skills CLI (Vercel)
npx skills add chrono-meta/forge-harness --skill edit-manifest -a codex2Manually: put the files in place
.agents/skills/edit-manifest/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add chrono-meta/forge-harness --skill edit-manifest -a cursor2Manually: put the files in place
.cursor/skills/edit-manifest/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install chrono-meta/forge-harness edit-manifest2Manually: put the files in place
.github/skills/edit-manifest/SKILL.md1Skills CLI (Vercel)
npx skills add chrono-meta/forge-harness --skill edit-manifest -a gemini-cli2Platform CLI
gemini skills install https://github.com/chrono-meta/forge-harness --path plugins/fh-meta/skills/edit-manifestManually: put the files in place
.devin/skills/edit-manifest/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add chrono-meta/forge-harness --skill edit-manifest -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about edit-manifest
How to install edit-manifest in Claude Code?
Run npx skills add chrono-meta/forge-harness --skill edit-manifest -a claude-code. The skill file is placed at ~/.claude/skills/edit-manifest/SKILL.md.
What does edit-manifest do?
It tracks changes made to harness assets like rules and skills, verifies whether they produced the predicted improvement, and rejects edits that fail to help.
Where does the skill store its records?
Entries are saved to an append-only file located at tracks/_meta/edit_manifest.yaml.
Source text
SKILL.md · MIT
---
name: edit-manifest
description: Implements a predict-verify loop for harness edits. Every SKILL.md, rules/*.md, or CLAUDE.md change is paired with a predicted impact stored in a manifest. The next session verifies predictions against actual outcomes, and a validation gate accepts edits only when improvement is measurable. Runs automatically on harvest-loop Step 0-c and on explicit invocation.
user-invocable: true
allowed-tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash"]
model: sonnet
---
# edit-manifest — Predict-Verify Loop for Harness Edits
> Implements two mechanisms from frontier harness research, named as in their source papers (both terms
> are the papers' own — verified 2026-06-17 against arXiv full text):
> - **Change Manifest** (AHE, arXiv:2604.25850): each edit attaches a manifest entry declaring a
> falsifiable predicted impact (expected fixes + at-risk regressions); the next round intersects it
> with observed task-level deltas to produce a per-edit verdict. (Paper: "the Evolve Agent produces a
> change manifest…".)
> - **Validation Gate** (SkillOpt, arXiv:2605.23904): a candidate is accepted only when its
> selection-split score is strictly greater than the current selection score (ties rejected); rejected
> edits are kept in an epoch-local buffer, not silently discarded. (Paper: "validation gate" /
> "held-out gate".)
FH's regression_guard.sh catches backward regressions. edit-manifest closes the forward
loop: did the edit actually improve what it claimed to improve?
**Boundary vs. verify-bidirectional**: verify-bidirectional is *reactive* — it updates the
baseline when the user raises a counter-argument to an AI recommendation. edit-manifest is
*predictive* — it records a forward prediction at edit time and verifies it against outcomes
later, with no user counter-argument required. Different axes: one responds to challenge,
the other tests a self-declared hypothesis.
## Manifest File Location
```
tracks/_meta/edit_manifest.yaml
```
Single append-only file. Entries are never deleted — they accumulate as the harness's
edit history and negative-feedback buffer.
## Manifest Entry Format
```yaml
- id: em-{YYYY-MM-DD}-{slug}
date: YYYY-MM-DD
file: plugins/fh-meta/skills/{skill}/SKILL.md # relative to repo root
edit_summary: "added 'trigger phrase X' to natural language triggers"
predicted_impact: "users entering via phrase X will increase — estimate +1 session/week"
predicted_measurable_by: "session start logs or user utterance pattern in next 2 sessions"
validation_status: pending # pending | verified | falsified | untestable
validation_type: judged # mechanical (grep/count/git) | judged (cited observation) | untestable
baseline_value: null # number, when a metric exists (mechanical)
measured_value: null # filled at VERIFY
delta: null # measured_value - baseline_value, or null
match_score: null # at VERIFY: 1.0 confirmed | 0.5 partial | 0.0 contradicted
verified_at: null
verification_note: null # one-line MEASURED outcome + cited evidence (never bare "seems better")
gate_decision: null # accepted | redefine | rejected
```
> **Status vocabulary is canonical and machine-greppable** — `validation_status` MUST be one of
> `pending | verified | falsified | untestable`, never freeform prose. The verify pass (Step V1)
> greps these literals; a freeform status like `"predicted — verify next session"` is **invisible to
> the grep and silently never closes the loop** (the format-reconciliation bug fixed 2026-06-16 — put
> the prose in `predicted_measurable_by`, keep `validation_status: pending`).
>
> `baseline_value` / `measured_value` / `delta` apply to **mechanical** entries only; judged and
> untestable entries leave them `null`. **`match_score` is the gate input (Step V3) for all types** —
> the numeric fields are a mechanical-entry audit detail, not a second gate signal.
## Trigger Conditions
### Automatic — Record Phase (on every FH asset edit)
Whenever the **3-axis auto-gate** in CLAUDE.md fires (any SKILL.md / rules / CLAUDE.md edit),
append a manifest entry **before** committing.
> **Wiring note**: This Record step is invoked manually or via harvest-loop until the
> CLAUDE.md 3-axis auto-gate is explicitly extended to call it. The auto-gate currently
> chains regression_guard → steel-quench → phantom-quench; adding edit-manifest
> Record as a pre-step is a proposed extension, not yet wired. Do not assume automatic
> invocation — call it explicitly after an FH asset edit.
### Automatic — Verify Phase (harvest-loop Step 0-c)
At session start (via harvest-loop), read all `pending` entries and attempt verification.
### Manual
| Phrase | Action |
|---|---|
| "check edit manifest", "did our edits work?" | Full verify pass on pending entries |
| "show rejected edits", "what didn't work?" | Display rejected-edits buffer |
| "add to manifest", "record this edit" | Manual Record step |
## Execution Steps
### RECORD mode (called on each FH asset edit)
**Step R1 — Draft Entry**
Prompt the AI (or the user, for high-stakes edits) to fill:
- `edit_summary`: one line, what changed
- `predicted_impact`: what observable improvement is expected
- `predicted_measurable_by`: how and when this can be checked
**Step R2 — Append to Manifest**
```bash
# Append YAML block to tracks/_meta/edit_manifest.yaml
```
Output confirmation: `edit-manifest: entry em-{date}-{slug} recorded`
**Step R3 — Flag Untestable Predictions**
If `predicted_measurable_by` is vague ("generally better", "feels cleaner") → mark
`validation_status: untestable` immediately. These are tracked separately as a signal
that the edit rationale needs sharpening.
---
### VERIFY mode (harvest-loop Step 0-c or manual)
**Step V1 — Load Pending Entries**
```bash
# canonical pending + legacy freeform "predicted ..." entries (transition: reconcile legacy to pending)
# \b anchors the alternation so 'pending_review' / 'predicted_outcome' (non-canonical) still surface as legacy, not swept as pending
grep -nA22 -E 'validation_status: *"?(predicted|pending)\b' tracks/_meta/edit_manifest.yaml
```
Skip entries where `predicted_measurable_by` date has not yet passed. **Reconcile any legacy
freeform `validation_status: "predicted — ..."` entry to `pending` (move the prose into
`predicted_measurable_by`) as you touch it — otherwise it stays invisible to future passes.**
**Reconciliation completeness** (a half-reconciled entry stays unverifiable): when you touch a legacy
entry, also backfill the fields a canonical entry needs — generate a missing `id`
(`em-{date}-{slug}`), set `file:` from the edit's target, and set `validation_type` explicitly (default
**mechanical** when `predicted_measurable_by` names a grep/count/git check; **judged** when it names a
reviewer observation). A missing `validation_type` is not a silent default — name it, or the entry
can't be scored consistently across passes.
**Step V2 — Verify Each Entry**
First classify the entry by `validation_type`, then collect evidence accordingly:
- **mechanical** — prediction is a count/presence checkable by grep/git. Record `baseline_value` →
`measured_value` → `delta`. The check IS the evidence (non-vacuous by construction).
- **judged** — prediction needs reviewer judgment. Requires **one concrete cited observation**
(file:line / a quoted signal), never a bare "seems better". No citation → stays `pending`, not verified.
**Non-Model Ground (the citation must be tool-confirmed, not asserted)**: the cited file:line MUST be
confirmed by an actual Grep/Read **in this verify pass** and the tool output (the matched line) pasted
into `verification_note` — a citation-shaped string asserted from memory is NOT evidence. An
unverifiable / un-pasted citation caps `match_score` at **0.5** (never 1.0). This is the same anchor
discipline as phantom-quench: a verdict rests on a surfaced span, not a claim that one exists.
- **untestable** — no observable evidence source. Mark `untestable`, do not score.
For each entry, check the evidence source specified in `predicted_measurable_by`:
| Evidence Source | Check Method |
|---|---|
| Session utterance patterns | Grep `tracks/_meta/` for trigger phrases |
| Skill invocation count | Read `knowledge/shared/learnings/subagent_invocations_log.yaml` (create if absent) |
| User friction signals | Grep `tracks/_meta/fh_signal_*.md` for related friction |
| Git commit frequency | `git log --oneline --since={date} -- {file}` |
Then score `match_score`: **1.0** = evidence clearly confirms the prediction · **0.5** = partial/ambiguous
· **0.0** = contradicted or no-occurrence. Record the score + the cited evidence in `verification_note`.
> **Circularity guard**: edit-manifest is invoked *by* harvest-loop (Step 0-c). To avoid a
> circular evidence loop, edit-manifest must NOT use harvest-loop's own synthesis outputs
> (proposal lists, curator decisions) as verification evidence. Evidence sources are limited
> to primary signals — raw utterance logs, invocation counts, git history, friction signals —
> that exist independently of any harvest-loop run.
**Step V3 — Apply Validation Gate**
| `match_score` | status → Gate Decision | Next Action |
|---|---|---|
| ≥ 0.75 | `verified` → `accepted` | No action needed |
| 0.25–0.75 | `verified`(partial) → `redefine` | Sharpen the prediction/edit; note what partially held |
| ≤ 0.25 | `falsified` → `rejected` | Add to rejected-edits buffer; propose revert if regression |
| no evidence / window not matured | keep `pending` | Re-check next session |
| no evidence source | `untestable` | Flag for human judgment |
**Step V4 — Rejected-Edits Buffer Report**
After verification pass, output rejected entries as a learning signal:
```
edit-manifest: verification complete
Verified (accepted): N
Falsified (rejected): N
Still pending: N
Untestable: N
Rejected edits (negative feedback buffer):
em-2026-05-28-trigger-phrase: predicted "+1 session/week via phrase X"
→ falsified: no utterance evidence in 7 sessions
→ proposed revert: [y/N]
```
**Step V5 — Update Manifest**
Apply `verified_at`, `verification_note`, `gate_decision` to each resolved entry via Edit.
## Validation Gate Logic
Mirrors SkillOpt's validation gate (the held-out gate over its selection-split score):
```
IF verified evidence shows improvement:
gate_decision = accepted (edit stays)
ELSE IF falsified (no improvement or regression):
gate_decision = rejected
→ retained in manifest as negative feedback
→ future edit proposals for same file grep rejected entries first
→ propose revert to human
ELSE:
stay pending
```
**Rejected-Edit Reuse**: When proposing a new edit for a file, the AI must grep
`edit_manifest.yaml` for prior `rejected` entries on that file and explicitly
state why the new proposal avoids the same failure mode.
## Constraints
- **Append-only**: Never delete manifest entries. Rejected edits are the most valuable
learning signal — they prevent the same mistake twice.
- **Human gate on revert**: Gate decision `rejected` proposes revert; human confirms.
- **Simplification guard**: If no pending entries exist, output one line
"edit-manifest: no pending entries" and exit.
- **Untestable rate alarm**: If `untestable` entries exceed 30% of total, flag:
"edit rationale quality degrading — predictions are not falsifiable."
## Done When
```
RECORD mode:
Entry appended to edit_manifest.yaml
+ Untestable flag applied if vague prediction
VERIFY mode:
All pending entries checked (canonical + legacy freeform reconciled to pending)
+ Final output line, EVERY exit path including no-pending: literal `Verdict: PASS` |
`Verdict: PASS (no pending entries)` | `Verdict: CONDITIONAL_PASS` (rejected buffer non-empty —
attach the list on the same line) | `Verdict: FAIL` — nothing after it; callers gate on this
line (return-path audit + codex S2 2026-08-10)
+ validation_type classified (mechanical / judged / untestable)
+ match_score recorded with cited evidence (mechanical: delta; judged: one cited observation)
+ Gate decisions applied (accepted / redefine / rejected / pending)
+ Rejected-edits buffer reported
+ Manifest file updated via Edit
+ Human gate presented for any proposed reverts
```
**Check class** (per `harness_6axis_framework.md §Axis 5`): the verify pass itself is *measured* for
mechanical entries (delta is a number) and *judged* for judged entries — the judged path is kept
non-vacuous by the **mandatory cited observation** (no citation → stays pending, never auto-verified).
## References
- Theoretical basis: AHE (arXiv:2604.25850) §4 change manifest + prediction falsifiability
- Validation gate: SkillOpt (arXiv:2605.23904) §3.3 validation/held-out gate over the selection-split score + rejected-edit buffer
- Integrates with: `harvest-loop` Step 0-c · `verify-bidirectional` · 3-axis auto-gate (CLAUDE.md)
- Manifest file: `tracks/_meta/edit_manifest.yaml`
© chrono-meta · MIT · chrono-meta/forge-harness