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.

25 changes: 25 additions & 0 deletions crates/graphql-orm-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,31 @@ 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.96.2] - 2026-09-02

Persistent schema module: **0.64.0** (unchanged from 0.96.1).

### Fixed

- The fixed capability broker now makes its empty argument, relationship and
root-bound wrapper fields genuinely optional. Its execute definition tells
providers to copy only paths admitted by the loaded `planSchema`, flatten
scalar argument leaves, and omit `maximumItems` unless that exact schema
exposes a root result bound.
- A scalar or custom object result no longer fails solely because a provider
was forced to invent an inapplicable root bound or send empty placeholder
collections around an otherwise valid closed query plan.

### Security

- The authoritative schema-derived compiler, exact loaded reference,
capability fingerprint, public selection allow-list, argument validation,
resolver authorization and result budgets remain unchanged. Optional broker
transport fields grant no additional query field or argument.

There is no database, data, table, column, index, constraint, backfill,
protected-payload, GraphQL SDL, backup, or restore migration.

## [0.96.1] - 2026-09-02

Persistent schema module: **0.64.0** (unchanged from 0.96.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.96.1"
version = "0.96.2"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
17 changes: 17 additions & 0 deletions crates/graphql-orm-ai/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ 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.96.1 to 0.96.2: schema-aligned fixed-broker execution wrappers

Adopt `graphql-orm-ai` 0.96.2 from one reviewed full monorepo revision. No host
API or configuration change is required. Fixed-broker providers may now omit
empty `arguments`, `relationshipArguments`, `relationshipMaximumItems` and
`maximumItems` wrapper fields. `loadedReference` and at least one exact public
selection remain required.

Providers should copy only fields admitted by the exact `planSchema` returned
by describe. Flatten supplied scalar argument leaves into the broker's
name/value entries, and supply `maximumItems` only when the loaded plan schema
exposes that property. The final schema-derived compiler and fresh resolver
authorization remain authoritative.

The AI schema module remains **0.64.0**. There is no database, data, GraphQL
SDL, protected-payload, backup, restore, or data backfill migration.

## 0.96.0 to 0.96.1: bounded assistant-item lifecycle continuation

Adopt `graphql-orm-ai` 0.96.1 from one reviewed full monorepo revision. No host
Expand Down
2 changes: 1 addition & 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.96.1", 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.96.2", default-features = false, features = ["sqlite"] }
```

Exactly one persistence backend is required: `sqlite` (default), `postgres`,
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai/docs/implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ supersedes: []

# Implementation Status

`graphql-orm-ai` is at crate version `0.96.1` with AI schema module
`graphql-orm-ai` is at crate version `0.96.2` with AI schema module
`0.64.0`. It uses workspace `graphql-orm` `0.30.0`, backend-neutral
`graphql-orm-ai-tool-profiles` `0.10.4`, and external `agql-auth`
`0.19.0` at `1d2e9fe2e1576105212a7b340a11abf8cad0382d`.
Expand Down
66 changes: 59 additions & 7 deletions crates/graphql-orm-ai/src/capability_delivery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,27 +306,42 @@ fn fixed_broker_definitions(index_fingerprint: &str) -> Vec<ModelToolDefinition>
let execute = broker_definition(
AI_CAPABILITY_EXECUTE_TOOL_ID,
"graphql_capabilities_execute",
"Execute one previously loaded exact capability using a closed public-name query plan.",
"Execute one previously loaded exact capability. Copy only fields admitted by the returned planSchema: flatten argument leaves into name/value entries, and omit optional wrapper fields that the planSchema does not expose.",
index_fingerprint,
json!({
"type": "object",
"properties": {
"loadedReference": {"type": "string", "minLength": 64, "maxLength": 64},
"loadedReference": {
"type": "string", "minLength": 64, "maxLength": 64,
"description": "Exact loadedReference returned by the matching describe call."
},
"arguments": {
"type": "array", "maxItems": 64,
"description": "Optional root arguments admitted by planSchema.arguments. Flatten each supplied scalar leaf into one name/value entry using its dotted public path; omit this array when no root argument is needed.",
"items": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1, "maxLength": 256},
"value": {"type": ["string", "integer", "number", "boolean", "null"]}
"name": {
"type": "string", "minLength": 1, "maxLength": 256,
"description": "Exact dotted public argument path admitted by planSchema.arguments."
},
"value": {
"type": ["string", "integer", "number", "boolean", "null"],
"description": "Scalar value for the exact argument path."
}
},
"required": ["name", "value"],
"additionalProperties": false
}
},
"selections": {"type": "array", "maxItems": 256, "uniqueItems": true, "items": {"type": "string", "maxLength": 512}},
"selections": {
"type": "array", "maxItems": 256, "uniqueItems": true,
"description": "One or more exact scalar paths copied from planSchema.selections.items.enum.",
"items": {"type": "string", "maxLength": 512}
},
"relationshipArguments": {
"type": "array", "maxItems": 64,
"description": "Optional relationship arguments admitted by planSchema.relationshipArguments. Omit when that schema has no applicable relationship argument.",
"items": {
"type": "object",
"properties": {
Expand All @@ -350,6 +365,7 @@ fn fixed_broker_definitions(index_fingerprint: &str) -> Vec<ModelToolDefinition>
},
"relationshipMaximumItems": {
"type": "array", "maxItems": 64,
"description": "Optional relationship bounds admitted by planSchema.relationshipMaximumItems. Omit when the exact relationship path is not present there.",
"items": {
"type": "object",
"properties": {
Expand All @@ -360,9 +376,12 @@ fn fixed_broker_definitions(index_fingerprint: &str) -> Vec<ModelToolDefinition>
"additionalProperties": false
}
},
"maximumItems": {"type": ["integer", "null"], "minimum": 1, "maximum": 10000}
"maximumItems": {
"type": ["integer", "null"], "minimum": 1, "maximum": 10000,
"description": "Optional root result bound. Supply a positive value only when planSchema exposes maximumItems; otherwise omit it."
}
},
"required": ["loadedReference", "arguments", "selections", "relationshipArguments", "relationshipMaximumItems", "maximumItems"],
"required": ["loadedReference", "selections"],
"additionalProperties": false
}),
);
Expand Down Expand Up @@ -3074,6 +3093,39 @@ mod tests {
));
}

#[test]
fn fixed_broker_execute_admits_the_minimal_schema_aligned_wrapper() {
let definitions = fixed_broker_definitions(&"a".repeat(64));
let execute = definitions
.iter()
.find(|definition| definition.tool_id == AI_CAPABILITY_EXECUTE_TOOL_ID)
.expect("fixed execute definition");
let validator = jsonschema::validator_for(&execute.parameters)
.expect("fixed execute parameters should be valid JSON Schema");
let minimal = json!({
"loadedReference": "b".repeat(64),
"selections": ["records.id"]
});
assert!(validator.is_valid(&minimal));
let parsed: BrokerExecuteArguments =
serde_json::from_value(minimal).expect("minimal execute wrapper should decode");
assert!(parsed.arguments.is_empty());
assert!(parsed.relationship_arguments.is_empty());
assert!(parsed.relationship_maximum_items.is_empty());
assert_eq!(parsed.maximum_items, None);

assert_eq!(
execute.parameters["required"],
json!(["loadedReference", "selections"])
);
assert!(execute.description.contains("returned planSchema"));
assert!(
execute.parameters["properties"]["maximumItems"]["description"]
.as_str()
.is_some_and(|description| description.contains("only when planSchema exposes"))
);
}

#[tokio::test]
async fn describe_exposes_compiler_owned_result_record_cost_bounds() {
let principal = principal();
Expand Down
12 changes: 12 additions & 0 deletions crates/graphql-orm-ai/src/providers/codex_app_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8109,6 +8109,18 @@ pub(crate) mod tests {
execute.pointer("/inputSchema/properties/maximumItems/type"),
Some(&json!(["integer", "null"]))
);
assert_eq!(
execute.pointer("/inputSchema/required"),
Some(&json!(["loadedReference", "selections"]))
);
assert!(
jsonschema::validator_for(&execute["inputSchema"])
.expect("projected execute schema")
.is_valid(&json!({
"loadedReference": "b".repeat(64),
"selections": ["records.id"]
}))
);
assert!(
execute
.pointer("/inputSchema/properties/maximumItems/description")
Expand Down

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

2 changes: 1 addition & 1 deletion docs/plans/active/ai-production-readiness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ retention, or restore proofs remain closed.

## Current checkpoint

Package 0.96.1 and AI schema module 0.64.0 provide the protected runtime,
Package 0.96.2 and AI schema module 0.64.0 provide the protected runtime,
provider adapters, exact completed-batch adoption, retention foundations,
restore planning, and readiness observation contracts. Database-derived
collection covers bounded conservative run classification, approval and
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/workspace-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ changes.
| Package | Version | Path | Default features | Direct internal dependencies |
| --- | --- | --- | --- | --- |
| `graphql-orm` | `0.30.0` | `crates/graphql-orm` | `sqlite` | `graphql-orm-macros`, `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-ai` | `0.96.1` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai` | `0.96.2` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai-tool-profiles` | `0.10.4` | `crates/graphql-orm-ai-tool-profiles` | none | `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-backup` | `0.7.2` | `crates/graphql-orm-backup` | `local` | `graphql-orm` (optional), `graphql-orm-storage` |
| `graphql-orm-macros` | `0.30.0` | `crates/graphql-orm-macros` | `sqlite` | none |
Expand Down
Loading