Record the completed Gate 8 recovery proof

948eb6301319 · Christopher David · · parent 6a812a22e994

Record the completed Gate 8 recovery proof

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified docs/2026-08-20-integration-hardening-and-staging-readiness-recommendations.md
  • added docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/README.md
  • added docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/baseline-receipt.json
  • added docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/migration-rehearsal.json
  • modified test/openagents_web/live/chat_live_test.exs

Diff

5 files changed, +129 -2

docs/2026-08-20-integration-hardening-and-staging-readiness-recommendations.md modified +44 -1

@@ -2,7 +2,7 @@

2 2
3 3
Date: 2026-08-20
4 4
5
Status: In progress; Gates 0–5 and 7 complete, Gate 6 application controls locally verified
5
Status: In progress; Gates 0–5 and 7–8 complete, Gate 6 application controls locally verified
6 6
7 7
## Outcome
8 8

@@ -791,6 +791,49 @@ use fixed sleeps as the correctness mechanism.

791 791
**Exit criteria:** Every asynchronous subsystem has tested interruption,
792 792
recovery, idempotency, ownership, and bounded-failure behavior.
793 793
794
### Gate 8 implementation status
795
796
Completed on 2026-08-20:
797
798
- Added the asynchronous recovery contract before the new recovery tests. The
799
  contract defines durable authority, generation fencing, permitted resume
800
  behavior, honest terminal failure, idempotency, and resource bounds for text,
801
  voice, work, and semantic derivatives.
802
- Added direct supervised-process tests for `TurnRecovery`, `VoiceRecovery`,
803
  `WorkRecovery`, and `SemanticWorker`. The tests cover a killed streaming turn,
804
  an admitted voice generation, live and orphaned work singletons, provider and
805
  drain failure, worker death, expired-lease reclamation, and stale-result
806
  fencing without fixed sleeps as the correctness mechanism.
807
- Made provider mutation retries operation-specific. OpenAI response creation
808
  and Realtime call creation now send one `POST` attempt, with direct adapter
809
  tests that fail if the request repeats.
810
- Added an accumulated assistant-message limit and a database hard ceiling for
811
  every message. Recovery now records the bounded `runtime_restarted` error
812
  code across the complete text-turn evidence chain.
813
- Added bounded semantic-provider execution, reclaimable leases, attempt
814
  fencing, and worker-level exception containment. Added composite database
815
  constraints that prevent semantic jobs or embeddings from crossing their
816
  source conversation.
817
- Bound every machine delegation to its account-owned machine, immutable
818
  admission-time authority, immutable execution request, and bounded budget.
819
  Only the generation-fenced ACP session checkpoint may change after
820
  admission. The worker reads machine, agent, working directory, and wall-clock
821
  authority from those fields.
822
- Rehearsed the Gate 8 migration forward, backward, and forward again on a
823
  populated disposable database. The rehearsal preserved the legacy job,
824
  rebuilt its machine, authority, and budget binding, admitted the session
825
  checkpoint, and refused an execution-identity rewrite.
826
- Exact implementation commit
827
  `6a812a22e9942f88b2593dc0d7b18fba13cabc53` passed the owned baseline without
828
  retries in 80 seconds: 1,295 default Elixir tests, all 9 distributed tests, 17
829
  browser tests, 83.59% merged coverage, and the packaged production release
830
  startup against a disposable PostgreSQL database. See the
831
  [Gate 8 evidence](evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/README.md).
832
833
Gate 8 is complete. Run only harmless delegated jobs against disposable
834
repositories and machines when Gates 14 and 15 execute this coverage in
835
staging. No staging or production environment was changed.
836
794 837
## Gate 9: Harden the forge build lane
795 838
796 839
Do not enable staging hot loading while the current v0 build and load protocol
docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/README.md added +28

@@ -0,0 +1,28 @@

1
# Gate 8 asynchronous-runtime evidence
2
3
Date: 2026-08-20
4
5
Implementation SHA: `6a812a22e9942f88b2593dc0d7b18fba13cabc53`
6
7
Gate 8 passed locally on the exact implementation commit. The evidence set is
8
content-free and contains no credentials, hostnames, database URLs, private
9
repository content, conversation content, or staging data.
10
11
## Evidence
12
13
- `baseline-receipt.json` is the immutable result copied from the owned
14
  exact-SHA gate receipt. Precommit, merged coverage, all nine distributed
15
  tests, browser tests, and the packaged production release startup passed
16
  without retries.
17
- `migration-rehearsal.json` records a populated forward, reverse, and second
18
  forward migration rehearsal. It verifies the legacy delegation backfill,
19
  immutable execution identity, the permitted fenced session checkpoint, and
20
  data preservation across rollback.
21
- The direct recovery tests kill or interrupt the real text-turn, semantic, and
22
  delegated-work processes. They start the recovery workers under supervision
23
  and assert the durable terminal or reclaimed state. The voice test starts the
24
  real startup recovery worker over an admitted generation.
25
26
The release startup and migration rehearsal used disposable PostgreSQL
27
databases. The migration-rehearsal database was dropped after verification. No
28
staging or production deployment occurred.
docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/baseline-receipt.json added +21

@@ -0,0 +1,21 @@

1
{
2
  "schema": "openagents.baseline-gate.v1",
3
  "git_sha": "6a812a22e9942f88b2593dc0d7b18fba13cabc53",
4
  "status": "passed",
5
  "started_at": "2026-08-20T09:09:19Z",
6
  "completed_at": "2026-08-20T09:10:39Z",
7
  "total_duration_seconds": 80,
8
  "automatic_retries": 0,
9
  "stages": {
10
    "precommit": {"status": "passed", "duration_seconds": 21},
11
    "coverage": {"status": "passed", "duration_seconds": 50},
12
    "release_smoke": {"status": "passed", "duration_seconds": 9}
13
  },
14
  "tests": {
15
    "javascript": 17,
16
    "default": 1295,
17
    "cluster": 9,
18
    "excluded_from_default": 9
19
  },
20
  "coverage_percent": 83.59
21
}
docs/evidence/gate-8/6a812a22e9942f88b2593dc0d7b18fba13cabc53/migration-rehearsal.json added +25

@@ -0,0 +1,25 @@

1
{
2
  "schema": "openagents.migration-rehearsal.v1",
3
  "git_sha": "6a812a22e9942f88b2593dc0d7b18fba13cabc53",
4
  "status": "passed",
5
  "migration": "20260820085203_harden_async_runtime_boundaries",
6
  "starting_version": 20260820082100,
7
  "fixture_counts": {
8
    "users": 1,
9
    "visitors": 1,
10
    "conversations": 1,
11
    "machines": 1,
12
    "legacy_delegation_jobs": 1
13
  },
14
  "checks": {
15
    "forward_backfill": "passed",
16
    "machine_authority_and_budget_binding": "passed",
17
    "fenced_session_checkpoint_update": "passed",
18
    "execution_identity_rewrite_refusal": "passed",
19
    "reverse_data_preservation": "passed",
20
    "second_forward_backfill": "passed"
21
  },
22
  "automatic_retries_in_successful_run": 0,
23
  "database_class": "disposable",
24
  "database_removed_after_run": true
25
}
test/openagents_web/live/chat_live_test.exs modified +11 -1

@@ -43,6 +43,13 @@ defmodule OpenAgentsWeb.ChatLiveTest do

43 43
44 44
    assert view |> element("#chat_message") |> render() =~
45 45
             ~r/<textarea[^>]*id="chat_message"[^>]*>\s*<\/textarea>/
46
47
    assert eventually(fn ->
48
             html = render(view)
49
50
             html =~ "You said: The draft must not remain after send." and
51
               not (html =~ ~s(id="cancel-turn"))
52
           end)
46 53
  end
47 54
48 55
  test "the sidebar leads with Computers immediately above Memory", %{conn: conn} do

@@ -465,7 +472,10 @@ defmodule OpenAgentsWeb.ChatLiveTest do

465 472
    |> form("#message-form", chat: %{message: "Toolbar please."})
466 473
    |> render_submit()
467 474
468
    assert eventually(fn -> render(view) =~ "Toolbar please." end)
475
    assert eventually(fn ->
476
             html = render(view)
477
             html =~ "You said: Toolbar please." and not (html =~ ~s(id="cancel-turn"))
478
           end)
469 479
470 480
    # Copy actions are icon-only, so the accessible name lives on the control.
471 481
    assert has_element?(

This page updates live while a promote is in flight · changelog