# test698 — capability-negotiated atomic peer reply

Date: 2026-08-12 Asia/Shanghai
Base: 17b8223f9d7fd25fcc435b40e7fa1fc0823ea1de
SOURCE_COMMIT: e920ebf8d189f9a92d242addd7bf2bb7d2329fb3
Scope: Hub + agent-node protocol/runtime wiring + isolated Docker tests.
Production deployment: NOT PERFORMED.

## Exact-source image

- image: `anet-test698:e920ebf8-exact`
- image id: `sha256:fe0f4401dfdd79e3542d635d58cd08763f58998bd6edf34d8a9659cc8d3f3f6f`
- image env:
  `TEST698_SOURCE_COMMIT=e920ebf8d189f9a92d242addd7bf2bb7d2329fb3`
- same-path source/image byte comparison: 25/25 MATCH (agent-node,
  server, and test698 files changed since base). Docs are intentionally not
  copied into the image; the test673 preload is intentionally remapped into
  the test698 directory and is not counted as a same-path file.
- focused main result: 178 pass / 0 fail / 518 expect calls.
- main runner: 28/28 named mutations witnessed red; `RESULT: PASS`.
- main run artifact digest:
  `c6e8c1da3bcc781dcee0f1965295237ac7c1b6e11de0330fcb14ef7700d63906`.
  This records one timestamped run and is not claimed reproducible or used
  as source provenance.

## Runner safety and reproducibility

- `run-legacy-wire.sh` sources `tests/lib/safe-rm.sh`; its cleanup uses
  `safe_rm_rf "$TMP"`, never a bare recursive delete.
- A real default-allowlist check was executed, not inferred:

  ```text
  TMP=/tmp/tmp.2mN9SQme3d
  safe_rm_rf_exit=0 path_removed=yes
  ✓ [lint-no-bare-rm-rf] clean — no bare rm -rf $VAR in tests/ or agent-network/tests/
  ```

- The archived old-Hub build no longer reads its Dockerfile from the live
  worktree. The base commit supplies the old Hub context; the exact source
  commit separately supplies `Dockerfile.legacy-hub` into that temporary
  context. This is required because the base predates the test698 directory.
- The first attempted reproduction assumed the Dockerfile existed in the
  base archive. It printed `fatal: not a tree object` and
  `tar: Exiting with failure status` to stderr, but the outer pipeline still
  exited `0` because `| tee` ran without `pipefail`. The failure was therefore
  indistinguishable from success to automated exit-code evaluation, which is
  why that run was initially recorded as PASS. Reproducing the same failure
  gave exit `0` without outer `pipefail` and exit `2` with
  `set -o pipefail`. Noise on stderr is not failure detection; the pipeline
  exit status is the contract. That invalid run is not counted as PASS. All
  PASS evidence below comes from the corrected exact-source runner with
  shell `pipefail` enabled at the evidence-capture boundary.

## Evidence-capture limitations and operational notes

1. The two archived-old-Hub log digests below identify timestamped runs with
   random task ids. They are not reproducible digests and are not used as
   source provenance, just like the main run artifact digest above.
2. The archived old-Hub build no longer reads its Dockerfile from the live
   worktree, but the runner is not fully independent of that worktree:
   `run-legacy-wire.sh` still sources `tests/lib/safe-rm.sh` through `$ROOT`.
3. `safe_rm_rf` permits `/tmp/`, while `mktemp -d` follows `TMPDIR`. With
   `TMPDIR=/var/tmp`, cleanup is refused and the temporary directory is left
   behind. This does not turn a failing run green or a passing run red, but it
   can leak test artifacts.
4. The archived old-Hub image tag encodes `BASE_COMMIT`, but not the separate
   `SOURCE_COMMIT` that supplies `Dockerfile.legacy-hub`. The runner rebuilds
   and retags the image each time, so no stale-image failure was observed;
   the tag alone is nevertheless an incomplete provenance label.

## Product behavior

1. `send_peer_reply` performs one synchronous SQLite transaction containing
   exact token-bound ownership validation, terminal task update, scheduled-run
   terminalization, and one `requires_response=none` inbox result. Injected
   task/run failures roll all three data surfaces back.
2. Recipient capability is current-session authority only. Every exact
   token-bound heartbeat writes 1 or 0; the query binds node, network, and
   canonical alias. Historical node snapshots cannot lend capability.
3. SSE is a doorbell, not a commit precondition. A capable but disconnected
   recipient still gets an atomically stored no-response reply; reconnect
   drains the durable inbox row.
4. Every explicit capability downgrade uses terminal `send_reply`, never
   `send_task`: archived old Hub unknown-tool, recipient rollback, unbound
   caller, non-node origin, and post-dispatch node-id rotation all preserve
   the exact original task lifecycle. No fallback creates a child task.
5. Current-Hub compatibility `send_reply` from a node token is alias-bound:
   the authenticated caller alias must be the original assignee, and the
   target must be the immutable original sender. This permits legitimate
   node-id rotation while rejecting a foreign node and a wrong target with
   zero writes.
6. Dashboard/user-origin tasks continue through terminal `send_reply`.
   Bound, unbound, and legacy NULL-target fixtures each become terminal with
   exactly one reply and zero child tasks.
7. The real `agent-node/src/cli.ts` ran against an isolated real current Hub
   with a deterministic SDK preload. It proved Dashboard and capability
   downgrade terminalization, atomic failed-status propagation, `new_reply`
   runtime delivery + ACK, and no reply-to-reply egress.
8. Ambiguous transport errors and unrelated application errors never choose
   a second route. A failed compatibility terminalization remains visible to
   the durable pending-reply queue instead of being reported as delivered.

## Archived real old-Hub wire

`run-legacy-wire.sh` archives the actual base Hub as its build context,
materializes `Dockerfile.legacy-hub` from the exact source commit into that
context, starts the result on an isolated Docker network, and calls its absent
`send_peer_reply`. The real wire
response is `result.isError` with MCP code `-32602`; the production classifier
preserves that code and selects terminal `send_reply`.

The pristine runner then starts the real source `cli.ts` twice against that
Hub. Its acceptance condition uses only committed final Hub state, never a
transient pending-queue observation:

```
LEGACY_HUB_WIRE_PASS code=-32602 node=terminal-reply user=terminal-reply
LEGACY_CLI_E2E_PASS node=terminal-reply user=terminal-reply
LEGACY_CLI_TERMINAL_PASS originals=2 terminal=2 replies=2 child_tasks=0
```

The two source tasks deliberately produce identical SDK-stub result text.
Both originals become terminal because compatibility uses `send_reply`; the
5-minute `send_task` content deduplicator is not in this path.

Two separately rebuilt mutations are deterministic final-state failures:

- `old-hub-terminal-fallback-skipped`
- `old-hub-capability-fallback-removed`

Each turns red because the pristine final-state tuple (2 terminal originals,
2 replies, 0 child tasks) cannot be reached. There is no identity-lookup race,
deleted-task timing window, legacy marker, or `send_task` child-row oracle.

Archived-old-Hub pristine log digest:
`01f3769bab33d7b38e6934d70e9d4494340376bc9e51c103399ccd9a965a13e2`.
Full archived-old-Hub runner log digest (including both mutation builds):
`d0de476019a676433f92ced86a574df082c0ffa6f04d99c8bab4fe6f2243a30e`.

## Main witnessed-red mutations (28)

- cli-reply-type-lost
- cli-terminal-reply-egress-restored
- cli-new-reply-wake-disabled
- cli-failed-status-lost
- cli-atomic-failed-status-lost
- dashboard-origin-misclassified
- dashboard-origin-checked-after-capability
- terminal-reply-replies-again
- new-reply-wake-removed
- old-hub-fallback-removed
- legacy-terminal-fallback-replaced-by-task
- legacy-mcp-code-lost
- identity-rotation-fallback-removed
- capability-provenance-bypassed
- recipient-capability-gate-removed
- recipient-disconnect-restores-legacy-fallback
- recipient-capability-alias-binding-removed
- rollback-capability-clear-removed
- legacy-terminal-fallback-silently-cleared
- reply-rename-canonicalization-removed
- node-ownership-check-removed
- compat-reply-assignee-check-removed
- compat-reply-target-check-removed
- task-terminalization-removed
- reply-requires-response
- scheduled-run-sync-removed
- capability-advertisement-removed
- legacy-agent-warning-removed

Every mutation must change bytes or the runner fails. The pristine suite runs
first and must be green. CLI mutations rerun the real-process wiring fixture;
Hub mutations rerun behavior tests against fresh per-mutation SQLite files.
The disconnected-recipient mutation specifically restores the rejected
live-SSE gate and turns red. The two compatibility ownership mutations each
turn red on committed task/inbox state, not source-string matching.

## Deployment and honest limits

- No production DB, token, node, runtime, fleet process, or endpoint was read
  or changed.
- No live rollout, production traffic/cost measurement, or long-duration SSE
  outage was performed.
- Mixed versions retain one-task lifecycle semantics: old Hub and incapable
  current recipients use terminal `send_reply`; capable current peers use the
  stricter atomic primitive.
- The new Hub strengthens node-token `send_reply` authorization. A caller with
  a legitimate alias but a rotated node id can finish its assigned task; a
  different alias cannot. Old Hubs cannot receive that server-side hardening.
- SSE emission occurs after commit. Reconnect drains missed inbox rows, but
  there is no independent periodic polling guarantee.
- The ordinary runtime reply path bounds model result text to 2,000 chars.
  The prior 9,938-character legacy-marker edge is unreachable after removal
  of the legacy `send_task` marker path and is not claimed as a tested product
  boundary.
