Codex stop-hook #4: the prior post-insert check (e797584) verified that the inserted nodeId is findable anywhere in the tree, but did not verify it landed under the REQUESTED parent. Silent wrong-parent inserts are still possible if batch_design's resolveRef quote-strip produces a literal that matches a DIFFERENT node than the one ensureParentExists validated. Concrete example: doc has nodes with ids `A"B` (3 chars: A, ", B) and `A\"B` (4 chars: A, \, ", B). User passes parent_id='A"B'. ensureParentExists does a raw-string `===` match and finds the first node. insertElementTree does JSON.stringify → `"A\"B"` in DSL source. batch_design's parseInsertArgs → resolveRef → `/^"|"$/g` quote-strip → literal `A\"B` (4 chars). insertNodeInTree matches the DECOY and inserts under it. Prior post-check: node is in tree → passes. Actual: wrong parent. Fix: when args.parent_id is provided, post-check also walks findParentInTree(postChildren, insertedId) and confirms the resolved parent id === the requested parent_id. Mismatch → throw with clear diagnostic. Regression test: element-tools-contract.test.ts adds the A"B / A\"B decoy scenario and asserts the tool throws (not silent success). 88/88 pen-mcp tests pass (+1 new wrong-parent guard). format + tsc green. Bundle rebuilt. |
||
|---|---|---|
| .. | ||
| agent-native@e1f90cab96 | ||
| pen-acp | ||
| pen-ai-skills | ||
| pen-core | ||
| pen-engine | ||
| pen-figma | ||
| pen-mcp | ||
| pen-react | ||
| pen-renderer | ||
| pen-sdk | ||
| pen-types | ||
| CLAUDE.md | ||