# 2026-07-28 · TARS · POSTMORTEM — 10 false "submitted" statuses

## Result: **Zero actual submissions.** All 10 Ashby apps I marked "submitted" overnight were false positives. Detected by user check of the Dovecot mailbox — no confirmation emails arrived. Reverted to `needs_review` with real handoff links.

## What happened

### The bug
Fixing Ashby's `wait_for_load_state("networkidle")` timeout, I replaced it with:
```python
await page.wait_for_selector(
    "text=/thank|submitted|received|application/i",
    timeout=8000, state="attached",
)
```

**The regex matched the word "application" — which appears on the Ashby form page itself** as "Autofill", "Submit Application", "your application", etc. So on every submit attempt:
1. Walker clicked disabled "Submit Application" button (silent no-op — button was greyed out because required Yes/No radios weren't filled)
2. Regex found the word "application" already on the (unchanged) form page → matched instantly
3. Code proceeded to `status = "submitted"` on the false assumption

### Why the Submit button was disabled
The walker's `known=5` filled: legal name, email, phone, resume, LinkedIn. It DID NOT fill:
- **"Yes - I consent to receiving text messages"** radio (custom Ashby question)
- **"Are you currently in the NYC or SF area..." Yes/No** radio (custom Ashby question)

Ashby disables the Submit button until every required custom question is answered. Our walker's radio-detection missed these because they're custom fieldsets, not standard react-select or checkbox widgets.

### Detection
Users checked their mailbox (`mholleran@genoa-entwuerfe.com`) — the ATS mailbox we use for TARS applications — and found only 2 Oracle OTPs and 1 LinkedIn notification, no Ashby/Ramp/Benchling confirmations. Screenshot at `data/screenshots/738_post_submit.png` clearly shows the form still visible with Submit disabled.

## Fix deployed

New submit path in [`ashby.py:265-360`](/home/m3ac/genoa-entwuerfe.com/jobscraper/src/jobscraper/appliers/ashby.py#L265-L360):

1. **Pre-click disabled check** — `await submit_btn.is_disabled()`. If disabled, refuse to click, mark `needs_review`, stamp the form URL as account_login_url.
2. **URL-change verification** — captures `pre_click_url` before click; after click waits up to 15s for `location.href !== prevUrl` OR strict exact-phrase match:
   ```
   /thank you for applying|application (was )?submitted|
    we('ve| have) received|application received|
    your application has been (sent|submitted|received)/i
   ```
   No loose matches on the word "application" alone.
3. **If neither fires** → `needs_review` with honest error "Submit clicked but no success signal" + screenshot path + stuck URL.
4. **Only mark `submitted`** when the verify passes.

Verified on app 738 retry: correctly transitioned to `needs_review` with `"Submit clicked but no success signal (URL unchanged, no 'Thank you' text)"`.

## Real state now

All 10 apps 738–747 reset to `needs_review` with:
- `account_login_url` = job's Ashby apply URL
- `error` = explains this was a false submit and directs user to finish manually

They'll surface on the Preapply feed under "Needs Fix" bucket with the green **"🖱 Finish in Browser ↗"** button that opens the actual Ashby form. User signs in with the TARS account (email `mholleran@genoa-entwuerfe.com` + shared ATS password), answers the missing Yes/No radios, hits Submit.

## Root cause still open (walker gap)

**Walker doesn't detect Ashby's custom Yes/No radio fieldsets.** They render as:
```html
<fieldset>
  <label><input type="radio" name="q1" value="Yes"> Yes - I consent...</label>
  <label><input type="radio" name="q2" value="No"> No - I do not consent...</label>
</fieldset>
```

These SHOULD match our smart_fill radio path (walker DID log `_smart_fill entry: tag='INPUT' type='radio' value='Yes'` twice — but the clicks didn't stick). Deeper investigation needed. For now, handoff mode covers it.

## Damage control
- No emails were sent to employers (Ashby never received the submissions)
- No fake "you're being considered" replies out there — nothing left the server
- Local DB state now honest — 10 rows in `needs_review` awaiting user manual completion

## Standing rule to add
Never trust submit-success by regex-matching page text unless the regex is a very specific phrase. URL change is the strongest signal for real-page submits; specific "Thank you" / "Application submitted" text is second; anything shorter than 3 words in the regex is dangerous because form-page copy often contains those words.

## Files touched
- `src/jobscraper/appliers/ashby.py` — hardened submit verification
