brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
edit-manifestImplements 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 invocat…
Independent GitHub snapshot · Automated classification · Original documentation governs
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.
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.
- 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_statusMUST be one ofpending | 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 inpredicted_measurable_by, keepvalidation_status: pending).
baseline_value/measured_value/deltaapply to mechanical entries only; judged and untestable entries leave themnull.match_scoreis the gate input (Step V3) for all types — the numeric fields are a mechanical-entry audit detail, not a second gate signal.
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.
At session start (via harvest-loop), read all pending entries and attempt verification.
| 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 |
Step R1 — Draft Entry
Prompt the AI (or the user, for high-stakes edits) to fill:
edit_summary: one line, what changedpredicted_impact: what observable improvement is expectedpredicted_measurable_by: how and when this can be checkedStep R2 — Append to Manifest
# 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.
Step V1 — Load Pending Entries
# 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:
baseline_value →
measured_value → delta. The check IS the evidence (non-vacuous by construction).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, 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.
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.
rejected proposes revert; human confirms.untestable entries exceed 30% of total, flag:
"edit rationale quality degrading — predictions are not falsifiable."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).
harvest-loop Step 0-c · verify-bidirectional · 3-axis auto-gate (CLAUDE.md)tracks/_meta/edit_manifest.yaml