← voidwest    ember    road to ember 1.0

v0.2: capturing, patching, and restoring hidden states

draft · part 2 of the road to Ember 1.0 series · not yet published
mohammed al-thobaiti · 2026-08-04
Ember interventions hidden states causal experiments provenance Qwen
draft status

complete draft with explicit citations to repository artifacts. the capture → compare → patch → restore transcript below was produced live on 2026-08-04 by running the committed v0.2 workflow (scripts/research_example_capture_patch.sh) and is recorded in artifacts/benchmark-v02/part2-capture-patch.md. the figure is embedded as SVG (dark/light theme variants under figures/).

a probe can tell you that a direction is decodable. it cannot tell you whether the model uses it. v0.2 built the instruments that can.

the problem: observation is not causation

a linear probe over cached hidden states shows that some direction in layer l carries information about a word's morphological root. it does not show that the model uses that direction to produce its output. the gap is the difference between decodability and causal use, and it is exactly the gap the research question cares about: representational availability without behavioral consequence.

v0.2's answer, stated as its constraint: intervention is scientifically meaningful only when the tensor identity, layer, token position, and execution route are explicit. a patch that cannot say precisely what it replaced proves nothing; a restoration that is not bit-exact proves less.

capture: selective, provenance-carrying observation

--capture-activations records live tensors only for explicitly selected records , at one of six semantic hook stages (before-layer, after-attention, after-mlp, after-layer, before-logits, after-logits), filtered by layer, phase, and decode position, with an optional record cap (CHANGELOG.md, v0.2). each record carries its origin: the stage, layer, phase, start position, the tensor hash, the model/tokenizer/GGUF provenance, a prompt hash (with optional prompt omission), input and generated token ids, and the exact capture-config hash. the artifact schema is versioned (0.2.0-experimental) and explicitly carries no compatibility guarantee.

the capture config is deliberately small, a TOML with an output dir, layers, stages, and phase. the v0.2 workflow generates three of them, one per run (the workflow script embeds the generator; scripts/research_example_capture_patch.sh).

patch: one source, exactly resolved

--activation-patch replaces a live activation in place from a captured artifact. the source resolution is unambiguous by construction: a target resolves to exactly one source record (position-qualified or unique match), anything else is a hard error; family, layer, width, dtype, and byte order are validated; a target that is never applied is a failure, not a silent skip; and the hook allocates nothing after initialization (CHANGELOG.md, v0.2).

the compact example, run live

the committed v0.2 workflow on Qwen3-0.6B Q8_0 (layer 4, stage after-mlp, 4 generated tokens, temperature 0), reproduced on 2026-08-04 (artifacts/benchmark-v02/part2-capture-patch.md):

  1. run a, baseline, with capture.
  2. run b, --zero-layer-output 4:mlp, same capture. the layer-4 MLP output is zeroed; the intervention is applied before the residual add, so the rest of the network sees a different residual stream.
  3. compare a vs b, status=differs, 0 of 8 records identical. the output changed: token ids 12095 13 576 6722279 6722 3283 315.
  4. run c, --activation-patch: a's layer-4 after-mlp activation patched back in at prefill and every decode position (4 patch applications across 4 targets).
  5. compare a vs c, status=tensor-identical, 8 of 8 records bit-identical; generated ids back to 12095 13 576 6722; model, tokenizer, prompt, and input hashes all match. the only differences are recorded provenance (the experiment's name and arguments, the capture config hash, argv, timestamp) , and created_at_unix plus the capture output dir are the fields compare-artifacts is specified to ignore.

that is the frozen restoration criterion: the patched run's captured logits must be bit-identical to the baseline's, sha256-equal at the tensor level, with generated-text equality explicitly rejected as insufficient evidence (the script's own comment says so).

The six-step intervention cycle: baseline capture, altered run, patch one layer, downstream output changes, restore the original activation, output returns to baseline The six-step intervention cycle (light theme)
figure 1, the six-step intervention cycle, live on Qwen3-0.6B Q8_0 (2026-08-04): a baseline → b zeroed layer-4 MLP output (0/8 records identical) → patch → downstream changes → restore → a vs c tensor-identical 8/8 with generated ids equal (artifacts/benchmark-v02/part2-capture-patch.md).

the honest finding: the harness drifted, the criterion held

running the committed script on the current binary produced a surprise worth reporting rather than hiding: the script exits with a failure even though the criterion passes. the script asserts that the a-vs-c comparison status is the literal string "identical"; the current compare-artifacts reports "tensor-identical" when every aligned record is bit-identical but recorded provenance differs. the status vocabulary evolved after v0.2 (the v0.5 comparison classes are exact-semantic, exact, output-equivalent, top1-equivalent, failed), and the v0.2-era script was never updated.

the substantive check is unambiguous: 8/8 records identical, generated token ids equal, all substantive run fields equal (artifacts/benchmark-v02/part2-capture-patch.md section 3). this is a harness-drift finding, the criterion held; the assertion string did not , and it is exactly the kind of thing a series about trust should surface rather than smooth over.

why this is more than probe accuracy

the same run can be read two ways. probe view: a direction at layer 4 is decodable. causal view: zeroing the layer-4 MLP output changes the output, and restoring the exact activation restores the exact output, tensor-for-tensor, down to the recorded logits. the second claim is strictly stronger, and it is the one the v0.2 artifact schema is built to support: the comparison aligns records on (phase, layer, stage, start position), refuses duplicates, and reports per-record bit-exact equality, max/mean/RMS diff, cosine, L2 norms, and relative L2 error (CHANGELOG.md, v0.2).

what still does not work

what this unlocked

the capture → compare → patch → restore cycle is the toolchain that later localized quantization-boundary failures causally, the story of part 6. and the demand for provenance at this granularity is what v0.5 turned into a verifiable artifact format.