write-primitive-completion
Goal
Add the two missing v7 work_item restructuring primitives so review-section can enact every restructuring verdict through a sanctioned script path.
Dependency
Foundational. review-section (S3) needs reorder + split to enact restructuring.
Implementation Sketch
Reuse the existing atomic-write machinery: _with_plan_lock + CAS (compute_plan_json_hash / expected_read_base_hash) + _post_mutation_hooks (scripts/plan_corpus/write.py:313/350; scripts/plan_corpus/plan_json_write.py:65). reorder_work_item rewrites the lexorank key via lexorank.key_between(prev,next) (id + section_id unchanged) AND then RE-SORTS work_items[] by key so the stored array order equals sorted(key) per INV-15 (validate_array_sorted_and_unique) — the same re-sort move_work_item performs at work_item_status.py:317-319; a key write without the re-sort leaves array order diverged from key order and trips the INV-15 validator. reorder_work_item is SAME-SECTION-ONLY (section_id is never reassigned); cross-section repositioning composes move_work_item (section reassign) then reorder_work_item (key edit), and never duplicates move’s section-reassign path. split_work_item lands SAME-SECTION: it mints a second w-<hex> via work_item_id, keys it key_between(orig,next), INSERTS the new item into work_items[] with status: "not-started" and re-sorts the array so order equals sorted(key) per INV-15 (symmetric with reorder’s re-sort), emits the reserved WriteResult(action="split") (write.py:87 slot, currently unimplemented), and appends the new item’s - [w-id] line in the SAME body content file as the original (no new content file). Owned success_criteria (owner_work_item_id) stay on the ORIGINAL work_item — the new item starts criterion-less (S1 is floor-exempt context; the new item’s criteria are authored as needed downstream); criteria are never transferred or duplicated with fresh sc- ids on split. move_work_item (work_item_status.py:199) + abandon_work_item (work_item_status.py:429) already exist and are reused unchanged. TDD-first: the reorder/split pytests assert the WriteResult.action values ("reordered" (the existing WriteAction literal reused for reorder_work_item, NOT a new "reorder" member) / "split"), the sorted-key projection of work_items[] post-reorder, status.md regeneration via _post_mutation_hooks, and negative pins rejecting invalid lexorank bounds (after/before out of order or naming a non-adjacent / non-existent neighbor) plus split body-migration correctness on -k split_work_item.
Spec References
scripts/plan_corpus/work_item_status.py; scripts/plan_corpus/write.py; scripts/plan_corpus/lexorank.py; .claude/rules/v7-plan-system.md §2.3.
Work Items
- Author failing pytest in scripts/plan_corpus/tests/ for reorder_work_item (reposition within the same section only — cross-section repositioning composes move_work_item then reorder_work_item) and split_work_item (split preserves descriptions + hint_needs + body-line migration).
- Implement reorder_work_item(plan_dir, work_item_id, *, after, before) on the flock+CAS+post-mutation-hook path, rewriting ONLY the lexorank key.
- Implement split_work_item(plan_dir, work_item_id, *, new_text) minting a second w-id, emitting WriteResult(action=split), and migrating the body [w-id] line.