Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 32 additions & 1 deletion crates/graphql-orm-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Changelog"
kind: reference
status: active
owner: graphql-orm-ai-maintainers
last_reviewed: 2026-08-16
last_reviewed: 2026-08-21
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -18,6 +18,37 @@ checkpoint facts. For the current workspace baseline and active gates, use the
[implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## [0.83.0] - 2026-08-21

Persistent schema module: **0.62.0**.

### Added

- Codex app-server interrupts can now report a proven settled turn for the
reviewed `codex-cli 0.148.0` / `gpt-5.4` deployment when the exact interrupt
is acknowledged and no dynamic tool call remains unresolved. The guarantee
is explicitly version-observed and must be reverified before a Codex upgrade.
- `AiProviderRunInterruptOutcome::RequestedSettled` and
`AiRuntime::interrupt_all_provider_runs_with_settlement` carry the
provider-side proof without changing the existing interruption-count API.
- `AiProviderSessionService::settle_interrupted_turn` and
`require_cleanup_for_run` let a durable store either advance the transcript
watermark across the retained unanswered user prompt or invalidate the
binding under the exact run fence. Alternate stores deny both by default.

### Changed

- A cancelled retained Codex turn keeps its provider thread only after three
independent proofs: exact provider acknowledgement, no unresolved dynamic
call plus version-observed partial-output discard, and a transactional ORM
check that the run persisted no assistant message, tool call, or checkpoint.
Every uncertain or refused case continues through the disclosed
cleanup-required path.
- The persistent schema module advances semantically to 0.62.0 because an
existing provider-session binding may now advance its watermark and
transcript fingerprint after a settled interrupt. No table, column, index,
row rewrite, or backfill is required.

## [0.82.0] - 2026-08-20

Persistent schema module: **0.61.0**.
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-ai"
version = "0.82.0"
version = "0.83.0"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
40 changes: 39 additions & 1 deletion crates/graphql-orm-ai/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Migration Guide"
kind: reference
status: active
owner: graphql-orm-ai-maintainers
last_reviewed: 2026-08-16
last_reviewed: 2026-08-21
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -19,6 +19,44 @@ they describe. For the current workspace baseline and active delivery gates,
use [implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## 0.82.0 to 0.83.0: settled retained Codex interruption

Adopt `graphql-orm-ai` 0.83.0 at one reviewed full monorepo revision.

### Schema module

The AI schema module advances **0.61.0 to 0.62.0** as a persistent-semantic
version. There is no DDL, table, column, index, constraint, protected-payload,
row-rewrite, or backfill change. Apply and verify the module while AI workers
are stopped, then restart all workers on the same revision. The semantic bump
records that an existing provider-session binding can now advance its durable
watermark and transcript fingerprint after a settled interrupt.

### Provider adoption

`AiProviderRunInterruptOutcome` gains the non-exhaustive
`RequestedSettled` variant. Ordinary adapters should continue returning
`Requested`; only an adapter with exact acknowledged-interrupt, unresolved-tool
absence, and provider-thread discard proof may report the new variant.

`AiRuntime::interrupt_all_provider_runs` keeps its existing count result. The
new `interrupt_all_provider_runs_with_settlement` returns the aggregate proof
for coordinator implementations. A caller must still apply durable evidence;
provider acknowledgement alone never permits retaining a thread.

The Codex app-server proof is version-observed for `codex-cli 0.148.0` with
`gpt-5.4`, not guaranteed by the empty `turn/interrupt` response. Re-run the
documented interrupt probe before changing the Codex version or admitted model.
The adapter fails closed when a dynamic call remains in flight or starts after
interruption begins. The ORM implementation then transactionally rechecks the
cancelled run, exact claim, message watermark, and absence of an assistant
message, tool call, or checkpoint before retaining the binding. A failure uses
the existing disclosed cleanup-required path.

The interrupted user message remains in Codex and in the durable transcript,
with no assistant reply. That unanswered prompt is expected and is incorporated
into the provider-session transcript fingerprint before a later run resumes.

## 0.81.0 to 0.82.0: session reliability and failure disposition

Adopt `graphql-orm-ai` 0.82.0 at one reviewed full monorepo revision.
Expand Down
7 changes: 7 additions & 0 deletions crates/graphql-orm-ai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ Invalidating a retained provider thread emits `provider_session_reset` or
`provider_session_rebound` so a host can tell the user the model's context was
reset even though the durable transcript reads as continuous.

The reviewed Codex app-server adapter can retain a thread after Stop only when
the exact interrupt was acknowledged, no dynamic tool call remains unresolved,
and the ORM transaction proves that the cancelled turn persisted no assistant
message, tool call, or checkpoint. This discard guarantee is version-observed
for `codex-cli 0.148.0` with `gpt-5.4`; reverify it before upgrading Codex. Any
missing proof continues through the disclosed cleanup-and-rebind path.

See the [session reliability adoption contract](docs/session-reliability-adoption.md).

## Features and capability boundary
Expand Down
52 changes: 34 additions & 18 deletions crates/graphql-orm-ai/docs/session-reliability-adoption.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ title: "Session reliability adoption contract"
kind: reference
status: active
owner: graphql-orm-ai-maintainers
last_reviewed: 2026-08-20
last_reviewed: 2026-08-21
review_by: 2027-02-01
supersedes: []
---

# Session reliability adoption contract

This is the exact contract for the 0.82.0 session-reliability work: which
This is the exact contract for the 0.82.0–0.83.0 session-reliability work: which
public APIs are new or changed, what a client must do differently, and which
behaviours changed with no API change at all. It complements
[MIGRATION.md](../MIGRATION.md), which records the schema and source-breaking
Expand Down Expand Up @@ -176,22 +176,35 @@ a changed rule fingerprint, an incomplete dynamic turn, and an exceeded budget
are all ordinary user behaviour rather than faults.

**Interruption reports what it proved.** `AiRunInterruptSettlement` replaces
`()` from `interrupt_run`. `retains_thread()` is true only for `Settled`, which
no adapter currently reports, so it fails closed to invalidation.

Acknowledgement is not settlement. The Codex app-server `turn/interrupt`
response is an empty object, `TurnStatus` has a first-class `interrupted`
value, and a resumed thread pages prior turns back through
`thread/turns/list` — so an acknowledgement cannot distinguish a discarded
partial turn from a retained one. Treating it as settlement would let the model
carry content the durable transcript never recorded, which is the same
divergence the disclosure events above exist to expose. The variant exists so
an adapter that can prove settlement may report it without a further breaking
change.

Interrupting an in-flight turn already invalidates the retained binding through
the executor's own ambiguous-turn cleanup. That path is now *disclosed* rather
than silent, so a mid-generation stop is visible to the user.
`()` from `interrupt_run`. `retains_thread()` is true only for `Settled`, and
settlement requires three independent legs:

1. the exact provider interrupt was acknowledged;
2. the adapter proves no unresolved dynamic tool call and version-observed
discard of the partial provider output; and
3. the durable provider-session store transactionally proves that the cancelled
run persisted no assistant message, tool call, or checkpoint.

Acknowledgement alone is not settlement. The Codex app-server adapter reports
its provider-side proof only for the reviewed `codex-cli 0.148.0` / `gpt-5.4`
deployment. Direct measurement showed that an interrupted assistant stream has
`status=interrupted`, no assistant item in `thread/turns/list`, no partial text
in the rollout file, and no partial text in the resumed model context. The
empty `turn/interrupt` response does not promise that behaviour, so repeat the
probe before upgrading Codex or the admitted model.

The adapter fences interruption against dynamic-call dispatch. A call still in
flight, or one first dispatched after interruption begins, keeps the result
unsettled. A call completed before interruption is no longer unresolved, but
the independent durable leg still refuses retention once tool traffic or a
checkpoint was persisted.

When all three proofs hold, the ORM store advances the binding watermark and
transcript fingerprint across the interrupted user message and releases the
claim. Codex retains that user message with no assistant reply, which matches
the durable transcript. Any missing proof, ORM conflict, or alternate store's
default-deny implementation invalidates the binding through the same disclosed
cleanup path, so a mid-generation context reset remains visible to the user.

## Messages accepted during cleanup

Expand All @@ -217,6 +230,9 @@ reconciliation keeps owning that case.
| `AiSessionEventEnvelope` | Added `closed`; construct via `delivered`/`ended` |
| `AiSessionStreamClose` | New enum |
| `AiRunInterruptSettlement` | New enum; `interrupt_run` returns it instead of `()` |
| `AiProviderRunInterruptOutcome::RequestedSettled` | Provider-side settled-interrupt proof |
| `AiRuntime::interrupt_all_provider_runs_with_settlement` | Aggregate provider proof; existing count API unchanged |
| `AiProviderSessionService::settle_interrupted_turn`, `require_cleanup_for_run` | Default-deny durable retain/invalidate boundary |
| `AiRunFailure`, `AiRunRetryAdmission`, `AiRunRetryEvidence`, `classify_run_retry` | New |
| `AiRunDisposition`, `AiRunDispositionView`, `AiRunRetryRefusal` | New |
| `RetryAiRunInput`, `AcknowledgeAiRunFailureInput` | New GraphQL inputs |
Expand Down
Loading