## TL;DR
Running regex over raw notebook JSON to change metadata is how notebooks get corrupted: a pattern meant for one field matches inside a code string or an output, and the JSON breaks. Do it structurally instead: `nbformat.read()`, modify `nb.metadata` or cell metadata as objects, `nbformat.write()`. The file stays valid because you never touch the serialization. Ban regex-on-JSON in the agent's notebook tools.

```text
agent's regex corrupted notebook metadata on rewrite, json broke, rewrite failed
```

## Use this when
- A notebook rewrite by an agent produces invalid JSON or lost metadata.
- The agent's code uses `re.sub` on the raw .ipynb text.
- Metadata changes work sometimes and corrupt other times.

## Not for this skill when
- The JSON was already corrupt. Fix the corruption first.
- A human hand-edits the JSON. Validate after editing.

## Steps
1. Stop using regex on the raw file. Verify: no `re` calls remain in the notebook-rewrite path.
2. Load structurally: `nb = nbformat.read(path, as_version=4)`. Verify: it parses.
3. Modify metadata as objects: `nb.metadata[k] = v`, `cell.metadata[k] = v`. Verify: the change is visible in the object.
4. Write with `nbformat.write(nb, path)`. Verify: the file parses and validates.
5. Add a regression test with metadata-like strings inside code cells. Verify: rewrites no longer corrupt.

## Variant phrasings
### regex notebook json corruption
Short form. Structural edits only.

### agent rewrite notebook metadata broken
The symptom phrasing. Never regex the raw JSON.

### nbformat metadata edit
The fix phrasing. Objects in, objects out.

Compatibility: nbformat 5.x. Metadata is a plain dict on the notebook and cell objects.

## Why it happens
JSON is not a regular language and notebook JSON is full of adversarial content for regex: code strings containing `"metadata"`, outputs containing escaped quotes, multiline strings. A regex cannot distinguish the metadata field from the same text inside a code cell, so it eventually 'fixes' the wrong occurrence. Structural editing sidesteps the entire class of bug.

## Edge cases / pitfalls
- Even 'safe' regexes (whitespace-only) can break inside string literals. There are no safe regexes on JSON.
- Pretty-printing differences after nbformat.write are normal. Do not 'fix' them with regex.
- Kernelspec metadata edits are the most common target; do them via `nb.metadata.kernelspec`, not text search.
- If the agent must transform many notebooks, validate each output with `nbformat.validate()`.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Ou5s4knoR16QKUWQu6cKkQ
