@@ -61,7 +61,7 @@ you which stack PR closes the row.**
6161| 7 | Voice edits drop pronunciation-dictionary attachments | Silent regression on Cartesia + 11labs voice edits | #4 | RESOLVED 2026-04-30 (Stack G) |
6262| 8 | Dashboard prompt edits can in-place duplicate the prompt | Two stacked prompt versions = stitched output | None | Partial — Stack D heuristic |
6363| 9 | Provider-specific voice schema mismatch (push 400) | ` voice.speed ` vs ` voice.generationConfig.speed ` | None | RESOLVED 2026-04-30 (Stack D + A) |
64- | 10 | Targeted assistant push mints duplicate tools | Re-pushing assistant duplicates ` end-call-* ` tools | #4 | Partial |
64+ | 10 | Targeted assistant push mints duplicate tools | Re-pushing assistant duplicates ` end-call-* ` tools | #4 | RESOLVED 2026-05-06 ( # 23 ) |
6565| 11 | Bidirectional SO ↔ assistant lockstep has no validation | One-sided edits silently inconsistent | None | RESOLVED 2026-04-30 (Stack D) |
6666| 12 | State file accumulates UUIDs without source files | Silent gitops drift | None | Partial |
6767| 13 | ` .agent/ ` and ` .claude/handoffs/ ` not gitignored | ` git add -A ` sweeps PII handoff scratch | None | RESOLVED 2026-04-30 (Stack A) |
@@ -533,6 +533,13 @@ cheat-sheet in `docs/learnings/voice-providers.md` (Stack A).
533533
534534## 10. Targeted assistant pushes can auto-create duplicate tool dependencies
535535
536+ ** [ RESOLVED 2026-05-06] (#23 )** — ` ensureToolExists ` /
537+ ` ensureStructuredOutputExists ` now run a name-based dedup check (state-side
538+ via ` extractBaseSlug ` + dashboard-side via lazy ` /tool ` list) between the
539+ exact-key short-circuit and the create path. Adoption re-keys state to the
540+ canonical UUID, drops stale duplicate state keys (orphan-deletion guard),
541+ and routes through ` applyTool ` for the standard PATCH + drift-check flow.
542+
536543** Discovered:** customer-fork log (Amazon3p #10 , 2026-04-29)
537544
538545### Problem
@@ -578,9 +585,15 @@ Before re-pushing an assistant with local tool dependencies, inspect
578585
579586### Status
580587
581- ** Partial.** ` ensureToolExists() ` blocks the most common path; the
582- state-renaming case remains. ** Stack C dry-run** surfaces auto-apply
583- intent before mutation.
588+ ** Resolved 2026-05-06 (#23 ).** Name-based dedup check (state-side +
589+ dashboard-side) added between the exact-key short-circuit and the create
590+ path. Adoption re-keys state to the canonical UUID, removes stale duplicate
591+ state keys (touched-marked so ` mergeScoped ` flushes the deletion), and
592+ routes through ` applyTool ` so a PATCH + drift check fires with the local
593+ payload (no fake ` lastPushedHash ` recorded). Dashboard-side dedup honors
594+ dry-run by skipping the API call. Prior partial mitigation
595+ (` ensureToolExists ` exact-key check) remains as the fast path; the new
596+ dedup is the second layer for the bootstrap-renamed case.
584597
585598---
586599
0 commit comments