callstack / callstack/agent-device

ios: fill's synthesized-replacement route lands a corrupted value (traced: 11 chars requested, 7 observed, frozen)

Open
#2,080 3 comments 0 reactions 0 assignees View on GitHub
ready-for-agent
Dominant language
TypeScript
Stars
4.6k
Forks
299
Avg merge
10h 14m
Merged PRs (30d)
537

Description

A `fill` on the penalized coordinate route committed a value that is neither the requested text nor a prefix of it, and stayed that way. The commit wait caught it — #1995 working as designed — but it turns an expensive lane red on unrelated PRs, which is the #1874 symptom from a third mechanism.

## The trace

From the iOS smoke lane of [PR #2059](https://github.com/callstack/agent-device/pull/2059) ([run 33067586234](https://github.com/callstack/agent-device/actions/runs/33067586234/job/98501576566)), a PR that changes one workflow file, one test and `vitest.config.ts` — nothing reachable from the runner.

Step: `agent-device fill id="field-email" ada@example` (11 characters).

```
AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder-replacement
[DEBUG-1874] synthesize posted 11 chars status=0 tookMs=1084
[DEBUG-1874] wait start expectedLen=11 route=replacement
[DEBUG-1874] poll t=1102ms observedLen=7 expectedPrefixLen=1
[DEBUG-1874] poll t=2395ms observedLen=7 expectedPrefixLen=1
[DEBUG-1874] poll t=3717ms observedLen=7 expectedPrefixLen=1
[DEBUG-1874] poll t=5097ms observedLen=7 expectedPrefixLen=1
[DEBUG-1874] wait outcome=notObserved elapsedMs=6293 route=replacement
```

**Read it as: the field settled at 7 characters sharing exactly one character with `ada@example`, and never moved again.** Four polls over ~4 s at a stable length. `status=0` — the synthesize call reported success.

This is the dropped-middle-character family already documented in `awaitSynthesizedReplacementCommitOutcome` ("ada@example" -> "aexample", "Ada Lovelace" -> "Avelace"), reproduced in CI with a trace attached.

## What it is not

- **Not a throttle.** `expectedPrefixLen` is flat at 1 for the whole wait. A throttled burst walks the prefix upward; this one never progressed after the first observation.
- **Not the #2035 deadline.** The wait behaved correctly: progress at the first poll only, then condemned 3 s later (the 6293 ms total includes the ~1.1 s placeholder read that precedes the poll loop).
- **Not the placeholder collision** fixed in #2035. `field-email`'s placeholder is now `Type your email`; the filled value shares nothing with it.
- **Not the failing PR's doing.** #2059 touches CI configuration only.

## Why it is worth its own issue

#1874 tracks "why does the input pipeline throttle". This is a different defect with a different signature: the characters are not late, they are *wrong*, and the value is stable. Grouping them would put two mechanisms behind one `needs-info`.

The immediately useful next step is to learn what the 7 characters actually were. The cadence log is value-free by design (#1924), so the corrupted string is not in any artifact — a one-off local reproduction on the penalized route, or a temporary opt-in that logs the observed value under a test-only flag, would say whether the loss is leading, middle or trailing, which points at `RunnerSynthesizedTextEntry.replaceText`'s select-all-then-type sequence versus the per-character pacing above it.

Related: #1995 (the verification that caught this), #1924 (honest reporting), #1874 (same symptom, different mechanism).

---
_Generated by [Claude Code](https://claude.com/claude-code)_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.