Skip to content

[Bug]: Completion gate reopens a successful remote upload; compaction loses its receipt #814

Description

@loveRhythm1990

Agent | Codex | GPT-5 (tier unavailable)

Summary

Astra rejected task completion after an approved Bash command had successfully uploaded a file to a remote HTTP service and returned a file ID. The completion guard requested another external mutation using filesystem-observation evidence. Concurrent context compaction removed the original upload command and its success receipt from the active message history. The agent then searched for the source file and prepared to repeat the upload instead of finishing the user's request.

This is a completion-contract mismatch amplified by loss of in-flight task progress—not an authentication failure or an upload-flag mismatch. Only one successful upload was observed. A duplicate upload is a risk, not a confirmed outcome.

Suggested priority: P1, because an acknowledged remote write can be followed by renewed execution and loss of its provenance.

Background and environment

  • User request: upload a previously selected local spreadsheet to MOI.
  • Astra CLI uses a local Edge for approved Bash execution; moi-cli performs the remote HTTP upload.
  • The upload reads the source file without modifying it. The mutation occurs in the remote service, not the local filesystem.
  • Observed server build: faee95b8dcc3688d27805241d0c60e5dbd092f3f; model: deepseek-v4-flash.
  • Evidence: server logs, durable session/tool audit, and heavy step checkpoints from a real run on September 18, 2026. The two source files discussed below matched that server commit when inspected.
  • Paths, account identifiers, resource IDs, and document contents are redacted here.

Observed sequence

Times below are UTC; round numbers are zero-based.

Time / round Evidence
04:57:11 / admission workspace_mutation=MustMutate, mutation_completion_scope=External, domain=Some(Web)
05:01:41 / 10 The model supplied the local source directory as external_state_paths. The executor correctly rejected it before execution because it overlapped the bound workspace. No upload ran on this attempt.
05:01:50 / 11 Without that field, the approved upload ran successfully: tool ok=true, response {"file_id":"<redacted-file-id>"}.
Rounds 12–17 Follow-up read-only catalog checks failed to resolve a Volume or lacked required filters. These were separate MOI lifecycle/CLI limitations, not evidence that the upload had not happened.
05:03:07 / 18 The model reported upload success and explicitly qualified the follow-up verification as unconfirmed. It returned zero tool calls, but the runtime recorded finish_reason="workspace_completion_retry" instead of completing.
Same moment Default compaction freed 3,493 tokens. The subsequent heavy checkpoint contained nine messages, without the upload call or its success receipt. A later failing lookup retained the file ID, but not the original upload's provenance.
05:03:22 / 19 onward The model searched shell history and local directories, retried lookups, and attempted memory/introspection recovery. It said it was recovering the path “before re-running the upload in the foreground.”
05:05:16 / 25 The run ended after the user canceled an Ask User interaction. There were 33 completed tool executions; no second successful upload was observed.

The user saw a success report followed by renewed investigation and eventually a request for the file path again. The UI reported about eight minutes for this single upload task.

Diagnosis A: remote service effects are routed into a filesystem receipt contract

Relevant source: execution_phase.rs.

  1. requires_external_effect_completion requires external-effect evidence for MustMutate with External/Mixed scope.
  2. has_concrete_external_effect requires an executor-owned, validated receipt. A Bash command's exit status and HTTP-response stdout do not establish this receipt. The special typed external-tool path has memory-action restrictions and does not establish a receipt for this upload.
  3. enforce_workspace_completion_before_text_completion_with_disposition clears final_text, extends the turn budget, and injects external_completion_required.v1 / required_external_effect_missing.
  4. The injected instruction asks for a foreground mutation with external_state_paths so the executor can compare filesystem state before and after the operation. The caller records workspace_completion_retry.

Classifying an HTTP upload as an external mutation is reasonable. The mismatch is requiring a filesystem delta to establish that remote mutation, then asking for another mutation when the already executed upload cannot supply that evidence. The local source directory need not change at all.

The path-overlap rejection in round 10 is a valid guard and should remain. Making an unrelated local change, repeating the upload, or accepting arbitrary stdout JSON as trusted evidence would not be a correct fix.

Diagnosis B: compaction loses the completed side effect from active task context

tiered_compaction.rs keeps selected user messages and a recent tail, removes middle messages, and inserts a fixed marker:

[Context compacted: older messages were removed to reduce token pressure. The conversation continues below.]

That marker is not a progress summary. In the observed checkpoint, the surviving user request still referred to “this file,” but the exact source/upload operation and successful receipt were absent. working_memory did not preserve that progress either.

The durable audit still contained the original upload evidence; this report does not claim it was deleted from storage. The demonstrated loss was from the compacted active message history, without a usable recovery path in this run. A byte-for-byte capture of the next complete provider request was not available, so this report does not claim to reconstruct that entire request.

Reproduction outline

This is an observed incident, not yet a standalone minimal reproduction:

  1. Admit a task requiring a remote HTTP write as MustMutate / External.
  2. Execute the write through approved Bash; return a stable remote operation/resource ID without modifying local files.
  3. Let the model finish after reporting the service acknowledgement. Observe whether completion injects required_external_effect_missing and records workspace_completion_retry.
  4. Under context pressure, compact away the earlier write call/result while keeping the current user task and recent verification calls.
  5. Check whether resumed reasoning remembers the acknowledged write or instead requests/repeats it.

For a regression fixture, use a mock HTTP service with a mutation counter rather than repeatedly uploading real user data. The incidental MOI lookup failures increased history pressure in this incident; they are not proven to be necessary preconditions.

Expected behavior and fix boundaries

  • Distinguish remote-service effects from external-filesystem effects. A supported remote operation should have trustworthy evidence bound to its actual operation and target.
  • If the evidence contract cannot support the operation, report that limitation explicitly; do not use another potentially non-idempotent write to verify the first one.
  • Preserve completed side effects, source/target associations, receipts, remaining work, and relevant approval decisions across compaction—or provide authoritative retrieval before further action.
  • A follow-up read failure must not silently turn an acknowledged write into “not yet executed.” Distinguish acknowledged success, unverified follow-up state, and genuinely unknown write outcome.
  • Do not present a candidate success answer as an accepted terminal outcome and then silently reopen execution.
  • Do not weaken approvals, path-overlap checks, or receipt validation. Arbitrary stdout JSON, exit code zero, an unrelated local mutation, or an unrelated memory write must not become authoritative proof of this remote upload.

Suggested regression coverage

  • Approved remote upload with a valid operation-bound receipt and no filesystem mutation: finishes without a forced second write.
  • Successful upload, failed read-only follow-up, then compaction: retains the original receipt and target; mutation counter remains one.
  • Unsupported/unknown remote outcome: explicit bounded outcome, no blind replay of a non-idempotent operation.
  • Untrusted stdout, unrelated receipts, and workspace-overlapping external paths: remain rejected as evidence.
  • Cancellation and disabled memory remain accurately classified; neither is interpreted as proof that the upload never occurred.

Related but distinct

#812 concerns a canonical WAL durable-base mismatch that prevents a follow-up turn from executing. This incident did execute and acknowledge the upload, then failed at completion settlement and lost progress during compaction. It should not be treated as the same failure merely because both involve conversation history.

Activity

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

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions