v3.10.0: a second session can no longer erase your plan in silence
Two sessions sharing one plan directory could silently destroy each other's work
Closes #217, reported by @dubes394.
Both agents read task_plan.md, both write it back, and the later write discards the earlier one's phases. Nothing noticed: injection emitted the clobbered file as an ordinary edit, plan-doctor reported PASS, and the Stop gate read the reverted status as current.
Attestation was the nearest existing mechanism and did not cover it. It is opt-in in legacy mode, it compares against a baseline a human approved once rather than against what the hooks last observed, it reports a collaborator's edit with the same [PLAN TAMPERED] wording as a hostile rewrite, and it is a read-side gate that cannot stop the stale write from landing.
The guard compares progress, not hashes. A hash comparison would flag a single agent's own edit on its very next fire, which is most fires. Checked items and completed phases only go up during normal work, so a decrease between two turn-start fires means work that was on disk is gone. Forward motion stays silent. Both markers are language-neutral, because every translated template deliberately keeps the literal English **Status:** complete token that check-complete.sh matches with grep -F.
On by default in every mode. PWF_PLAN_GUARD=0, or a plan-guard-off token in .mode, turns it off.
Every non-English install was a subset install
The five language variants shipped 8 of the 20 scripts the canonical skill ships. Attestation, the Stop gate, the ledger, phase status and plan-doctor had never reached them, and neither had the v3.2.0 Windows UTF-8 fix, so a non-ASCII session log still crashed session recovery for exactly the users most likely to have one. sync-ide-folders.py covered only the three hook dispatch targets from #212, which made the drift structural.
Closed additively: 60 files created, 0 overwritten. The UTF-8 fix is backported by insertion so translated prose survives, and check-complete, init-session and session-catchup are now pinned as translator-owned, because the sync manifest's claim that variant scripts are language-neutral is false and a future full sync would have replaced German and Arabic output with English.
The top of the README was unreadable on a phone
The before/after comparison used width="50%" cells, which GitHub honors directly, so the columns locked to a 50/50 split of a roughly 340px container instead of scrolling as one unit, crushing the block that shows the actual injection payload. The stats panel was a 48-column box-drawing block with right-flushed values, so a first-time mobile visitor saw five labels and no numbers. Both restructured with all content preserved.
Also
The pinned tesslio/skill-review-and-optimize SHA moves to the current release commit (#215, by @popey). The old pin predated the vendor's migration, so skill reviews had stopped running correctly, and the range it moves across closes a marker-spoofing hole in the commit this repo was pinned to.
Suite 411 to 417.