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
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ futures = "0.3"
getrandom = "0.3"
graphql-composition = "=0.12.2"
graphql-orm = { path = "crates/graphql-orm", version = "0.23.0", default-features = false }
graphql-orm-ai-tool-profiles = { path = "crates/graphql-orm-ai-tool-profiles", version = "0.8.0" }
graphql-orm-ai-tool-profiles = { path = "crates/graphql-orm-ai-tool-profiles", version = "0.9.0" }
graphql-orm-backup = { path = "crates/graphql-orm-backup", version = "0.7.1", default-features = false }
graphql-orm-operation-catalog = { path = "crates/graphql-orm-operation-catalog", version = "0.3.0" }
graphql-orm-router-protocol = { path = "crates/graphql-orm-router-protocol", version = "0.2.1" }
Expand Down
17 changes: 16 additions & 1 deletion crates/graphql-orm-ai-tool-profiles/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,28 @@ title: "graphql-orm-ai-tool-profiles changelog"
kind: reference
status: active
owner: graphql-orm-ai-maintainers
last_reviewed: 2026-08-21
last_reviewed: 2026-08-22
review_by: 2027-02-11
supersedes: []
---

# Changelog

## [0.9.0] - 2026-08-22

### Added

- `AiError::StatelessNativeItemRejected` is the proof-bearing terminal error
for a completed, authoritatively metered StatelessReplay turn whose refused
provider-native item was contained and produced no admitted answer or host
tool effect. It retains the stable `AI_PROVIDER_FAILED` public code.

### Security

- The variant is not a generic rejection category. An incomplete, retained,
unmetered, content-producing, tool-producing, or uncontained provider turn
must remain `ProviderFailed` and preserve uncertainty.

## [0.8.0] - 2026-08-21

### Added
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai-tool-profiles/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-ai-tool-profiles"
version = "0.8.0"
version = "0.9.0"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Backend-neutral GraphQL AI tool profile compiler and manifest contracts"
Expand Down
20 changes: 19 additions & 1 deletion crates/graphql-orm-ai-tool-profiles/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,31 @@ title: "graphql-orm-ai-tool-profiles migration guide"
kind: reference
status: active
owner: graphql-orm-ai-maintainers
last_reviewed: 2026-08-21
last_reviewed: 2026-08-22
review_by: 2027-02-11
supersedes: []
---

# Migration Guide

## 0.8.0 to 0.9.0: proof-bearing stateless native-item refusal

Adopt `graphql-orm-ai-tool-profiles` 0.9.0 with `graphql-orm-ai` 0.86.0 from
one reviewed full monorepo revision.

`AiError` gains `StatelessNativeItemRejected`. Only the provider-call executor
may return it, after committing authoritative usage for a completed
StatelessReplay turn and proving that no assistant answer, application tool,
hosted tool, citation, cursor, or unknown provider event was admitted. The
provider adapter must separately prove the refused native item was contained.
Every incomplete or ambiguous turn remains `ProviderFailed`.

The new variant deliberately retains the stable `AI_PROVIDER_FAILED` public
code. Update deliberately exhaustive internal matches so it cannot be folded
back into provider uncertainty. There is no schema, database, data, GraphQL
SDL, manifest, capability, fingerprint, protected-content, credential, or AI
schema-module migration from this package change.

## 0.7.0 to 0.8.0: canonical federated capability-index sets

Adopt `graphql-orm-ai-tool-profiles` 0.8.0 and `graphql-orm-ai` 0.85.0 from one
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai-tool-profiles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ are separate runtime decisions and must remain default-deny.

```toml
[dependencies]
graphql-orm-ai-tool-profiles = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.8.0" }
graphql-orm-ai-tool-profiles = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.9.0" }
serde_json = "1"
```

Expand Down
25 changes: 25 additions & 0 deletions crates/graphql-orm-ai-tool-profiles/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ pub enum AiError {
/// Provider operation failed safely.
#[error("AI provider operation failed")]
ProviderFailed,
/// A stateless provider turn completed and was metered, but the adapter
/// refused one provider-native item outside the admitted model surface.
///
/// This is a proof-bearing terminal classification, not a generic parser
/// error. It may be returned only after authoritative usage was committed,
/// no assistant answer was admitted, no application or hosted tool effect
/// crossed the host boundary, and the adapter's deployment contract proves
/// the refused native item was contained. Retained-session turns and
/// incomplete streams must use [`Self::ProviderFailed`] instead.
#[error("AI provider-native item was rejected")]
StatelessNativeItemRejected,
/// Runtime has not passed startup/restore readiness checks.
#[error("AI runtime is not ready")]
RuntimeNotReady,
Expand Down Expand Up @@ -79,6 +90,7 @@ impl AiError {
Self::ReauthorizationFailed => "AI_REAUTHORIZATION_FAILED",
Self::ToolExecutionFailed => "AI_TOOL_EXECUTION_FAILED",
Self::ProviderFailed => "AI_PROVIDER_FAILED",
Self::StatelessNativeItemRejected => "AI_PROVIDER_FAILED",
Self::RuntimeNotReady => "AI_RUNTIME_NOT_READY",
Self::PersistenceFailed => "AI_PERSISTENCE_FAILED",
Self::ProviderSessionDeferred => "AI_PROVIDER_SESSION_DEFERRED",
Expand All @@ -93,3 +105,16 @@ impl ErrorExtensions for AiError {
})
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn stateless_native_item_rejection_keeps_the_provider_failure_public_code() {
assert_eq!(
AiError::StatelessNativeItemRejected.public_code(),
"AI_PROVIDER_FAILED"
);
}
}
34 changes: 33 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-21
last_reviewed: 2026-08-22
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -18,6 +18,38 @@ 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.86.0] - 2026-08-22

Persistent schema module: **0.63.0** (unchanged from 0.85.0).

### Added

- `ProviderError::StatelessNativeItemRejected` is the adapter-to-executor
terminal signal for a completed provider-native item that a stateless local
deployment proves was contained outside the admitted host tool surface.
- `AiError::StatelessNativeItemRejected`, supplied by
`graphql-orm-ai-tool-profiles` 0.9.0, carries the executor's stronger proof
into the read-only and supervised coordinators.

### Changed

- A proven stateless native-item refusal now terminates `Failed` with outcome
code `provider_native_item_rejected` and admits retry instead of becoming
`RecoveryRequired/provider_turn_uncertain`.
- The provider-call executor drains and validates authoritative completion and
usage before accepting this proof, settles actual tokens/cost, and commits
the budget reservation even though no provider result is returned.

### Security

- The certain path is limited to `StatelessReplay` with no response cursor,
answer, citation, application-tool event, hosted-tool event, or unknown
provider event. An incomplete stream, retained turn, answer delta, or any
unproven native effect remains ordinary provider uncertainty.

There is no schema, data, protected-payload, GraphQL SDL, backup or restore
migration in this release.

## [0.85.0] - 2026-08-21

Persistent schema module: **0.63.0** (unchanged from 0.84.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.85.0"
version = "0.86.0"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
30 changes: 29 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-21
last_reviewed: 2026-08-22
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -19,6 +19,34 @@ 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.85.0 to 0.86.0: metered stateless native-item refusal

Adopt `graphql-orm-ai` 0.86.0 and `graphql-orm-ai-tool-profiles` 0.9.0 from one
reviewed full monorepo revision. The AI schema module remains **0.63.0**. There
is no database, data, table, column, index, constraint, backfill, GraphQL SDL,
protected-payload, backup or restore migration.

An adapter may end a dispatched stream with
`ProviderError::StatelessNativeItemRejected` only after it has emitted an
authoritative `Usage` and `ResponseCompleted`, and only when its deployment
contract proves the refused provider-native item was contained. The executor
accepts that claim only for `ModelContinuationMode::StatelessReplay` with no
provider cursor, assistant text, citation, application-tool event,
provider-hosted-tool event, or unknown event. It settles the authoritative
usage, commits the reservation, and returns
`AiError::StatelessNativeItemRejected`. Do not use either variant for a parser
error, incomplete stream, retained session, unmetered response, or an operation
that might have escaped the provider sandbox.

The read-only and supervised coordinators close this proof as `Failed` with
outcome code `provider_native_item_rejected`. That code is explicitly admitted
by `classify_run_retry` when no assistant output exists, so the failure record
offers a new run over the same user message. All generic provider errors still
close for recovery because their effects remain uncertain. Clients that
previously rendered this exact adapter refusal as
`provider_turn_uncertain` should render the new bounded failure code and expose
their existing retry action.

## 0.84.0 to 0.85.0: executable federated bounded capability delivery

Adopt `graphql-orm-ai` 0.85.0 and `graphql-orm-ai-tool-profiles` 0.8.0 at one
Expand Down
8 changes: 7 additions & 1 deletion crates/graphql-orm-ai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ for AI, ORM, storage, backup, and tool-profile packages:

```toml
[dependencies]
graphql-orm-ai = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.85.0", default-features = false, features = ["sqlite"] }
graphql-orm-ai = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.86.0", default-features = false, features = ["sqlite"] }
```

Exactly one persistence backend is required: `sqlite` (default), `postgres`,
Expand Down Expand Up @@ -190,6 +190,12 @@ A denial at reservation is pre-transport and certain: the run fails with
`provider_budget_denied` and stays retryable. See the
[usage and budgets guide](docs/usage-and-budgets.md).

A local stateless adapter can likewise close a refused provider-native item as
`provider_native_item_rejected` only after the completed turn's authoritative
usage is committed and both adapter and executor prove there was no admitted
answer or host tool effect. That failure is retryable. Incomplete, retained, or
otherwise ambiguous provider turns remain recovery-required.

## Reasoning effort profiles

`ModelReasoningEffort` is the closed provider-neutral selection:
Expand Down
9 changes: 7 additions & 2 deletions crates/graphql-orm-ai/docs/implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ supersedes: []

# Implementation Status

`graphql-orm-ai` is at crate version `0.85.0` with AI schema module
`graphql-orm-ai` is at crate version `0.86.0` with AI schema module
`0.63.0`. It uses workspace `graphql-orm` `0.23.0`, backend-neutral
`graphql-orm-ai-tool-profiles` `0.8.0`, and external `agql-auth`
`graphql-orm-ai-tool-profiles` `0.9.0`, and external `agql-auth`
`0.15.0` at `e841ffd382082ad7419be259fe957f949b956ff7`.

Completed stateless local-provider turns can carry a proof-bearing contained
native-item refusal after authoritative usage settlement. Those runs close as
retryable `Failed/provider_native_item_rejected`; every ambiguous provider
turn retains the recovery-required boundary.

The active work order, dependencies, and exit gates are maintained in the
[AI production-readiness plan](../../../docs/plans/active/ai-production-readiness/README.md).
This page is the concise crate-local capability boundary; detailed design and
Expand Down
1 change: 1 addition & 0 deletions crates/graphql-orm-ai/src/orm_background.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4037,6 +4037,7 @@ fn classify_background_retrieval_error(
| ProviderError::BudgetDenied
| ProviderError::Unsupported
| ProviderError::Rejected
| ProviderError::StatelessNativeItemRejected
| ProviderError::NewlyBoundTurnRejected(_)
| ProviderError::Cancelled
| ProviderError::Classified(_) => {
Expand Down
Loading