# SuperAgent fetch_oss_file Prompt Experiment

## Scope

Use the first fresh controlled ARR trace together with historical successful
SuperAgent fetches to separate Agent orchestration behavior, address shape and
platform file-type policy.

## Evidence

- The controlled ARR job reached the intended SuperAgent Agent with its
  generated `PROGRAM_INPUT` and invoked `fetch_oss_file` four times.
- The trace shows that the runtime Tool accepted `object_uri` and optional
  `filename` arguments. The first OSS shorthand request returned
  `public_endpoint_missing`; later HTTPS variants for the XML returned
  `extension_not_allowed`. These are Provider results, not Tool Schema
  validation failures.
- The Agent also read the Skill and used shell inspection before fetch success,
  despite the prior concise Prompt's stop rule. The four calls were four Agent
  tool decisions inside one remote run, not four ARR submissions or transport
  retries.
- Historical exported conversations contain successful `fetch_oss_file` calls
  for `.xlsx` attachments. They returned a local file under the runtime uploads
  directory in about 2–20 seconds. Those inputs included a direct OSS HTTPS URL,
  but the exports do not expose the raw Tool Call arguments and do not prove
  that `.xml` is allowed in the ARR Agent's Provider configuration.
- No public upstream source or official documentation containing the two
  Provider error codes was found; this appears to be a platform-specific Tool.

## Historical Prompt Change (superseded)

The first corrective Main Prompt made fetch the only permitted tool action before a
local source file exists and specifies exactly one call:

```text
object_uri = "oss://" + attachment.oss.bucket + "/" + attachment.oss.object_key
filename   = attachment.name
```

It forbids parallel Skill/reference reads, filesystem/environment inspection,
URI substitution, argument repair, shell/curl/SDK fallback and every second
fetch. Any Provider failure, ambiguous result or missing unique local path must
produce one failed Profile object and end the run.

The Prompt is 1,757 characters, remains below the existing 1,800-character
regression limit, and all 12 `tests.test_arr_opera_daily_ingest` tests pass.

## Interpretation at that stage

This was a bounded diagnostic Prompt experiment. It removed retries and
side-path noise but still used the wrong `oss://` address form.

After this Prompt is published, one fresh controlled ARR job has decisive
outcomes:

1. One successful fetch returning one local XML path: continue to verify the
   Skill and MCP stages.
2. One `public_endpoint_missing`: confirm whether the Tool expects a public
   HTTPS address before assuming it needs a credential-backed Provider.
3. One `extension_not_allowed`: add `.xml`/`application/xml` to the Provider's
   allowed source types; do not keep tuning the Prompt.
4. More than one fetch or any pre-fetch shell/Skill read: the published Prompt
   was not selected or the model did not obey it; verify Profile version and
   runtime trace before any Provider change.

## Published Prompt Follow-up Run

Controlled job `arrjob-737acd9d35d04d7f9bcbbc60e7674236` reached remote run
`53510877-e30a-4f44-9a6c-26980cdc9461` with the intended PROGRAM_INPUT. The
available trace snapshot shows:

- exactly one model-selected tool action: `fetch_oss_file` with `object_uri`
  and `filename=source.xml`;
- no `read_file`, shell, Skill processor, `present_files`, or
  `arr_submit_processing_result` action before or after that fetch in the
  captured events;
- one Provider result with `success=false`,
  `error=public_endpoint_missing`, and message
  `Public OSS endpoint is not configured`;
- no HTTPS substitution and therefore no new `extension_not_allowed` result.

This validates the Prompt's single-call/no-bypass behavior for the captured
portion and makes the Agent-specific Provider endpoint the first actionable
blocker. The supplied snapshot was refreshed about 20 seconds after the Tool
result and still ended with `status=running`; it contains no `message.final` or
terminal run event, so it does not yet prove final failure-object emission or
ARR terminalization. A later trace snapshot is required for that separate
check.

## Public-read URL correction

The user subsequently confirmed two authoritative deployment facts:

- `fetch_oss_file` reads a publicly accessible OSS URL and does not need a Provider;
- the ARR OSS deployment is `public-read`.

The local implementation therefore replaces the historical `oss://` experiment:

- PROGRAM_INPUT is now `arr-opera-daily-program-input-3` with required `oss.url`;
- ARR generates `https://{bucket}.oss-{region}.aliyuncs.com/{encoded-object-key}` with no query signature;
- the 1,682-character Prompt copies `oss.url` to `object_uri` and `source.xml` to `filename` exactly once;
- only committed source XML has public-read object ACL; staged objects and processing outputs remain private;
- OSS readiness requires the approved public-read bucket.

Forty-four targeted tests and the complete 276-test suite pass with two expected skips. No fresh platform run
has exercised this contract yet. The next controlled trace should no longer return `public_endpoint_missing`.
If it returns the previously observed `extension_not_allowed`, `.xml`/`application/xml` must be enabled in the
platform Tool; more Prompt retries or URI substitutions would not solve that policy failure.

## Mixed-version local run

The next attempted local job, `arrjob-1fd0f5e182eb4056af53be7300174981`, did not exercise this correction.
Its complete available snapshot ended about seven seconds after `run.started`, still in middleware processing,
with no `object_uri`, Tool call, Tool result, Skill load, MCP submission or terminal event. The serialized input
was PROGRAM_INPUT v2 because the local 8765 process had started before the v3 files were modified. After the
validated listener was restarted, all local readiness flags returned true. Acceptance therefore moves to one
new job generated by the restarted process; the mixed-version job must not be used as v3 evidence.

## First true v3 controlled run

Job `arrjob-3c2cd75568554b0ab6d17817d446fed1` provided decisive evidence:

- middleware input contained `arr-opera-daily-program-input-3` and no v2 contract;
- the model selected exactly one `fetch_oss_file` call with a redacted URL and `filename=source.xml`;
- the Tool returned `success=false`, `error=extension_not_allowed` and no artifact;
- the Agent made no second fetch, shell/SDK bypass, Skill call or MCP submission;
- SuperAgent emitted `run.completed` with remote status `success`, meaning the orchestration run ended, not that business ingestion succeeded;
- direct submissions, deliveries, Finance versions and outbox events remained zero.

Because an extension check can precede network download, ARR separately issued an anonymous HEAD without
logging the object URL or reading its body. OSS returned HTTP 200, `Content-Type: application/xml` and
`Content-Length: 629434`, exactly matching the registered source. ARR URL generation, object ACL and public
reachability are therefore verified; the platform XML allowlist is the sole current fetch blocker.

The failure path also exposed two independent defects. The Agent returned only `job_id`, `source_file_id`, a
minimal `processor_result` and `files=[]`, which does not satisfy the Profile output object's required fields
or object-shaped `files`. ARR still reported `status=running` 145 seconds after `run.completed`, because no MCP
submission arrived and remote finalization is not yet projected into a terminal ARR failure. Neither defect
should be addressed by URI retries or renaming the XML.

## Frozen RUNNING diagnosis

A later read-only inspection distinguished a stale ARR state from an active Agent run:

- the page continued polling every four seconds and its `refreshed_at` changed, but two trace samples stayed at 73 events;
- the last persisted Agent event was `AGENT_TRACE_STREAM_ENDED` at 11:42:26 +08, three seconds after remote `run.completed`;
- a read-only remote run lookup reported `success`, while the authoritative ARR run and attempt remained `running` with no finish time;
- the trace JSONL was fully drained and no longer changing; direct submissions, artifact deliveries, Finance versions and outbox events were all zero;
- the Agent-side business result was a safe failure code, `extension_not_allowed`, not an in-progress computation.

The production upload path constructs `ProcessingRunner` but calls only `start()`. No production component invokes
`poll()` or otherwise reconciles a terminal remote run that never calls MCP. Even if polling were wired, the runner's
`delivery_missing` transition is not recognized by `PostgresProcessingState`. The available stale-expiry helper is
also not scheduled and applies to existing submission rows, whereas this run created none. Consequently this task
will remain `running` until separately authorized repair logic or a guarded one-off repair is applied. Diagnosis did
not change state, retry the stream, submit another XML or restart a service.

## Main-flow impact assessment

The stale `running` state is not currently a report-generation gate:

- every upload creates a new independent job id, and the upload control is gated by runtime readiness rather than another job's status;
- Finance facts are written only inside an accepted MCP submission transaction, not by polling or task-log state;
- current monthly and analytics readers consume committed Finance facts and do not wait for all processing jobs to become terminal;
- at this historical ARR1 snapshot, automatic post-commit monthly dispatch was still absent, so no worker was blocked by this stale job. ARR2 later implemented a separate worker under ADR-001.

Terminal reconciliation would still improve operational correctness: accurate failure state, bounded retry semantics,
idempotent failure notification and earlier revocation of an unused writeback grant. It does not make a failed XML run
produce Finance facts or a report. At that snapshot, the immediate business-flow priorities were platform XML
allowlisting, a successful MCP commit and the accepted automatic report-trigger implementation; the later run below
supersedes the allowlist diagnosis while leaving the reconciler as separate control-plane hardening.

## First successful fetch/process and rejected direct submission

Job `arrjob-ae1a40b69c46402fb80e55c980b84886` proves that the platform XML allowlist was changed successfully and moves
the failure boundary beyond OSS ingestion:

- PROGRAM_INPUT v3 caused exactly one `fetch_oss_file` call. The Tool returned `/mnt/user-data/uploads/source.xml`,
  `application/xml`, 629434 bytes and SHA-256
  `b0019ba8ecdaad878bbde463b0c3129994bf582da16d9caf56d6b96da9a2db2a`, exactly matching ARR registration.
- The Agent loaded the intended Skill and references and invoked `process_daily.py` once. Its successful result reported
  135 source rows, 16 excluded rows, 119 output rows and channel counts 26/25/54/14.
- The generated `structured-result.json` passed the Agent's own key check with 135 records, zero errors and a compact
  size of 124493 characters.
- Instead of passing that object through once, the Agent repeatedly reopened, printed, compacted and range-read the
  file. The captured sequence includes extra shell inspections, a temporary serialization, a full-file read and a
  later `start_line=1200,end_line=2500` read.
- The supplied trace snapshot was not a terminal log: it was copied at 12:41:02 +08 with `status=running`, after the
  trace connection had failed at 12:40:15 +08. A later read-only ARR trace projection shows the actual terminal state
  at 12:41:40 +08.
- Exactly one MCP submission then reached ARR, proving active Tool discovery, network reachability and grant acceptance.
  ARR recorded only 20 submitted records, rejected the request as `RESULT_CONTRACT_INVALID`, wrote no Finance version,
  terminalized the job as failed and queued one downstream failure event.

The submitted payload therefore was not the complete 135-record object produced by the deterministic Skill. This is
not an OSS, XML allowlist, Skill or MCP reachability problem, and another URI or fetch retry cannot change it. The
current contract makes the model reproduce roughly 124 KB of JSON inside one tool-call argument after receiving that
file through bounded model/tool context. Prompt wording can discourage the observed rereads, but cannot make exact
large-payload transport reliable.

The durable options are either (1) let an installed platform-side submission adapter consume a sandbox file without
serializing it through model output, or (2) make the MCP call a compact attempt-bound completion signal and let ARR use
the deterministic source replay it already performs as the canonical structured payload. A remote MCP server cannot
resolve an Agent-local `/mnt/...` path by itself, so merely replacing `payload` with `payload_path` in the current
remote schema would not work.
