> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Site Coordination — ordered commands and results

Site Coordination owns the ordered instructions sent to Site Runtime. Execution
Core owns Runs and Attempts. A caller supplies an already constructed instruction
using the 1C contract. This context validates and stores it, allocates its sequence
and records the result when the Runtime caller replies.

## Internal interface

Compose `adaptors.postgres.PostgresSiteProtocolStore(database)` with a
`Database("site_coordination", url)` using its restricted runtime credentials.
It implements the provider-independent `application.protocol.SiteProtocolStore` port.

- `append(draft)` assigns a sequence and returns the saved command. The draft is
  a validated 1C command envelope without its `sequence` field.
- `pull(environment, after_sequence=0, limit=100)` reads pending commands in order.
  Pages contain the acknowledgement position, commands and continuation cursor.
  Reading a page does not acknowledge anything.
- `acknowledge(outcome)` verifies the command and execution identity, then records
  the result and advances acknowledgement together. Gaps and conflicts fail.
- `get_outcome(environment, command_id)` reads the saved result, or returns `None`
  while the command has no recorded result.
- `report_progress(report)` saves why the stream's next command waits: a code
  from the Runtime, never provider text. Only the next unacknowledged command may
  report, each report has its own ID, and repeating one is a replay.
- `progress(environment, command_id)` reads that reason for a pending command,
  `site-queue-busy` for a later command while the next one waits, or `None`.
- `upload_run_logs(token, command_id, upload)` (#1056) takes the logs that one of the Runtime's own read
  commands (`queued-batch.read-logs`, `reconciled-service.read-logs`) asked for, through
  `POST /v1/site/commands/run-logs/{commandId}`, up to 5 MiB with a limit of its own. It reads the command
  and its result through the store, takes the permit from the command's `readPermitId` and hands the bytes to the
  `RunLogUploads` owner (Execution Core's copy of the permit), which this context never imports. The text never
  travels in a command's result, and nothing here keeps it.
- `upload_final_run_logs(token, run_id, attempt_id, upload)` (#1056) takes the final logs of a failed service, which
  the Runtime read before it removed the service, through `POST /v1/site/commands/run-logs/final/{runId}/{attemptId}`
  with the same headers and limit. No command asks for them; the `FinalRunLogUploads` owner checks that the Attempt is
  a started service of the Runtime's environment that has not ended, and keeps the first copy.

Kubernetes and Slurm each have one configured stream. The stream aggregate lives
in `pharos.aggregates` with kind `site_stream`. Commands and results are immutable
children in `pharos.site_commands` and `pharos.site_command_outcomes`. All belong
to the private `pharos_site_coordination` database. The common transaction writer
records versions and receipts. Progress reports live in their own aggregate, kind
`site_progress`, one per environment, so they never change the stream or its
evidence; a report whose command has since been acknowledged is no longer read.
Older code refuses nothing in the stream, and a rollback only loses the reports. Database guards require child writes to accompany
their root mutation and prevent changing stored command/result evidence.

A repeated identical command keeps its ID and sequence. A repeated identical
result returns the saved outcome. Reusing an identity with different data fails.
Corrupt stored envelopes, cursor state or receipts fail restoration.

Batch observations may carry a fixed `failureCode` for permanent member consent
loss, only with failed state and confirmed cleanup. Deploy the updated receiving
Site API and Execution Core before the Runtime that emits this field; older strict
receivers reject it. Existing stored outcomes without the field remain valid.

Batch and service observations of an unfinished workload may carry a `waiting`
code for why it has not run yet (#1053). Deploy the receiving Site API and
Execution Core before a Runtime that sends it, for the same reason.

The generated transport schemas remain outside the application/domain layers.
This context emits no browser updates. The authenticated Runtime API, supervisor
invocation and native execution follow in later tasks.

<a href="/source/services/metallo/docs/epics/instantiate-and-run/ordered-commands.md.txt">Design and verification</a>.

<details class="page-source"><summary>Page source</summary>

<a href="/source/services/metallo/contexts/site_coordination/README.md.txt">Source snapshot</a> · Revision `f928834c8`.

</details>
