Adversarial review of Phase 4-lite found two real gaps, both rooted in the
apply engine resolving script `id → name` from `current.scripts` (app-own)
only — so a route/trigger bound to an inherited GROUP script (whose id is not
app-own) couldn't be named:
* **Prune gap (reachable via pure declarative apply):** a trigger bound to an
inherited group script, once dropped from the manifest, never diffed to a
Delete (the diff couldn't resolve its identity once the bundle stopped
referencing the name), so `apply --prune` silently orphaned it.
* **Bound-plan false-negative:** `state_token` excluded such a trigger from
its fingerprint, so the StateMoved check missed a concurrent edit to that
binding class. (Routes were already safe — they hash the raw `script_id`.)
Fix: `resolve_current_target_names` resolves the names of group scripts the
app's CURRENT routes/triggers are bound to (by id, independent of the bundle),
and that map now feeds `compute_diff_with_names`, `state_token_with_names`, and
the prune trigger-identity map. App-owned bindings are unaffected (their names
are already in `current.scripts`). Also fixes a stale "in this app" conflict
message for group-owned scripts.
New journey `inherited_bound_trigger_is_pruned_when_dropped` proves prune now
removes an inherited-bound cron trigger. Full journey suite 105/105.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>