Skip to content

[#115] Fix browser attachment completion and send readiness#116

Open
HeMuling wants to merge 1 commit intosteipete:mainfrom
HeMuling:fix/115-browser-attachment-send-readiness
Open

[#115] Fix browser attachment completion and send readiness#116
HeMuling wants to merge 1 commit intosteipete:mainfrom
HeMuling:fix/115-browser-attachment-send-readiness

Conversation

@HeMuling
Copy link

@HeMuling HeMuling commented Mar 16, 2026

Ticket: #115

Fixes #115.

Summary

  • introduce a shared composer-scoped readiness reader for attachment evidence and send button state
  • make attachment upload completion depend on stable attachment evidence instead of a separate send contract
  • prevent local browser mode from swallowing attachment wait timeouts and degrading into Enter fallback
  • document and test the attachment send-race path

Root Cause Analysis

The bug was not a single timeout value problem; it was a contract split across three layers:

  1. waitForAttachmentCompletion and attemptSendButton did not use the same definition of readiness.
    • upload completion was inferred in one place
    • send readiness was decided later with a different, weaker attachment check
  2. local browser mode in src/browser/index.ts treated attachment confirmation timeout as recoverable.
    • it cleared attachmentNames
    • it continued into the send path anyway
  3. once attachmentNames were cleared, submitPrompt no longer knew it was handling an attachment submission.
    • attemptSendButton could fail
    • the code could then fall back to Enter
    • verifyPromptCommitted finally reported the visible symptom: send may have failed

The broken invariant was: attachment submissions must never enter the send path unless the same composer has stable attachment evidence and a clickable send button.

Repair Strategy

This PR fixes the problem at the source instead of adding another retry or guard at the error site:

  1. introduce a shared composer-scoped readiness reader
    • one DOM reader now gathers attachment evidence, attachment UI count, file-count hints, upload state, and the actual send-button state for the same composer
  2. split the lifecycle into two explicit gates backed by that shared state
    • waitForAttachmentCompletion now answers: "do we have stable attachment evidence?"
    • attemptSendButton now answers: "is this attachment submission actually send-ready?"
  3. remove the local browser downgrade path
    • attachment timeout is no longer swallowed in src/browser/index.ts
    • attachmentNames are no longer cleared before submit
  4. forbid attachment submissions from degrading into plain Enter fallback
    • if send readiness never materializes, the run fails explicitly with an attachment/browser automation error

This keeps state ownership crisp and restores the invariant at the earliest safe layer, instead of preserving the bad assumption and hiding it behind retries.

Failure Log That Motivated The Fix

Uploading attachment: ../../../tmp/oracle-race.aKIUsa/a.txt
Attachment queued (UI anchored, file input confirmed)
Uploading attachment: ../../../tmp/oracle-race.aKIUsa/b.txt
Attachment queued (UI anchored, file input confirmed)
Attachment wait state: {"state":"disabled","uploading":false,"filesAttached":true,"attachedNames":["remove file","remove file","remove file"],"inputNames":["b.txt"],"fileCount":0}
...
Attachment upload timed out while waiting for ChatGPT composer to become ready.
[browser] Attachment upload timed out after 80s; continuing without confirmation.
Submitted prompt via Enter key
Prompt commit check failed; latest state: {"baseline":0,"userMatched":false,"prefixMatched":false,"lastMatched":false,"hasNewTurn":false,...}
Failed to complete ChatGPT run: Prompt did not appear in conversation before timeout (send may have failed)

Verification

  • pnpm run typecheck
  • pnpm vitest run tests/browser/attachmentsCompletion.test.ts tests/browser/promptComposerExpressions.test.ts tests/browser/promptComposer.test.ts tests/browser/pageActions.test.ts
  • live browser smoke: single random attachment with --browser-attachments always

Successful Post-Fix Log

Uploading attachment: ../../../tmp/oracle-attach-min.1yYKNT/oracle-live-1773660483-12767-verify-note.txt
Attachment queued (UI anchored, file input confirmed)
Attachment wait state: {"state":"disabled","uploading":false,"filesAttached":true,"fileCount":0,"attachmentUiCount":1,"attachedNames":["remove file"],"inputNames":["oracle-live-1773660483-12767-verify-note.txt"],"attachedMatch":false,"inputMatch":true,"fileCountSatisfied":false,"attachmentUiSatisfied":true}
All attachments uploaded
Attachment send readiness: {"state":"disabled","uploading":false,"filesAttached":true,...}
Clicked send button
Verified attachments present on sent user message
Answer:
OK

Notes

  • while validating, a separate pre-existing multi-attachment false positive in uploadAttachmentFile surfaced (Attachment already present before upload)
  • this PR does not change that path; it fixes the attachment completion/send-readiness split and the Enter fallback behavior

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: browser attachment runs can fall back to Enter after upload timeout instead of failing before send

1 participant