From 7f19b40f7e9e6fab10d9819dd9b9af9ee94c665d Mon Sep 17 00:00:00 2001 From: Rino Montiel <516416+RinoFM@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:48:47 +0000 Subject: [PATCH] sync: lbb 3fe42f31e51a --- README.md | 25 +- contracts/openapi.json | 15638 ++++++++------------------------------- lbb/_async_client.py | 220 +- lbb/_client_base.py | 659 +- lbb/_sync_client.py | 119 +- lbb/models.py | 1618 +--- tests/test_client.py | 533 +- tests/typecheck_dx.py | 15 +- 8 files changed, 3816 insertions(+), 15011 deletions(-) diff --git a/README.md b/README.md index c4f7a84..262fd11 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # littlebigbrain — Python SDK -The Python client for [Little Big Brain](https://littlebigbrain.com) — write graph facts, build indexes, and run hybrid search over one snapshot. Built on `httpx` + `pydantic`; ships sync and async clients. +The Python client for [Little Big Brain](https://littlebigbrain.com) — write graph facts and query one immutable published snapshot. Built on `httpx` + `pydantic`; ships sync and async clients. ```sh pip install littlebigbrain # imports as `lbb` @@ -28,11 +28,16 @@ with LbbClient( }], }, idempotency_key="doc:42:v1") - # 2. Build persisted BM25 + vector + adjacency indexes and wait. - lbb.indexes.run(wait=True) + # 2. Publication is automatic. Inspect one coherent watermark when needed. + published = lbb.read_snapshot_model() + print(published.snapshot.served_at_seq, published.query_lag_commits) # 3. Hybrid search over the snapshot. - results = lbb.search.hybrid("how much annual leave do employees get?", top_k=5) + results = lbb.search.hybrid( + "how much annual leave do employees get?", + top_k=5, + consistency="eventual", + ) for hit in results.get("assertions", []): print(hit["relation"]["name"], hit["score"]) ``` @@ -41,7 +46,8 @@ For hosted use, pass the exact `endpoint_url` shown on the stack's Connect page. Omitting `base_url` retains the loopback default for local/self-hosted development only; graph and branch remain ordinary client scope parameters. -Facts are graph-scoped (`lbb.graph("main").facts`); indexes and search are client-level (`lbb.indexes`, `lbb.search`) and use the stack's default graph. +Facts are graph-scoped (`lbb.graph("main").facts`); search and published-snapshot +inspection use the client's active graph/branch scope. ## Examples @@ -96,7 +102,14 @@ Methods return parsed dictionaries and raise `LbbError` (with `status_code`, `co ## More -Beyond the quickstart: `entities.iter(...)` for cursor-safe iteration, `context.ask(...)` for grounded answers, `ontology`/`schema` for the SHACL lifecycle, durable index and training jobs (`index_submit`/`index_job`), managed embeddings, traversal, and temporal history. Typed Pydantic responses are available via the matching `*_model` / `*_page` helpers; generated models live in `lbb.models`. +Beyond the quickstart: `entities.sample(type=..., limit=...)` for a bounded +published-generation sample and `entities.filter_by_attributes(...)` for +relation-bound structured SPARQL; `context.suggest(...)`, `context.resolve(...)`, +`context.decode(...)`, and `context.groundability(...)` for vocabulary-grounded +applications; and `ontology`/`schema` for ontology inspection and atomic schema +publication. Model shadow evaluation and planner, preference, suggestion, and +extractor datasets remain available. Typed Pydantic responses are exposed by +matching `*_model` helpers; generated models live in `lbb.models`. Full reference and guides: [docs.littlebigbrain.com/sdks/python](https://docs.littlebigbrain.com/sdks/python/). diff --git a/contracts/openapi.json b/contracts/openapi.json index 20e8b87..e14dd83 100644 --- a/contracts/openapi.json +++ b/contracts/openapi.json @@ -292,23 +292,9 @@ ] }, "AnalyticQueryRequest": { + "additionalProperties": false, "description": "A basic-graph-pattern query: a conjunction of triple patterns evaluated over\nthe graph's current edges (joined on shared variables), served from the\nobject-storage permutation view.", "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin: evaluate the query as of this `commit_seq`, hiding any event\ncommitted later. Errors if it exceeds the head. Forces the snapshot reduce\npath — the head-fresh permutation view and the count fast paths are\ndeclined, since they cannot reconstruct an earlier snapshot.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "type": [ - "string", - "null" - ] - }, "combinators": { "description": "Group-graph-pattern combinators (UNION / OPTIONAL / MINUS / EXISTS /\nNOT EXISTS) folded over the base `patterns`, left-to-right. Empty (the\ndefault) leaves the query a plain conjunctive BGP.", "items": { @@ -323,7 +309,7 @@ }, { "$ref": "#/components/schemas/SearchConsistency", - "description": "Read consistency (A3 serving; A5 default). `eventual` (the **default**)\nserves ENTIRELY from the last published segment RDF family (the\nmaintenance-owned, asserted-only default) at its watermark — no in-memory\ngap fold, so the query stays available while background indexing lags — and\nsurfaces the served watermark on `snapshot.served_at_seq`. Eventual serving\nrequires a published dataset; a graph with none yet returns a retryable 429.\n`strong` (explicit opt-in) evaluates against the head snapshot on the exact\nconformant engine, folding any un-indexed WAL tail in memory — the path that\ncarries `rdfs:subClassOf` closure over the aggregation." + "description": "Read consistency (A3 serving; A5 default). `eventual` (the **default**)\nserves ENTIRELY from the last published segment RDF family (the\nmaintenance-owned, asserted-only default) at its watermark — no in-memory\ngap fold, so the query stays available while background indexing lags — and\nsurfaces the served watermark on `snapshot.served_at_seq`. Eventual serving\nrequires a published dataset; a graph with none yet returns a retryable 429.\n`strong` (explicit opt-in) succeeds only when the immutable published\ngeneration itself covers head. Otherwise it returns retryable\n`strong_read_pending`; no query folds mutable WAL state." } ] }, @@ -481,154 +467,6 @@ ], "type": "string" }, - "AskCitation": { - "properties": { - "id": { - "description": "Entity id or edge-event id, as a string.", - "type": "string" - }, - "kind": { - "$ref": "#/components/schemas/AskCitationKind" - }, - "label": { - "description": "Human-readable label (entity name, or \"src —relation→ dst\").", - "type": "string" - }, - "score": { - "format": "float", - "type": "number" - } - }, - "required": [ - "kind", - "id", - "label", - "score" - ], - "type": "object" - }, - "AskCitationKind": { - "enum": [ - "entity", - "assertion" - ], - "type": "string" - }, - "AskExplain": { - "description": "Per-request instrumentation of the `/v1/ask` pipeline: what each stage cost,\nhow much the DB narrowed the world before the model saw it, and the embedding\nmodel that did the grounding.", - "properties": { - "embedding": { - "description": "The embedding model that grounded + retrieved — its id, or `lexical` for\nthe hash/lexical fallback when the graph has no managed embedding model.", - "type": "string" - }, - "narrowing": { - "$ref": "#/components/schemas/AskNarrowing", - "description": "How much the DB narrowed: the vocabulary the question snapped to and the\nsize of the retrieved evidence set the answer rests on." - }, - "timings": { - "$ref": "#/components/schemas/AskTimings", - "description": "Wall-clock latency of each stage of the one call, in milliseconds." - } - }, - "required": [ - "timings", - "narrowing", - "embedding" - ], - "type": "object" - }, - "AskFeedbackRequest": { - "properties": { - "ask_id": { - "description": "The `ask_id` the ask response carried.", - "type": "string" - }, - "corrected_plan": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AskStructuredPlanV2", - "description": "With `corrected`: the plan that should have been decoded." - } - ] - }, - "note": { - "description": "Optional free-text note (bounded server-side).", - "type": [ - "string", - "null" - ] - }, - "verdict": { - "$ref": "#/components/schemas/AskFeedbackVerdict" - } - }, - "required": [ - "ask_id", - "verdict" - ], - "type": "object" - }, - "AskFeedbackResponse": { - "properties": { - "accepted": { - "description": "True when the verdict was captured. False when signal capture is off\non this deployment — the request contract is identical either way, so\nclients never break when the flag flips.", - "type": "boolean" - }, - "accepted_count": { - "minimum": 0, - "type": "integer" - }, - "event_id": { - "type": "string" - }, - "excluded_count": { - "minimum": 0, - "type": "integer" - }, - "exclusions": { - "additionalProperties": { - "minimum": 0, - "type": "integer" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "receipt_id": { - "type": "string" - }, - "replayed": { - "type": "boolean" - }, - "trainable_count": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "accepted", - "receipt_id", - "event_id", - "replayed", - "accepted_count", - "trainable_count", - "excluded_count" - ], - "type": "object" - }, - "AskFeedbackVerdict": { - "description": "A user verdict on one ask (`POST /v1/ask/feedback`) — the planner's\nexplicit feedback capture. Joined to the ask's `ask_trace` signal by\n`ask_id`.", - "enum": [ - "accepted", - "rejected", - "corrected" - ], - "type": "string" - }, "AskFilterOperatorV2": { "enum": [ "eq", @@ -664,63 +502,6 @@ ], "type": "object" }, - "AskGrounding": { - "properties": { - "candidates": { - "description": "Real vocabulary the question snapped to (classes/relations/properties/\nterms) — a subset of the graph's vocabulary by construction.", - "items": { - "$ref": "#/components/schemas/ResolvedTerm" - }, - "type": "array" - }, - "constrained": { - "description": "True when identifier slots were hard-constrained during decode. Always\nfalse in `grounding_only` (no decode); true under the resident planner.", - "type": "boolean" - }, - "signature_forced": { - "description": "True when the grounding forced a single relation via a type signature\n(WS10). Always false in `grounding_only` v1; set by the resident planner.", - "type": "boolean" - } - }, - "required": [ - "candidates", - "constrained" - ], - "type": "object" - }, - "AskMode": { - "enum": [ - "grounding_only", - "resident_planner" - ], - "type": "string" - }, - "AskNarrowing": { - "description": "How much the database narrowed the world before the model — the core\ncontext-substrate quantity, exposed per request.", - "properties": { - "assertions": { - "description": "Assertions (edges) retrieved as evidence.", - "minimum": 0, - "type": "integer" - }, - "entities": { - "description": "Entities retrieved as evidence.", - "minimum": 0, - "type": "integer" - }, - "vocab_candidates": { - "description": "Vocabulary terms the question snapped to (classes/relations/properties) —\nthe narrowed candidate set, a subset of real vocabulary by construction.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "vocab_candidates", - "entities", - "assertions" - ], - "type": "object" - }, "AskPlanExecutionModeV2": { "enum": [ "entity_search", @@ -729,95 +510,6 @@ ], "type": "string" }, - "AskPlanFailure": { - "properties": { - "code": { - "$ref": "#/components/schemas/AskPlanFailureCode" - }, - "retryable": { - "description": "True when retrying after the planner recovers can produce a plan.", - "type": "boolean" - }, - "stage": { - "$ref": "#/components/schemas/AskPlanFailureStage" - } - }, - "required": [ - "code", - "stage", - "retryable" - ], - "type": "object" - }, - "AskPlanFailureCode": { - "enum": [ - "planner_disabled", - "planner_unavailable", - "no_class_candidates", - "generation_failed", - "validation_failed" - ], - "type": "string" - }, - "AskPlanFailureStage": { - "enum": [ - "configuration", - "target_type", - "relation", - "anchor" - ], - "type": "string" - }, - "AskQuery": { - "properties": { - "plan_failure": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AskPlanFailure", - "description": "Typed explanation when execution fell back without a validated V2\nplan. For every executed ask exactly one of `structured_v2` and\n`plan_failure` is present." - } - ] - }, - "query": { - "description": "The retrieval query text that was executed.", - "type": "string" - }, - "structured": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AskStructuredQuery", - "description": "The structured plan the resident model decoded under the shortlist\ntrie, when the constrained leg ran. Identifiers are real vocabulary by\nconstruction (server-verified ⊆ the grounded shortlist)." - } - ] - }, - "structured_v2": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AskStructuredPlanV2", - "description": "Complete versioned execution contract. Present for every constrained\nplanner result; V1 remains as a compatibility projection." - } - ] - }, - "top_k": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "query", - "top_k" - ], - "type": "object" - }, "AskRelationDirectionV2": { "enum": [ "outgoing", @@ -841,139 +533,6 @@ ], "type": "object" }, - "AskRequest": { - "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin (transaction-time ceiling): retrieval and citations\nreproduce the graph as of this commit sequence; the response\n`snapshot.as_of_commit_seq` echoes the pin. Omitted means head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "description": "Valid-time cursor (RFC 3339): retrieval reflects facts true at this\ninstant. Omitted means the latest valid time.", - "type": [ - "string", - "null" - ] - }, - "execute": { - "description": "Run retrieval and return citations (default true). When false, only the\ngrounding is computed — the caller drives its own retrieval/model.", - "type": [ - "boolean", - "null" - ] - }, - "fields": { - "description": "Entity attributes retained as evidence on the internal execution trace.", - "items": { - "type": "string" - }, - "type": "array" - }, - "filters": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchFilterExpr", - "description": "Authorization/attribute filter applied to grounding prepasses and final\nexecution at the same snapshot." - } - ] - }, - "question": { - "description": "The natural-language question.", - "type": "string" - }, - "snapshot_token": { - "description": "Opaque alternative to `as_of_commit_seq`. Exactly one pin spelling may\nbe supplied; grounding, validation, execution, trace, and citations all\nuse the resolved commit.", - "type": [ - "string", - "null" - ] - }, - "top_k": { - "description": "Max citations to return (default 8, clamped to 25).", - "minimum": 0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "question" - ], - "type": "object" - }, - "AskResponse": { - "properties": { - "answer": { - "description": "A synthesized answer when a model produced one; in `grounding_only` this\nis a templated evidence summary (the retrieved matches), not model prose.", - "type": [ - "string", - "null" - ] - }, - "ask_id": { - "description": "Server-stamped id for this ask. Reference it in\n`POST /v1/ask/feedback` to attach a verdict; when signal capture is on\nit is also the `request_id` joining the emitted `ask_trace` signal to\nits `ask_feedback` — the planner fine-tune's training join key.", - "type": [ - "string", - "null" - ] - }, - "citations": { - "description": "Evidence: the graph items the answer rests on.", - "items": { - "$ref": "#/components/schemas/AskCitation" - }, - "type": "array" - }, - "confidence": { - "description": "Confidence in [0, 1], from the top retrieved score.", - "format": "float", - "type": "number" - }, - "explain": { - "$ref": "#/components/schemas/AskExplain", - "description": "Instrumentation for the one call: per-stage latency, how much the DB\nnarrowed, and which embedding model grounded the question. Makes the\n\"DB narrows, cheap model decodes\" pipeline observable per request." - }, - "grounding": { - "$ref": "#/components/schemas/AskGrounding", - "description": "How the question was mapped onto real vocabulary." - }, - "mode": { - "$ref": "#/components/schemas/AskMode", - "description": "Which pipeline produced this answer." - }, - "query": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AskQuery", - "description": "The retrieval that was executed (absent when `execute` is false)." - } - ] - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - } - }, - "required": [ - "mode", - "grounding", - "citations", - "confidence", - "explain", - "snapshot" - ], - "type": "object" - }, "AskStructuredPlanV2": { "properties": { "execution_mode": { @@ -1070,48 +629,6 @@ ], "type": "object" }, - "AskTimings": { - "description": "Per-stage wall-clock latency for one `/v1/ask` call, in milliseconds.", - "properties": { - "decode_ms": { - "description": "Shortlist-constrained structured-query decode on the resident model;\nabsent when the constrained leg did not run.", - "format": "double", - "type": [ - "number", - "null" - ] - }, - "ground_ms": { - "description": "Grounding the question to real vocabulary (WS11 resolve).", - "format": "double", - "type": "number" - }, - "retrieve_ms": { - "description": "Hybrid retrieval against the pinned snapshot. Zero when `execute` is false.", - "format": "double", - "type": "number" - }, - "synth_ms": { - "description": "Resident-model synthesis; absent when no planner ran (`grounding_only`).", - "format": "double", - "type": [ - "number", - "null" - ] - }, - "total_ms": { - "description": "End-to-end latency of the whole call.", - "format": "double", - "type": "number" - } - }, - "required": [ - "ground_ms", - "retrieve_ms", - "total_ms" - ], - "type": "object" - }, "AskTypedFilterV2": { "properties": { "field": { @@ -1520,9 +1037,6 @@ "idempotent_replay": { "type": "boolean" }, - "indexed": { - "type": "boolean" - }, "no_op": { "type": "boolean" }, @@ -1575,7 +1089,6 @@ "observation_ids", "entity_ids", "edge_event_ids", - "indexed", "idempotent_replay" ], "type": "object" @@ -1953,44 +1466,6 @@ ], "type": "object" }, - "DerivedEdgeView": { - "description": "One derived edge (a fact that follows from the rules but is not asserted).", - "properties": { - "confidence": { - "description": "Confidence inherited from the supporting facts: the **max** over\nderivations of the **min** over each derivation's premises (so a fact is\nas strong as its weakest premise, and the best derivation wins).", - "format": "float", - "type": "number" - }, - "depends_on": { - "description": "The provenance trail this fact transitively rests on — typed leaves so an\nasserted edge (`Asserted`) and a calibrated retrieval match (`Retrieval`)\nstay distinguishable and a retrieval match can never masquerade as an\nasserted fact (FAL-PROV-NOT-LAUNDERED). Pure rule derivation resolves to\n`Asserted` leaves only.", - "items": { - "$ref": "#/components/schemas/ProvenanceLeafView" - }, - "type": "array" - }, - "object": { - "$ref": "#/components/schemas/EntityView" - }, - "predicate": { - "type": "string" - }, - "rule": { - "description": "The rule that first derived this edge.", - "type": "string" - }, - "subject": { - "$ref": "#/components/schemas/EntityView" - } - }, - "required": [ - "subject", - "predicate", - "object", - "rule", - "confidence" - ], - "type": "object" - }, "EdgeEventId": { "type": "string" }, @@ -2061,135 +1536,6 @@ ], "type": "string" }, - "EmbeddingIndexBuildRequest": { - "properties": { - "dim": { - "format": "int32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "include_clusters": { - "type": "boolean" - }, - "include_raw_rerank": { - "description": "Append a raw-f32 region per cluster so persisted vector search can opt\ninto exact rerank (`rerank` on the search request). Larger objects at\nrest; default off keeps runs compact and 4-bit-only.", - "type": "boolean" - }, - "max_clusters": { - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "provider": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EmbeddingProviderConfig" - } - ] - }, - "quantizer": { - "description": "Quantizer codec for the persisted cluster blocks. Absent / `None` uses\nthe default `tq-hadamard` (4-bit). Set `exrabitq` (with `quantizer_bits`,\n2..=8) for the higher-bit Extended RaBitQ codec that can reach\nrerank-grade recall without the raw-f32 region (P30/R9). The scheme is\nself-describing in the persisted index meta, so reads dispatch\nautomatically; this only changes how new runs are built.", - "type": [ - "string", - "null" - ] - }, - "quantizer_bits": { - "description": "Bits per dimension for the `exrabitq` scheme (2..=8). Ignored by\n`tq-hadamard` (fixed 4-bit); defaults to 4 when `quantizer` is set\nwithout bits.", - "format": "int32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "targets": { - "items": { - "$ref": "#/components/schemas/AnnTargetKind" - }, - "type": "array" - } - }, - "required": [ - "targets", - "include_clusters" - ], - "type": "object" - }, - "EmbeddingIndexBuildResponse": { - "properties": { - "manifest_etag": { - "type": "string" - }, - "manifest_key": { - "type": "string" - }, - "provider": { - "$ref": "#/components/schemas/EmbeddingProviderSpec" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "spaces": { - "items": { - "$ref": "#/components/schemas/EmbeddingIndexBuildSpaceView" - }, - "type": "array" - } - }, - "required": [ - "snapshot", - "provider", - "manifest_key", - "manifest_etag", - "spaces" - ], - "type": "object" - }, - "EmbeddingIndexBuildSpaceView": { - "properties": { - "cluster_count": { - "minimum": 0, - "type": "integer" - }, - "clusters": { - "items": { - "$ref": "#/components/schemas/EmbeddingIndexClusterView" - }, - "type": "array" - }, - "entry_count": { - "minimum": 0, - "type": "integer" - }, - "object_etag": { - "type": "string" - }, - "object_key": { - "type": "string" - }, - "space": { - "$ref": "#/components/schemas/EmbeddingSpaceKey" - } - }, - "required": [ - "space", - "object_key", - "object_etag", - "entry_count", - "cluster_count", - "clusters" - ], - "type": "object" - }, "EmbeddingIndexClusterView": { "properties": { "cluster_id": { @@ -2244,16 +1590,6 @@ } ] }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EmbeddingIndexSource" - } - ] - }, "targets": { "items": { "$ref": "#/components/schemas/AnnTargetKind" @@ -2281,9 +1617,6 @@ "snapshot": { "$ref": "#/components/schemas/SnapshotView" }, - "source": { - "$ref": "#/components/schemas/EmbeddingIndexSource" - }, "spaces": { "items": { "$ref": "#/components/schemas/EmbeddingIndexSpaceView" @@ -2293,20 +1626,11 @@ }, "required": [ "snapshot", - "source", "provider", "spaces" ], "type": "object" }, - "EmbeddingIndexSource": { - "enum": [ - "ephemeral", - "persisted", - "persisted_only" - ], - "type": "string" - }, "EmbeddingIndexSpaceView": { "properties": { "cluster_count": { @@ -2553,11 +1877,12 @@ "model_id": { "type": "string" }, - "overlay_candidates": { + "probe_count": { "minimum": 0, "type": "integer" }, - "probe_count": { + "published_lag_commits": { + "description": "Commit distance from the graph head to the pinned published generation.", "minimum": 0, "type": "integer" }, @@ -2576,9 +1901,6 @@ "minimum": 0, "type": "integer" }, - "source": { - "$ref": "#/components/schemas/EmbeddingIndexSource" - }, "spaces_searched": { "minimum": 0, "type": "integer" @@ -2593,46 +1915,25 @@ "description": "Which persisted ANN run served this query relative to the resolved\n`as_of` ceiling. Present only when `explain` is set. See\n[`SearchTemporalCoverage`]." } ] - }, - "unindexed_tail_commits": { - "minimum": 0, - "type": "integer" } }, "required": [ "model_id", "dim", "metric", - "source", - "unindexed_tail_commits", + "published_lag_commits", "spaces_searched", "entries_scored", "candidates_after_filter", "probe_count", - "overlay_candidates", "filter_prefiltered_candidates", "filter_skipped_candidates" ], "type": "object" }, "EmbeddingSearchRequest": { + "additionalProperties": false, "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. The ANN\nrun is selected as the newest run at or below the pin and the pin bounds\nthe forward overlay; candidate generation is never the correctness layer.\nOmitted means the current head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "description": "Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.", - "type": [ - "string", - "null" - ] - }, "consistency": { "oneOf": [ { @@ -2734,16 +2035,6 @@ "null" ] }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EmbeddingIndexSource" - } - ] - }, "targets": { "items": { "$ref": "#/components/schemas/AnnTargetKind" @@ -3211,7 +2502,7 @@ "EntityNeighborhoodRequest": { "properties": { "as_of_commit_seq": { - "description": "Snapshot pin: reproduce the neighborhood as of this `commit_seq`, hiding\nany event committed later. Errors if it exceeds the current head, and\nforces the snapshot scan (the ranged adjacency fast path declines a\npinned read). Omit for the latest snapshot.", + "description": "Snapshot pin: reproduce the neighborhood as of this `commit_seq`, hiding\nany event committed later. Public serving reduces the entity's bounded\nincident domains from the Base family in the one pinned published\ngeneration; it never discovers or assembles another snapshot. Omit for\nthe latest snapshot.", "format": "int64", "minimum": 0, "type": [ @@ -3244,7 +2535,7 @@ "type": "object" }, "EntityNeighborhoodResponse": { - "description": "Result of an entity point lookup: the entity plus its current out/in\nneighborhood. Served from the ranged adjacency run's per-entity slices when\none exists (cost is the entity's degree, not the whole graph), otherwise\nfrom the snapshot overlay.", + "description": "Result of an entity point lookup: the entity plus its out/in neighborhood.\nPublic reads use adjacency for the published watermark and the same\ngeneration's Base family for historical pins; both paths cost the entity's\ndegree rather than the whole graph.", "properties": { "entity": { "$ref": "#/components/schemas/EntityView" @@ -3262,7 +2553,7 @@ "type": "array" }, "served_from_ranged": { - "description": "True when served from the persisted ranged adjacency run (the\npoint-lookup fast path); false when computed from the snapshot overlay.", + "description": "True when served directly from the persisted adjacency family. False\nwhen an exact historical pin was reduced from the same published\ngeneration's Base family.", "type": "boolean" }, "snapshot": { @@ -3954,91 +3245,11 @@ ], "type": "object" }, - "FullTextIndexBuildRequest": { - "properties": { - "include_terms": { - "type": "boolean" - }, - "targets": { - "items": { - "$ref": "#/components/schemas/AnnTargetKind" - }, - "type": "array" - }, - "tokenizer": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FullTextTokenizerConfig" - } - ] - } - }, - "required": [ - "targets", - "include_terms" - ], - "type": "object" - }, - "FullTextIndexBuildResponse": { - "properties": { - "average_document_len": { - "format": "float", - "type": "number" - }, - "document_count": { - "minimum": 0, - "type": "integer" - }, - "manifest_etag": { - "type": "string" - }, - "manifest_key": { - "type": "string" - }, - "object_etag": { - "type": "string" - }, - "object_key": { - "type": "string" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "term_count": { - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "snapshot", - "manifest_key", - "manifest_etag", - "object_key", - "object_etag", - "document_count", - "term_count", - "average_document_len" - ], - "type": "object" - }, "FullTextIndexInspectRequest": { "properties": { "include_terms": { "type": "boolean" }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FullTextIndexSource" - } - ] - }, "targets": { "items": { "$ref": "#/components/schemas/AnnTargetKind" @@ -4071,9 +3282,6 @@ "snapshot": { "$ref": "#/components/schemas/SnapshotView" }, - "source": { - "$ref": "#/components/schemas/FullTextIndexSource" - }, "term_count": { "minimum": 0, "type": "integer" @@ -4090,7 +3298,6 @@ }, "required": [ "snapshot", - "source", "document_count", "term_count", "average_document_len", @@ -4099,14 +3306,6 @@ ], "type": "object" }, - "FullTextIndexSource": { - "enum": [ - "ephemeral", - "persisted", - "persisted_only" - ], - "type": "string" - }, "FullTextSearchExplain": { "properties": { "candidates": { @@ -4145,7 +3344,8 @@ "null" ] }, - "overlay_candidates": { + "published_lag_commits": { + "description": "Commit distance from the graph head to the pinned published generation.", "minimum": 0, "type": "integer" }, @@ -4159,9 +3359,6 @@ } ] }, - "source": { - "$ref": "#/components/schemas/FullTextIndexSource" - }, "temporal_coverage": { "oneOf": [ { @@ -4169,50 +3366,29 @@ }, { "$ref": "#/components/schemas/SearchTemporalCoverage", - "description": "Which persisted run served this query relative to the resolved `as_of`\nceiling, and how far the forward overlay had to reach. Present only when\n`explain` is set. See [`SearchTemporalCoverage`]." + "description": "Which immutable run in the pinned published generation served this\nquery. Present only when `explain` is set. See\n[`SearchTemporalCoverage`]." } ] }, "term_count": { "minimum": 0, "type": "integer" - }, - "unindexed_tail_commits": { - "minimum": 0, - "type": "integer" } }, "required": [ - "source", - "unindexed_tail_commits", + "published_lag_commits", "document_count", "term_count", "candidates", "filtered_candidates", - "overlay_candidates", "filter_prefiltered_candidates", "filter_skipped_candidates" ], "type": "object" }, "FullTextSearchRequest": { + "additionalProperties": false, "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. The BM25\nrun is selected as the newest run at or below the pin and the pin bounds\nthe forward overlay; candidate generation is never the correctness layer.\nOmitted means the current head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "description": "Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.", - "type": [ - "string", - "null" - ] - }, "consistency": { "oneOf": [ { @@ -4272,16 +3448,6 @@ "query": { "type": "string" }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FullTextIndexSource" - } - ] - }, "targets": { "items": { "$ref": "#/components/schemas/AnnTargetKind" @@ -4454,16 +3620,9 @@ "type": "object" }, "GovernedConflictAggregationRequest": { + "additionalProperties": false, "description": "Snapshot-pinned governed fact-conflict aggregation. Authorization is a\nrequired filter and is evaluated before any grouping or value collection.", "properties": { - "as_of_commit_seq": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, "entity_type": { "type": "string" }, @@ -5205,24 +4364,6 @@ "GraphId": { "type": "string" }, - "GraphImportIndexOutcome": { - "description": "Outcome of the optional one-shot index build a bulk import runs at the end\nwhen `?index=true` is passed — the \"bulk load, queryable on return\"\nprimitive. `built` is whether the full build completed, so the imported data\nis served from the persisted runs (not just the ephemeral snapshot fallback)\nby the time the request returns. `skipped_reason` is present only when\n`built` is false: `\"index_busy\"` (the node's build-admission gate was busy —\nthe data is committed and queryable, retry the build later) or\n`\"index_error\"` (the build failed; detail is logged server-side, not\nsurfaced, to avoid leaking internal paths).", - "properties": { - "built": { - "type": "boolean" - }, - "skipped_reason": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "built" - ], - "type": "object" - }, "GraphImportLine": { "description": "One line of an NDJSON bulk-import stream (`POST /v1/graph/import`). Each line\nis a single JSON object that is either a triplet (carries `relation`) or an\nentity-properties record (carries `properties`); the two shapes are disjoint,\nso the importer routes each line by shape. This is the streamable counterpart\nof `TripletCommitFile`: a client streams a large dataset line-by-line instead\nof buffering one giant commit, and the server batches lines into bounded\ninternal commits.", "oneOf": [ @@ -5251,8 +4392,32 @@ ], "type": "object" }, + "GraphImportPublishedGenerationOutcome": { + "description": "Durable publication accepted after `POST /v1/graph/import?publish=true`.\nThe import request never constructs index families or waits for publication;\nclients can poll the returned job while continuing to observe the previously\npublished generation.", + "properties": { + "disposition": { + "$ref": "#/components/schemas/PublishedGenerationEnqueueDisposition" + }, + "due_seq": { + "$ref": "#/components/schemas/CommitSeq" + }, + "job_id": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "job_id", + "disposition", + "status", + "due_seq" + ], + "type": "object" + }, "GraphImportResponse": { - "description": "Aggregate outcome of a bulk NDJSON import. `committed_commit_seq` is the\nsequence of the last internal batch commit (absent if nothing committed).\n`errors` is bounded; `error_count` is the true total even when the list is\ntruncated. `index` is present only when the caller passed `?index=true`.", + "description": "Aggregate outcome of a bulk NDJSON import. `committed_commit_seq` is the\nsequence of the last internal batch commit (absent if nothing committed).\n`errors` is bounded; `error_count` is the true total even when the list is\ntruncated. `published_generation` is present only when the caller passed\n`?publish=true` and at least one batch committed.", "properties": { "batches": { "minimum": 0, @@ -5289,19 +4454,6 @@ "description": "True when every internal mutation batch was the already-committed\nreceipt for this idempotency key.", "type": "boolean" }, - "index": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/GraphImportIndexOutcome" - } - ] - }, - "indexed": { - "type": "boolean" - }, "lines_read": { "minimum": 0, "type": "integer" @@ -5319,6 +4471,16 @@ "minimum": 0, "type": "integer" }, + "published_generation": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/GraphImportPublishedGenerationOutcome" + } + ] + }, "triplets": { "minimum": 0, "type": "integer" @@ -5333,7 +4495,6 @@ "triplets", "properties", "batches", - "indexed", "error_count" ], "type": "object" @@ -5399,9 +4560,6 @@ "include_indexes": { "type": "boolean" }, - "include_objects": { - "type": "boolean" - }, "max_clusters": { "minimum": 0, "type": [ @@ -5472,7 +4630,7 @@ "type": "integer" }, "index_caught_up": { - "description": "One-shot \"has the persisted index caught up to head?\" signal, so a\nbulk-import caller does not hand-assemble the three-field predicate.\n`Some(true)` iff both the BM25 and ANN persisted runs are current to the\nhead commit (no un-indexed tail); `Some(false)` when a build is still\npending or absent; `None` when indexes were not inspected\n(`include_indexes=false`). Note (Strong consistency): committed data is\nqueryable via the per-query overlay *before* this turns true — this marks\nthe persisted fast path being current, not queryability.", + "description": "One-shot \"has the published generation caught up to head?\" signal, so a\nbulk-import caller does not hand-assemble the three-field predicate.\n`Some(true)` iff both the BM25 and ANN persisted runs are current to the\nhead commit; `Some(false)` when publication is still\npending or absent; `None` when indexes were not inspected\n(`include_indexes=false`).", "type": [ "boolean", "null" @@ -5488,15 +4646,6 @@ } ] }, - "object_bytes": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "object_count": { - "minimum": 0, - "type": "integer" - }, "ontology_version": { "format": "int64", "minimum": 0, @@ -5512,6 +4661,11 @@ } ] }, + "published_lag_commits": { + "description": "Commit distance from the graph head to the pinned published generation.", + "minimum": 0, + "type": "integer" + }, "segment_bytes": { "format": "int64", "minimum": 0, @@ -5525,29 +4679,6 @@ "snapshot": { "$ref": "#/components/schemas/SnapshotView" }, - "temporal_coverage": { - "$ref": "#/components/schemas/TemporalCoverage", - "description": "Temporal coverage of this snapshot — what kinds of as-of query the data\ncan actually answer. Lets a caller tell *before* querying whether\npoint-in-time / daily views are possible, instead of discovering that\nevery as-of returns the same picture." - }, - "temporal_coverage_computed": { - "description": "Whether `temporal_coverage` was computed from the full snapshot. The\nbounded HTTP metadata path is head-only by default; callers that need\nexact event-time coverage opt in explicitly.", - "type": "boolean" - }, - "unindexed_tail_commits": { - "minimum": 0, - "type": "integer" - }, - "visibility_manifest": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/IndexVisibilityManifest", - "description": "Unified visibility-manifest summary. `None` before the first family is\npublished or when index inspection was disabled." - } - ] - }, "wal_tail_bytes": { "format": "int64", "minimum": 0, @@ -5565,9 +4696,7 @@ "head_generation", "wal_tail_commits", "wal_tail_bytes", - "object_count", - "object_bytes", - "unindexed_tail_commits" + "published_lag_commits" ], "type": "object" }, @@ -5584,17 +4713,11 @@ "type": "object" }, "GraphRdfImportPredicate": { - "description": "A predicate discovered while importing RDF through `POST /v1/graph/import/rdf`.\n`uri` is the original RDF predicate IRI. `relation` is the fixed\n`RDF_TRIPLE` relation used for committed edges, while `lbb_predicate_iri`\nremains the source predicate IRI that the RDF/SPARQL projection emits.\n`property` and `lbb_property_iri` are retained as nullable compatibility\nfields for older clients and are not populated by the fixed-schema importer.", + "description": "A predicate discovered while importing RDF through `POST /v1/graph/import/rdf`.\n`uri` is the original RDF predicate IRI. `relation` is the fixed\n`RDF_TRIPLE` relation used for committed edges, while `lbb_predicate_iri`\nremains the source predicate IRI that the RDF/SPARQL projection emits.", "properties": { "lbb_predicate_iri": { "type": "string" }, - "lbb_property_iri": { - "type": [ - "string", - "null" - ] - }, "lbb_relation_iri": { "type": "string" }, @@ -5602,12 +4725,6 @@ "minimum": 0, "type": "integer" }, - "property": { - "type": [ - "string", - "null" - ] - }, "relation": { "type": "string" }, @@ -5676,9 +4793,6 @@ "minimum": 0, "type": "integer" }, - "indexed": { - "type": "boolean" - }, "lines_read": { "minimum": 0, "type": "integer" @@ -5697,6 +4811,16 @@ }, "type": "array" }, + "published_generation": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/GraphImportPublishedGenerationOutcome" + } + ] + }, "resource_triples": { "minimum": 0, "type": "integer" @@ -5716,7 +4840,6 @@ "duplicate_literal_triples", "imported_triplets", "batches", - "indexed", "predicate_count", "error_count" ], @@ -6422,215 +5545,232 @@ ], "type": "object" }, - "IndexBuildOptions": { - "description": "Optional JSON body for the data-plane index-build routes (`/v1/index/run`\nand `/v1/index/build`). Every field is optional: an empty body resolves the\nANN space the way the search path does — a managed embedding config selects\nits `stored` space (its dim winning), otherwise the server's hash default —\nso a bare reindex always rebuilds the space queries actually look up.\nSupplying `provider` overrides that resolution, e.g. to persist a build over\ncommitted BYO vectors with an explicit `stored`/`external_vectors` space.", + "IndexLineage": { + "description": "Typed convergence view over the persisted serving families.", "properties": { - "build_permutation": { - "default": false, - "description": "Build the object-storage-native permutation view (PSO). Off by default.", - "type": "boolean" - }, - "dim": { - "default": null, - "description": "Embedding dimension when no `provider.dim` is given. Defaults to the\nserver's configured dim. Must match the committed vectors' dimension.", - "format": "int32", - "minimum": 0, - "type": [ - "integer", - "null" + "adjacency_indexed_commit_seq": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CommitSeq" + } ] }, - "include_raw_rerank": { - "default": false, - "description": "Append a raw-f32 rerank region to the embedding run. Off by default.", - "type": "boolean" - }, - "max_clusters": { - "default": null, - "description": "ANN clusters per space. Defaults to the server's configured value.", - "minimum": 0, - "type": [ - "integer", - "null" + "ann_indexed_commit_seq": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CommitSeq" + } ] }, - "provider": { - "default": null, + "bm25_indexed_commit_seq": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/EmbeddingProviderConfig", - "description": "Embedding provider for the ANN family. `None` keeps the server default\n(hash). Use `stored`/`external_vectors` to index committed BYO vectors." + "$ref": "#/components/schemas/CommitSeq" } ] - } - }, - "type": "object" - }, - "IndexDeltaResponse": { - "description": "Outcome of an incremental index-run delta build (`index delta`, or the\ncommit-path auto-delta trigger). `built` is true when a delta segment was\nappended; `folded` is true when the chain was instead rebuilt into a fresh\nbase (chain too long, or freshness fold). `skipped_reason` explains a no-op\n(no base run, nothing un-indexed).", - "properties": { - "built": { - "type": "boolean" }, - "delta_document_count": { - "minimum": 0, - "type": "integer" - }, - "family": { - "type": "string" - }, - "folded": { + "caught_up": { "type": "boolean" }, - "from_commit_seq": { + "head_commit_seq": { "$ref": "#/components/schemas/CommitSeq" }, - "indexed_seq": { - "$ref": "#/components/schemas/CommitSeq" + "manifest_view_token": { + "description": "Content identity of the head generation plus the exact three manifest\nviews observed while constructing this response.", + "type": "string" }, - "segments": { - "minimum": 0, + "observed_at_micros": { + "format": "int64", "type": "integer" - }, - "skipped_reason": { - "type": [ - "string", - "null" - ] - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "to_commit_seq": { - "$ref": "#/components/schemas/CommitSeq" } }, "required": [ - "snapshot", - "family", - "built", - "folded", - "from_commit_seq", - "to_commit_seq", - "delta_document_count", - "segments", - "indexed_seq" + "head_commit_seq", + "caught_up", + "manifest_view_token", + "observed_at_micros" ], "type": "object" }, - "IndexFamilyVisibility": { - "description": "Bounded, user-facing summary of one family in the unified visibility manifest.", + "IndexVisibilityFamily": { + "description": "One of the index families referenced by an atomic published read root.", + "enum": [ + "base", + "rdf", + "bm25", + "ann", + "adjacency" + ], + "type": "string" + }, + "InferenceRule": { + "description": "A single inference rule (SHACL-AF `sh:TripleRule` shape): a BGP `body` (the\ncondition / `WHERE`) and a `head` triple template instantiated once per\nbinding. Every variable used in `head` must be bound by `body`.", "properties": { - "class": { - "$ref": "#/components/schemas/IndexVisibilityFamilyClass" + "body": { + "description": "The rule condition: a basic graph pattern over current edges (asserted +\nalready-derived), joined on shared variables.", + "items": { + "$ref": "#/components/schemas/AnalyticTriplePattern" + }, + "type": "array" }, - "covered_seq": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommitSeq", - "description": "Highest commit folded into the family's merged run. For `merged_only`\nfamilies this is compaction position only; query freshness comes from the\nfamily's delta/L0 path plus bounded tail union and snapshot verification." - } - ] + "combinators": { + "description": "Negation/existence filters folded over the `body` solutions, in order.\nOnly `exists` (semijoin — keep body rows that have a compatible match) and\n`not_exists` (antijoin — keep body rows that have none) are supported in a\nrule; `union`/`optional`/`minus` are rejected. A `not_exists` over a\nrelation produced by another rule's head places this rule in a strictly\nhigher evaluation stratum (so the negated relation is fully derived first);\na negation cycle is rejected. This is what lets a rule express universal\nconditions like \"phase complete when no deliverable is incomplete\". A\nfilter pattern may introduce its own local variables and may reference\n`body` variables to correlate, but it never binds a `head` variable.", + "items": { + "$ref": "#/components/schemas/AnalyticCombinator" + }, + "type": "array" }, - "family": { - "$ref": "#/components/schemas/IndexVisibilityFamily" + "head": { + "$ref": "#/components/schemas/AnalyticTriplePattern", + "description": "The triple template derived once per `body` binding. `subject`/`object`\nare variables bound by `body` (or fixed entities); `predicate` is a\nrelation name." }, - "l0_from_seq": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommitSeq" - } - ] + "name": { + "type": "string" }, - "l0_segment_count": { - "minimum": 0, + "order": { + "description": "SHACL `sh:order`. Rules run low-to-high; a determinism hint for the\npositive (monotone) rules supported today, where the least fixpoint is\norder-independent.", + "format": "int64", "type": "integer" + } + }, + "required": [ + "name", + "head" + ], + "type": "object" + }, + "LbbErrorBody": { + "properties": { + "code": { + "examples": [ + "missing_idempotency_key" + ], + "type": "string" }, - "l0_to_seq": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommitSeq" - } + "doc_url": { + "type": [ + "string", + "null" ] }, - "model_hash": { - "description": "Distinguishes ANN model spaces without exposing object keys.", + "message": { + "type": "string" + }, + "param": { "type": [ "string", "null" ] }, - "target_hash": { - "description": "Distinguishes target-specific BM25/ANN families without exposing object keys.", + "request_id": { "type": [ "string", "null" ] + }, + "retry_after_seconds": { + "minimum": 0, + "type": "integer" + }, + "retryable": { + "type": "boolean" + }, + "type": { + "examples": [ + "invalid_request_error" + ], + "type": "string" } }, "required": [ - "family", - "class", - "l0_segment_count" + "type", + "code", + "message", + "request_id", + "doc_url" ], "type": "object" }, - "IndexGcJobProgress": { + "LbbErrorEnvelope": { "properties": { - "deleted_bytes": { - "format": "int64", + "error": { + "$ref": "#/components/schemas/LbbErrorBody" + } + }, + "required": [ + "error" + ], + "type": "object" + }, + "ManagedEmbeddingBackfillJobProgress": { + "properties": { + "continuation": { + "type": [ + "string", + "null" + ] + }, + "embedded": { "minimum": 0, "type": "integer" }, - "deleted_objects": { + "failed": { "minimum": 0, "type": "integer" }, + "final_index_job_id": { + "type": [ + "string", + "null" + ] + }, "heartbeat_micros": { "format": "int64", "type": "integer" }, - "reclaimable_bytes": { - "format": "int64", + "index_lineage": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/IndexLineage" + } + ] + }, + "missing": { "minimum": 0, "type": "integer" }, - "reclaimable_objects": { + "processed": { "minimum": 0, "type": "integer" }, - "reclaimable_runs": { + "skipped": { "minimum": 0, "type": "integer" }, - "scanned_bytes": { + "source_commit_seq": { "format": "int64", "minimum": 0, "type": "integer" }, - "scanned_objects": { - "minimum": 0, - "type": "integer" + "source_snapshot_token": { + "type": "string" }, - "scanned_runs": { + "total": { "minimum": 0, "type": "integer" }, - "stage": { - "type": "string" - }, "worker": { "type": [ "string", @@ -6639,19 +5779,41 @@ } }, "required": [ - "stage", - "scanned_runs", - "scanned_objects", - "scanned_bytes", - "reclaimable_runs", - "reclaimable_objects", - "reclaimable_bytes", - "deleted_objects", - "deleted_bytes" + "total", + "processed", + "embedded", + "skipped", + "missing", + "failed", + "source_commit_seq", + "source_snapshot_token", + "heartbeat_micros" ], "type": "object" }, - "IndexGcJobStatusResponse": { + "ManagedEmbeddingBackfillJobRequest": { + "properties": { + "batch_size": { + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "full": { + "type": "boolean" + }, + "limit": { + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "ManagedEmbeddingBackfillJobStatusResponse": { "properties": { "attempts": { "format": "int32", @@ -6665,29 +5827,33 @@ "graph": { "$ref": "#/components/schemas/GraphKey" }, + "idempotency_key": { + "type": "string" + }, "job_id": { "type": "string" }, + "parked": { + "description": "True when the job failed terminally because the provider rejected it for\nan account data-policy / configuration reason (a ZDR-ineligible model,\nauth, model-not-found) rather than a transient error — a *parked* job that\nwill not retry. The console renders this as a \"choose a different model\"\nblock instead of a retry. It clears when the embedding config version\nchanges, which mints a fresh reconciliation job.", + "type": "boolean" + }, "progress": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/IndexGcJobProgress" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobProgress" } ] }, - "request": { - "$ref": "#/components/schemas/IndexGcRequest" - }, "result": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/IndexGcResponse" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillResponse" } ] }, @@ -6709,2103 +5875,1532 @@ "job_id", "status", "graph", - "request", + "idempotency_key", "attempts", "enqueued_at_micros", "updated_at_micros" ], "type": "object" }, - "IndexGcRequest": { + "ManagedEmbeddingBackfillResponse": { + "description": "Outcome of embedding the corpus and scheduling a complete published\ngeneration. `indexed_commit_seq` remains zero until publication;\n`final_index_job_id` identifies the durable generation build when one was\nenqueued. ANN is never cut over independently.", "properties": { - "dry_run": { - "description": "Report what would be deleted without deleting anything.", - "type": "boolean" + "batches": { + "minimum": 0, + "type": "integer" }, - "include_branch_shared": { - "description": "Delete runs even when other branches exist in the graph. Child\nbranches fall back to parent-branch index runs until they build their\nown, so deleting shared parent runs can force child rebuilds.", - "type": "boolean" + "continuation": { + "type": [ + "string", + "null" + ] }, - "keep_runs": { - "description": "Keep this many newest index runs per family (bm25/ann grouping key).\nThe newest run is always kept regardless of this value.", + "embedded": { "minimum": 0, "type": "integer" }, - "reader_grace_commits": { - "description": "Reader grace: retain any run whose snapshot is within this many commits\nof the current head, even when it exceeds `keep_runs`. A search that\nalready resolved a now-superseded run keeps reading its objects, so\ncollecting a recently-passed run out from under an in-flight reader\nsurfaces as a NotFound/500. The grace window protects those runs until\nthe head has advanced far enough that no in-flight search can still be\nholding them. Set to 0 to disable the grace and collect purely by\n`keep_runs` ordering.", - "format": "int64", + "entities_total": { "minimum": 0, "type": "integer" - } - }, - "type": "object" - }, - "IndexGcResponse": { - "properties": { - "deleted_bytes": { - "format": "int64", + }, + "failed": { "minimum": 0, "type": "integer" }, - "deleted_objects": { + "final_index_job_id": { + "type": [ + "string", + "null" + ] + }, + "index_lineage": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/IndexLineage" + } + ] + }, + "indexed_commit_seq": { + "format": "int64", "minimum": 0, "type": "integer" }, - "deleted_runs": { + "missing": { "minimum": 0, "type": "integer" }, - "dry_run": { - "type": "boolean" + "model_id": { + "type": "string" }, - "kept_runs": { + "processed": { "minimum": 0, "type": "integer" }, - "runs": { - "items": { - "$ref": "#/components/schemas/IndexRunView" - }, - "type": "array" + "skipped": { + "minimum": 0, + "type": "integer" }, - "scanned_bytes": { + "source_commit_seq": { "format": "int64", "minimum": 0, "type": "integer" }, - "scanned_objects": { + "source_snapshot_token": { + "type": "string" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "entities_total", + "processed", + "embedded", + "skipped", + "missing", + "failed", + "batches", + "truncated", + "source_commit_seq", + "source_snapshot_token", + "indexed_commit_seq", + "model_id" + ], + "type": "object" + }, + "ManagedEmbeddingConfig": { + "description": "The resolved, versioned managed embedding configuration.", + "properties": { + "auto_embed_query": { + "type": "boolean" + }, + "base_model": { + "type": "string" + }, + "created_at_micros": { + "format": "int64", + "type": "integer" + }, + "dim": { + "format": "int32", "minimum": 0, "type": "integer" }, - "skipped_branch_shared": { - "description": "Set when deletion was skipped because other branches may share this\nbranch's index runs and `include_branch_shared` was false.", - "type": "boolean" + "metric": { + "$ref": "#/components/schemas/VectorMetric" }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" + "model_id": { + "type": "string" + }, + "run_id": { + "type": [ + "string", + "null" + ] + }, + "service": { + "$ref": "#/components/schemas/ManagedEmbeddingService" + }, + "source": { + "$ref": "#/components/schemas/ManagedEmbeddingSource" + }, + "version": { + "format": "int64", + "minimum": 0, + "type": "integer" } }, "required": [ - "snapshot", - "dry_run", - "scanned_objects", - "scanned_bytes", - "kept_runs", - "deleted_runs", - "deleted_objects", - "deleted_bytes", - "skipped_branch_shared", - "runs" + "version", + "model_id", + "base_model", + "dim", + "metric", + "service", + "source", + "auto_embed_query", + "created_at_micros" ], "type": "object" }, - "IndexLineage": { - "description": "Typed convergence view over the persisted serving families.", + "ManagedEmbeddingConfigRequest": { + "description": "Set the graph branch's default managed embedding model.", "properties": { - "adjacency_indexed_commit_seq": { + "auto_embed_query": { + "type": [ + "boolean", + "null" + ] + }, + "base_model": { + "type": [ + "string", + "null" + ] + }, + "dim": { + "description": "Vector width. Required for `modal`; optional for `open_router`, where a\none-text validation call discovers the model's native width.", + "format": "int32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "metric": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/CommitSeq" + "$ref": "#/components/schemas/VectorMetric" } ] }, - "ann_indexed_commit_seq": { + "model_id": { + "type": "string" + }, + "run_id": { + "type": [ + "string", + "null" + ] + }, + "service": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/CommitSeq" + "$ref": "#/components/schemas/ManagedEmbeddingService" } ] }, - "bm25_indexed_commit_seq": { + "source": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/CommitSeq" + "$ref": "#/components/schemas/ManagedEmbeddingSource" + } + ] + } + }, + "required": [ + "model_id" + ], + "type": "object" + }, + "ManagedEmbeddingConfigResponse": { + "description": "Read/set response. Legacy hash-derived graphs return `configured=false` and no config.", + "properties": { + "config": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ManagedEmbeddingConfig" } ] }, - "caught_up": { + "configured": { "type": "boolean" }, - "head_commit_seq": { - "$ref": "#/components/schemas/CommitSeq" - }, - "manifest_view_token": { - "description": "Content identity of the head generation plus the exact three manifest\nviews observed while constructing this response.", - "type": "string" - }, - "observed_at_micros": { - "format": "int64", - "type": "integer" + "reconciliation": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse", + "description": "Durable corpus reconciliation for the current config version. `Active`\nis truthful only after this job succeeds." + } + ] } }, "required": [ - "head_commit_seq", - "caught_up", - "manifest_view_token", - "observed_at_micros" + "configured" ], "type": "object" }, - "IndexRunView": { + "ManagedEmbeddingModel": { + "description": "One model returned by the live managed-embedding service catalog.", "properties": { - "bytes": { + "context_length": { "format": "int64", "minimum": 0, - "type": "integer" + "type": [ + "integer", + "null" + ] }, - "family": { + "id": { "type": "string" }, - "kept": { - "type": "boolean" - }, - "objects": { - "minimum": 0, - "type": "integer" + "input_modalities": { + "items": { + "type": "string" + }, + "type": "array" }, - "prefix": { + "name": { "type": "string" }, - "snapshot_commit_seq": { - "$ref": "#/components/schemas/CommitSeq" + "output_modalities": { + "description": "The model's output modalities (e.g. `[\"embeddings\"]`). The catalog is\nfiltered to embedding models on this field, so every entry carries the\nembeddings modality; it is surfaced so clients (and the deploy smoke) can\nre-verify the catalog is embeddings-only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "policy_eligible": { + "description": "True when the model is eligible under the account's data policy — for the\nhosted OpenRouter path, that it has a Zero-Data-Retention route. The\ncatalog only returns eligible models, so this is `true` for every entry\ntoday; the console can trust it to gate selection if ineligible models are\never surfaced alongside them.", + "type": "boolean" + }, + "prompt_price": { + "description": "Provider prompt price as a decimal USD/token string when advertised.", + "type": [ + "string", + "null" + ] } }, "required": [ - "family", - "prefix", - "snapshot_commit_seq", - "objects", - "bytes", - "kept" + "id", + "name" ], "type": "object" }, - "IndexVisibilityFamily": { - "description": "One of the index families published through the unified visibility manifest.", - "enum": [ - "base", - "rdf", - "bm25", - "ann", - "adjacency" - ], - "type": "string" - }, - "IndexVisibilityFamilyClass": { - "description": "How a family participates in the unified visibility watermark.", - "enum": [ - "lockstep", - "merged_only" - ], - "type": "string" - }, - "IndexVisibilityManifest": { - "description": "The unified, per-graph visibility view consumed by the console and status tools.", + "ManagedEmbeddingModelsResponse": { + "description": "Live embedding models available on this deployment.", "properties": { - "epoch": { - "format": "int64", - "minimum": 0, - "type": "integer" + "configured": { + "type": "boolean" }, - "families": { + "models": { "items": { - "$ref": "#/components/schemas/IndexFamilyVisibility" + "$ref": "#/components/schemas/ManagedEmbeddingModel" }, "type": "array" }, - "visible_seq": { - "$ref": "#/components/schemas/CommitSeq", - "description": "Shared published watermark. Lockstep families define this value." + "service": { + "$ref": "#/components/schemas/ManagedEmbeddingService" } }, "required": [ - "epoch", - "visible_seq", - "families" + "service", + "configured" ], "type": "object" }, - "InferenceRule": { - "description": "A single inference rule (SHACL-AF `sh:TripleRule` shape): a BGP `body` (the\ncondition / `WHERE`) and a `head` triple template instantiated once per\nbinding. Every variable used in `head` must be bound by `body`.", + "ManagedEmbeddingPromoteResponse": { + "description": "Response after promoting a finished training run to the graph default.", "properties": { - "body": { - "description": "The rule condition: a basic graph pattern over current edges (asserted +\nalready-derived), joined on shared variables.", - "items": { - "$ref": "#/components/schemas/AnalyticTriplePattern" - }, - "type": "array" + "config": { + "$ref": "#/components/schemas/ManagedEmbeddingConfig" }, - "combinators": { - "description": "Negation/existence filters folded over the `body` solutions, in order.\nOnly `exists` (semijoin — keep body rows that have a compatible match) and\n`not_exists` (antijoin — keep body rows that have none) are supported in a\nrule; `union`/`optional`/`minus` are rejected. A `not_exists` over a\nrelation produced by another rule's head places this rule in a strictly\nhigher evaluation stratum (so the negated relation is fully derived first);\na negation cycle is rejected. This is what lets a rule express universal\nconditions like \"phase complete when no deliverable is incomplete\". A\nfilter pattern may introduce its own local variables and may reference\n`body` variables to correlate, but it never binds a `head` variable.", - "items": { - "$ref": "#/components/schemas/AnalyticCombinator" - }, - "type": "array" + "configured": { + "type": "boolean" }, - "head": { - "$ref": "#/components/schemas/AnalyticTriplePattern", - "description": "The triple template derived once per `body` binding. `subject`/`object`\nare variables bound by `body` (or fixed entities); `predicate` is a\nrelation name." + "evals": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ManagedEmbeddingPromotionEvals" + } + ] }, - "name": { + "promoted_run": { "type": "string" }, - "order": { - "description": "SHACL `sh:order`. Rules run low-to-high; a determinism hint for the\npositive (monotone) rules supported today, where the least fixpoint is\norder-independent.", + "registry": {} + }, + "required": [ + "promoted_run", + "configured", + "config" + ], + "type": "object" + }, + "ManagedEmbeddingPromotionEvals": { + "description": "Quality comparison used when promoting a fine-tuned embedding run.", + "properties": { + "allow_regression": { + "type": "boolean" + }, + "baseline_ndcg": { + "format": "double", + "type": "number" + }, + "tier": { + "type": "string" + }, + "trained_ndcg": { + "format": "double", + "type": "number" + } + }, + "required": [ + "tier", + "baseline_ndcg", + "trained_ndcg", + "allow_regression" + ], + "type": "object" + }, + "ManagedEmbeddingService": { + "description": "Service used to generate managed corpus and query embeddings.", + "enum": [ + "open_router", + "modal" + ], + "type": "string" + }, + "ManagedEmbeddingSource": { + "description": "Where a managed embedding model came from.", + "enum": [ + "stock", + "fine_tuned" + ], + "type": "string" + }, + "ModelArtifact": { + "properties": { + "blake3": { + "type": "string" + }, + "bytes": { "format": "int64", + "minimum": 0, "type": "integer" + }, + "key": { + "description": "Object key of the artifact (under the tenant prefix, so purge covers it).", + "type": "string" } }, "required": [ - "name", - "head" + "key", + "bytes", + "blake3" ], "type": "object" }, - "InferenceRunRequest": { - "description": "Run a set of inference rules to a bounded fixpoint and return the derived\nedges as a **preview**. Derived facts are never written: the write gate\nrefuses `origin=Derived`, so this surfaces \"what follows\" without mutating\nthe graph. Stratified persistence (`derived/v1`) is a separate path.", + "ModelCadenceResponse": { + "description": "`GET /v1/models/cadence` — the auto-index doubling policy applied to\nmodels: retraining is due when the graph has doubled since the promoted\nrun was trained (or when nothing was ever trained).", "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin: run inference over the graph as of this `commit_seq`, hiding\nlater commits. Errors if it exceeds the head.", + "commits_since_trained": { "format": "int64", "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "type": [ - "string", - "null" - ] + "type": "integer" }, - "max_derived": { - "description": "Fail-closed ceiling on total derived edges (clamped server-side).", + "current_run": { + "format": "int64", "minimum": 0, "type": [ "integer", "null" ] }, - "max_rounds": { - "description": "Fail-closed ceiling on fixpoint rounds (clamped server-side).", + "head_commit_seq": { + "format": "int64", "minimum": 0, - "type": [ - "integer", - "null" - ] + "type": "integer" }, - "max_solutions": { - "description": "Per-rule ceiling on the `body` join's solution set (clamped server-side).", + "kind": { + "type": "string" + }, + "retrain_due": { + "type": "boolean" + }, + "trained_at_commit_seq": { + "format": "int64", "minimum": 0, "type": [ "integer", "null" ] - }, - "rules": { + } + }, + "required": [ + "kind", + "head_commit_seq", + "commits_since_trained", + "retrain_due" + ], + "type": "object" + }, + "ModelCheckFile": { + "properties": { + "checks": { "items": { - "$ref": "#/components/schemas/InferenceRule" + "$ref": "#/components/schemas/ModelCheckSpec" }, "type": "array" } }, "required": [ - "rules" + "checks" ], "type": "object" }, - "InferenceRunResponse": { + "ModelCheckResponse": { "properties": { - "derived": { + "checks": { "items": { - "$ref": "#/components/schemas/DerivedEdgeView" + "$ref": "#/components/schemas/ModelCheckResult" }, "type": "array" }, - "rounds": { - "description": "Number of fixpoint rounds executed.", - "minimum": 0, - "type": "integer" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "truncated": { - "description": "True if a bound (rounds / derived edges / per-rule solutions) was hit, so\nthe derived set may be incomplete.", + "passed": { "type": "boolean" } }, "required": [ - "derived", - "snapshot", - "rounds", - "truncated" + "passed", + "checks" ], "type": "object" }, - "LbbErrorBody": { + "ModelCheckResult": { "properties": { - "code": { - "examples": [ - "missing_idempotency_key" - ], + "details": { "type": "string" }, - "doc_url": { - "type": [ - "string", - "null" - ] - }, - "message": { + "kind": { "type": "string" }, - "param": { - "type": [ - "string", - "null" - ] - }, - "request_id": { - "type": [ - "string", - "null" - ] - }, - "retry_after_seconds": { - "minimum": 0, - "type": "integer" - }, - "retryable": { + "passed": { "type": "boolean" - }, - "type": { - "examples": [ - "invalid_request_error" - ], - "type": "string" } }, "required": [ - "type", - "code", - "message", - "request_id", - "doc_url" - ], - "type": "object" - }, - "LbbErrorEnvelope": { - "properties": { - "error": { - "$ref": "#/components/schemas/LbbErrorBody" - } - }, - "required": [ - "error" + "kind", + "passed", + "details" ], "type": "object" }, - "ManagedEmbeddingBackfillJobProgress": { - "properties": { - "continuation": { - "type": [ - "string", - "null" - ] - }, - "embedded": { - "minimum": 0, - "type": "integer" - }, - "failed": { - "minimum": 0, - "type": "integer" - }, - "final_index_job_id": { - "type": [ - "string", - "null" - ] - }, - "heartbeat_micros": { - "format": "int64", - "type": "integer" - }, - "index_lineage": { - "oneOf": [ - { - "type": "null" + "ModelCheckSpec": { + "oneOf": [ + { + "properties": { + "entity": { + "$ref": "#/components/schemas/EntitySelector" }, - { - "$ref": "#/components/schemas/IndexLineage" + "expected_targets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "kind": { + "enum": [ + "neighbors" + ], + "type": "string" + }, + "relation": { + "type": [ + "string", + "null" + ] } - ] + }, + "required": [ + "entity", + "expected_targets", + "kind" + ], + "type": "object" }, - "missing": { - "minimum": 0, - "type": "integer" + { + "properties": { + "as_of_valid_time": { + "type": [ + "string", + "null" + ] + }, + "entity": { + "$ref": "#/components/schemas/EntitySelector" + }, + "expected_target": { + "type": "string" + }, + "kind": { + "enum": [ + "temporal_state" + ], + "type": "string" + }, + "relation": { + "type": "string" + } + }, + "required": [ + "entity", + "relation", + "expected_target", + "kind" + ], + "type": "object" }, - "processed": { + { + "properties": { + "from": { + "$ref": "#/components/schemas/EntitySelector" + }, + "kind": { + "enum": [ + "path" + ], + "type": "string" + }, + "max_hops": { + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "relations": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "should_exist": { + "type": "boolean" + }, + "to": { + "$ref": "#/components/schemas/EntitySelector" + } + }, + "required": [ + "from", + "to", + "max_hops", + "should_exist", + "kind" + ], + "type": "object" + } + ] + }, + "ModelDataLineage": { + "properties": { + "example_count": { + "format": "int64", "minimum": 0, "type": "integer" }, - "skipped": { + "signal_from_seq": { + "description": "Signal-bus range the training examples were drawn from (commit seqs).", + "format": "int64", "minimum": 0, "type": "integer" }, - "source_commit_seq": { + "signal_to_seq": { "format": "int64", "minimum": 0, "type": "integer" }, - "source_snapshot_token": { + "synthetic_fraction": { + "description": "Fraction of examples that were execution-verified synthetic pairs.", + "format": "float", + "type": "number" + } + }, + "required": [ + "signal_from_seq", + "signal_to_seq", + "example_count", + "synthetic_fraction" + ], + "type": "object" + }, + "ModelEval": { + "properties": { + "ledger_ref": { + "description": "Pointer into the quality/perf ledger row that gates promotion.", "type": "string" }, - "total": { - "minimum": 0, - "type": "integer" - }, - "worker": { - "type": [ - "string", - "null" - ] + "metrics": { + "additionalProperties": { + "format": "double", + "type": "number" + }, + "description": "Metric name → value (e.g. `ndcg10`).", + "propertyNames": { + "type": "string" + }, + "type": "object" } }, "required": [ - "total", - "processed", - "embedded", - "skipped", - "missing", - "failed", - "source_commit_seq", - "source_snapshot_token", - "heartbeat_micros" + "ledger_ref", + "metrics" ], "type": "object" }, - "ManagedEmbeddingBackfillJobRequest": { + "ModelRegistryResponse": { + "description": "`GET /v1/models/registry` — the runs of one kind, newest first.", "properties": { - "batch_size": { + "current": { + "description": "The promoted run number, when a `CURRENT` pointer exists.", + "format": "int64", "minimum": 0, "type": [ "integer", "null" ] }, - "full": { - "type": "boolean" + "kind": { + "type": "string" }, - "limit": { - "minimum": 0, - "type": [ - "integer", - "null" - ] + "runs": { + "items": { + "$ref": "#/components/schemas/ModelRunView" + }, + "type": "array" } }, + "required": [ + "kind", + "runs" + ], "type": "object" }, - "ManagedEmbeddingBackfillJobStatusResponse": { + "ModelRunManifest": { "properties": { - "attempts": { - "format": "int32", - "minimum": 0, - "type": "integer" + "artifacts": { + "items": { + "$ref": "#/components/schemas/ModelArtifact" + }, + "type": "array" }, - "enqueued_at_micros": { - "format": "int64", - "type": "integer" + "base_model": { + "description": "The base model this run derives from (e.g. `bge-small-en-v1.5`,\n`Qwen3-1.7B`); free-form but stable within a kind.", + "type": "string" }, - "graph": { - "$ref": "#/components/schemas/GraphKey" + "data_lineage": { + "$ref": "#/components/schemas/ModelDataLineage" }, - "idempotency_key": { - "type": "string" + "eval": { + "$ref": "#/components/schemas/ModelEval" }, - "job_id": { + "kind": { + "description": "One of [`MODEL_KINDS`].", "type": "string" }, - "parked": { - "description": "True when the job failed terminally because the provider rejected it for\nan account data-policy / configuration reason (a ZDR-ineligible model,\nauth, model-not-found) rather than a transient error — a *parked* job that\nwill not retry. The console renders this as a \"choose a different model\"\nblock instead of a retry. It clears when the embedding config version\nchanges, which mints a fresh reconciliation job.", + "promoted": { + "description": "Advisory at write time; promotion truth is the CAS `CURRENT` pointer.", "type": "boolean" }, - "progress": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobProgress" - } - ] + "recipe_id": { + "description": "The training/derivation recipe identifier (searchable; the flywheel\ndriver hill-climbs recipe space).", + "type": "string" }, - "result": { + "signature": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillResponse" + "$ref": "#/components/schemas/ModelSignature", + "description": "Reserved post-quantum signature envelope (SLH-DSA; ECC forbidden for\nthese artifacts). `null` until signing lands — the field exists from\nday one so signed and unsigned manifests share one schema." } ] }, - "status": { + "snapshot_token": { "type": "string" }, - "terminal_error": { + "source_job_id": { + "description": "Durable background job that produced this run. The server assigns this\nfrom the queue's stable job ID so redelivery returns the same run.", "type": [ "string", "null" ] }, - "updated_at_micros": { + "trained_at_commit_seq": { + "description": "The snapshot the run was derived from. Trainers MUST train on data\n≤ this commit and evaluate on > it (the temporal-split obligation);\nrecording it here is what lets audits verify the split.", "format": "int64", + "minimum": 0, + "type": "integer" + }, + "v": { + "description": "Manifest format version. Currently `1`.", + "format": "int32", + "minimum": 0, "type": "integer" } }, "required": [ - "job_id", - "status", - "graph", - "idempotency_key", - "attempts", - "enqueued_at_micros", - "updated_at_micros" + "v", + "kind", + "base_model", + "recipe_id", + "trained_at_commit_seq", + "snapshot_token", + "data_lineage", + "eval", + "artifacts", + "promoted" ], "type": "object" }, - "ManagedEmbeddingBackfillResponse": { - "description": "Outcome of embedding the corpus and rebuilding its Stored ANN index.", + "ModelRunView": { + "description": "One registry entry as reads report it: the manifest plus its run number\nand the *effective* promotion state (from the `CURRENT` pointer, not the\nmanifest's advisory flag).", "properties": { - "batches": { - "minimum": 0, - "type": "integer" - }, - "continuation": { - "type": [ - "string", - "null" - ] + "manifest": { + "$ref": "#/components/schemas/ModelRunManifest" }, - "embedded": { - "minimum": 0, - "type": "integer" + "promoted": { + "type": "boolean" }, - "entities_total": { + "run": { + "format": "int64", "minimum": 0, "type": "integer" + } + }, + "required": [ + "run", + "promoted", + "manifest" + ], + "type": "object" + }, + "ModelServingDefaults": { + "description": "The serving defaults derived from promoted model runs, pinned to the\nbranch head like the embedding config (`model_defaults_ref`). One object\nserves every in-process kind; promotion truth stays the registry's\n`CURRENT` pointer — this is its read-optimized projection. **[PIN]**\nfield names (persisted object).", + "properties": { + "calibration": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CalibrationServingDefaults" + } + ] }, - "failed": { - "minimum": 0, - "type": "integer" + "extractor": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/PlannerServingDefaults", + "description": "Extractor adapter serving default — same `{run, adapter}` shape as the\nplanner's (both are LoRA adapters on the resident model's volume);\nresident extraction passes it per generate call." + } + ] }, - "final_index_job_id": { - "type": [ - "string", - "null" + "fusion": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/FusionServingDefaults" + } ] }, - "index_lineage": { + "planner": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/IndexLineage" + "$ref": "#/components/schemas/PlannerServingDefaults" } ] }, - "indexed_commit_seq": { - "format": "int64", - "minimum": 0, - "type": "integer" + "suggest": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/SuggestServingDefaults" + } + ] }, - "missing": { + "v": { + "description": "Format version. Currently `1`.", + "format": "int32", "minimum": 0, "type": "integer" - }, - "model_id": { + } + }, + "required": [ + "v" + ], + "type": "object" + }, + "ModelSignature": { + "properties": { + "alg": { "type": "string" }, - "processed": { - "minimum": 0, - "type": "integer" - }, - "skipped": { - "minimum": 0, - "type": "integer" - }, - "source_commit_seq": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "source_snapshot_token": { + "key_id": { "type": "string" }, - "truncated": { - "type": "boolean" + "sig": { + "type": "string" } }, "required": [ - "entities_total", - "processed", - "embedded", - "skipped", - "missing", - "failed", - "batches", - "truncated", - "source_commit_seq", - "source_snapshot_token", - "indexed_commit_seq", - "model_id" + "alg", + "key_id", + "sig" ], "type": "object" }, - "ManagedEmbeddingConfig": { - "description": "The resolved, versioned managed embedding configuration.", + "ModelSplitAudit": { + "description": "`GET /v1/models/split-audit` — makes the WS9 temporal-split obligation\ncheckable: a trainer MUST train on data ≤ `trained_at_commit_seq` and\nevaluate on data > it; the manifest records the lineage window so this\naudit can verify it after the fact.", "properties": { - "auto_embed_query": { + "conforms": { "type": "boolean" }, - "base_model": { - "type": "string" - }, - "created_at_micros": { + "head_commit_seq": { "format": "int64", - "type": "integer" - }, - "dim": { - "format": "int32", "minimum": 0, "type": "integer" }, - "metric": { - "$ref": "#/components/schemas/VectorMetric" - }, - "model_id": { + "kind": { "type": "string" }, - "run_id": { - "type": [ - "string", - "null" - ] + "lineage_respects_split": { + "description": "The lineage window closes at or before the split pin\n(`signal_to_seq ≤ trained_at_commit_seq`).", + "type": "boolean" }, - "service": { - "$ref": "#/components/schemas/ManagedEmbeddingService" + "run": { + "format": "int64", + "minimum": 0, + "type": "integer" }, - "source": { - "$ref": "#/components/schemas/ManagedEmbeddingSource" + "split_within_history": { + "description": "The split pin lies within the graph's history (`≤ head`).", + "type": "boolean" }, - "version": { + "trained_at_commit_seq": { "format": "int64", "minimum": 0, "type": "integer" } }, "required": [ - "version", - "model_id", - "base_model", - "dim", - "metric", - "service", - "source", - "auto_embed_query", - "created_at_micros" - ], + "kind", + "run", + "trained_at_commit_seq", + "head_commit_seq", + "lineage_respects_split", + "split_within_history", + "conforms" + ], "type": "object" }, - "ManagedEmbeddingConfigRequest": { - "description": "Set the graph branch's default managed embedding model.", + "ModelTrainingConfig": { + "description": "Per-graph automatic-training configuration, stored as one small CAS\nobject under the branch prefix (purged with the tenant). **[PIN]** field\nnames. Default: off — training never starts without an explicit opt-in.", "properties": { - "auto_embed_query": { - "type": [ - "boolean", - "null" - ] + "auto_train": { + "description": "Master switch for cadence-triggered training. Off by default.", + "type": "boolean" }, - "base_model": { - "type": [ - "string", - "null" - ] + "kinds": { + "description": "Which [`TRAINABLE_KINDS`] the cadence loop may train. Empty with\n`auto_train: true` means \"all trainable kinds\".", + "items": { + "type": "string" + }, + "type": "array" }, - "dim": { - "description": "Vector width. Required for `modal`; optional for `open_router`, where a\none-text validation call discovers the model's native width.", + "v": { + "description": "Config format version. Currently `1`.", "format": "int32", "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "metric": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/VectorMetric" - } - ] - }, - "model_id": { - "type": "string" - }, - "run_id": { - "type": [ - "string", - "null" - ] - }, - "service": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingService" - } - ] - }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingSource" - } - ] + "type": "integer" } }, "required": [ - "model_id" + "v", + "auto_train" ], "type": "object" }, - "ManagedEmbeddingConfigResponse": { - "description": "Read/set response. Legacy hash-derived graphs return `configured=false` and no config.", + "NameSemantics": { + "description": "Whether entity names look like natural language (embeddings will carry) or\nopaque identifiers (a hash/lexical approach fits better).", "properties": { - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingConfig" - } - ] + "embeddable_pct": { + "format": "float", + "type": "number" }, - "configured": { - "type": "boolean" + "hash_like_pct": { + "format": "float", + "type": "number" }, - "reconciliation": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse", - "description": "Durable corpus reconciliation for the current config version. `Active`\nis truthful only after this job succeeds." - } - ] + "sampled": { + "description": "Entity names sampled for the heuristic.", + "minimum": 0, + "type": "integer" } }, "required": [ - "configured" + "embeddable_pct", + "hash_like_pct", + "sampled" ], "type": "object" }, - "ManagedEmbeddingModel": { - "description": "One model returned by the live managed-embedding service catalog.", + "NamedCount": { "properties": { - "context_length": { - "format": "int64", + "count": { "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "id": { - "type": "string" - }, - "input_modalities": { - "items": { - "type": "string" - }, - "type": "array" + "type": "integer" }, "name": { "type": "string" - }, - "output_modalities": { - "description": "The model's output modalities (e.g. `[\"embeddings\"]`). The catalog is\nfiltered to embedding models on this field, so every entry carries the\nembeddings modality; it is surfaced so clients (and the deploy smoke) can\nre-verify the catalog is embeddings-only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "policy_eligible": { - "description": "True when the model is eligible under the account's data policy — for the\nhosted OpenRouter path, that it has a Zero-Data-Retention route. The\ncatalog only returns eligible models, so this is `true` for every entry\ntoday; the console can trust it to gate selection if ineligible models are\never surfaced alongside them.", - "type": "boolean" - }, - "prompt_price": { - "description": "Provider prompt price as a decimal USD/token string when advertised.", + } + }, + "required": [ + "name", + "count" + ], + "type": "object" + }, + "NamedEntityInput": { + "properties": { + "key": { + "description": "Optional stable external key. When set, entity identity is `(type, key)`\nand `name` is just a display label — so a later rename keeps the same\nentity, and two records that share a name stay distinct by key (e.g. two\n\"Cambridge\" universities in a relational import). Omit it to keep the\ndefault `(type, name)` identity. To attach properties or embeddings to a\nkeyed entity, set the same `key` on those inputs.", "type": [ "string", "null" ] + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" } }, "required": [ - "id", + "type", "name" ], "type": "object" }, - "ManagedEmbeddingModelsResponse": { - "description": "Live embedding models available on this deployment.", + "NarrowRelationOp": { + "description": "Remove entity types from a relation's domain and/or range (a subtractive\nchange). Conflicts when current edges of the relation already use a\nremoved source/target type — those edges stay (append-only) but begin to\nwarn. Blocked unless `allow_data_conflicts` is set on the request.", "properties": { - "configured": { - "type": "boolean" + "op": { + "enum": [ + "narrow_relation" + ], + "type": "string" }, - "models": { + "relation": { + "type": "string" + }, + "remove_domain": { "items": { - "$ref": "#/components/schemas/ManagedEmbeddingModel" + "type": "string" }, "type": "array" }, - "service": { - "$ref": "#/components/schemas/ManagedEmbeddingService" + "remove_range": { + "items": { + "type": "string" + }, + "type": "array" } }, "required": [ - "service", - "configured" + "relation", + "op" ], "type": "object" }, - "ManagedEmbeddingPromoteResponse": { - "description": "Response after promoting a finished training run to the graph default.", + "NarrowingRecall": { + "description": "Whether the graph's own entities are retrievable by their names — a proxy\nfor \"will narrowing/retrieval carry\". Computed by self-querying a sample and\nchecking top-10 membership; no LLM.", "properties": { - "config": { - "$ref": "#/components/schemas/ManagedEmbeddingConfig" - }, - "configured": { - "type": "boolean" - }, - "evals": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ManagedEmbeddingPromotionEvals" - } - ] - }, - "promoted_run": { - "type": "string" + "n": { + "minimum": 0, + "type": "integer" }, - "registry": {} + "recall_at_10": { + "format": "float", + "type": "number" + } }, "required": [ - "promoted_run", - "configured", - "config" + "recall_at_10", + "n" ], "type": "object" }, - "ManagedEmbeddingPromotionEvals": { - "description": "Quality comparison used when promoting a fine-tuned embedding run.", + "NeighborResponse": { "properties": { - "allow_regression": { - "type": "boolean" - }, - "baseline_ndcg": { - "format": "double", - "type": "number" + "entity": { + "$ref": "#/components/schemas/EntityView" }, - "tier": { - "type": "string" + "neighbors": { + "items": { + "$ref": "#/components/schemas/TripletView" + }, + "type": "array" }, - "trained_ndcg": { - "format": "double", - "type": "number" + "snapshot": { + "$ref": "#/components/schemas/SnapshotView" } }, "required": [ - "tier", - "baseline_ndcg", - "trained_ndcg", - "allow_regression" + "entity", + "neighbors", + "snapshot" ], "type": "object" }, - "ManagedEmbeddingService": { - "description": "Service used to generate managed corpus and query embeddings.", - "enum": [ - "open_router", - "modal" - ], - "type": "string" - }, - "ManagedEmbeddingSource": { - "description": "Where a managed embedding model came from.", - "enum": [ - "stock", - "fine_tuned" - ], - "type": "string" - }, - "ModelArtifact": { + "NeighborhoodEdge": { + "description": "One current-edge projection touching the queried entity, materialized from\nthe entity's own adjacency slice (peer stub + relation + valid time). Unlike\n`StateEntry`/`TripletView` it carries no `previous`/`evidence`/single\n`edge_event_id`, because the ranged adjacency run does not store them — so\nthe ranged and snapshot code paths produce identical edges.", "properties": { - "blake3": { - "type": "string" + "confidence": { + "format": "float", + "type": "number" }, - "bytes": { - "format": "int64", - "minimum": 0, - "type": "integer" + "derived_from": { + "items": { + "$ref": "#/components/schemas/EdgeEventId" + }, + "type": "array" }, - "key": { - "description": "Object key of the artifact (under the tenant prefix, so purge covers it).", - "type": "string" + "peer": { + "$ref": "#/components/schemas/EntityView" + }, + "relation": { + "$ref": "#/components/schemas/RelationView" + }, + "valid_time": { + "$ref": "#/components/schemas/ValidTime" } }, "required": [ - "key", - "bytes", - "blake3" + "relation", + "peer", + "confidence", + "valid_time", + "derived_from" ], "type": "object" }, - "ModelCadenceResponse": { - "description": "`GET /v1/models/cadence` — the auto-index doubling policy applied to\nmodels: retraining is due when the graph has doubled since the promoted\nrun was trained (or when nothing was ever trained).", + "ObservationId": { + "type": "string" + }, + "ObservationRow": { "properties": { - "commits_since_trained": { + "created_at_commit": { "format": "int64", "minimum": 0, "type": "integer" }, - "current_run": { - "format": "int64", + "extracted_edge_event_count": { "minimum": 0, - "type": [ - "integer", - "null" - ] + "type": "integer" }, - "head_commit_seq": { - "format": "int64", + "extracted_entity_count": { "minimum": 0, "type": "integer" }, - "kind": { + "id": { + "$ref": "#/components/schemas/ObservationId" + }, + "observation_type": { "type": "string" }, - "retrain_due": { - "type": "boolean" + "source_id": { + "type": "string" }, - "trained_at_commit_seq": { - "format": "int64", - "minimum": 0, + "text": { "type": [ - "integer", + "string", + "null" + ] + }, + "text_preview": { + "type": [ + "string", "null" ] } }, "required": [ - "kind", - "head_commit_seq", - "commits_since_trained", - "retrain_due" + "id", + "observation_type", + "source_id", + "created_at_commit", + "extracted_entity_count", + "extracted_edge_event_count" ], "type": "object" }, - "ModelCheckFile": { + "ObserveByoFact": { + "description": "A caller-extracted candidate fact (`extraction.byo_completion`).", "properties": { - "checks": { + "confidence": { + "format": "float", + "type": "number" + }, + "fact": { + "description": "Natural-language statement of the fact.", + "type": "string" + }, + "triplet": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TripletInput", + "description": "The structured form. Required for the fact to be committable — a bare\nstatement without structure is answered `needs_review` (structuring\nfree text is the resident extractor's job)." + } + ] + } + }, + "required": [ + "fact" + ], + "type": "object" + }, + "ObserveEpisode": { + "description": "The raw conversation slice to remember. Ground truth — stored verbatim on\nthe main branch as an `EPISODE` evidence entity.", + "properties": { + "session_id": { + "description": "Caller's conversation id (opaque; drives the default branch name).", + "type": "string" + }, + "source": { + "description": "Optional source label, e.g. `support-bot`.", + "type": [ + "string", + "null" + ] + }, + "turns": { + "description": "1..=500 turns, <= 1 MiB of content in total.", "items": { - "$ref": "#/components/schemas/ModelCheckSpec" + "$ref": "#/components/schemas/ObserveTurn" }, "type": "array" } }, "required": [ - "checks" + "turns", + "session_id" ], "type": "object" }, - "ModelCheckResponse": { + "ObserveExtraction": { "properties": { - "checks": { + "byo_completion": { + "description": "Caller-side extraction: skip the model, run anchoring / supersedure /\ngating only.", "items": { - "$ref": "#/components/schemas/ModelCheckResult" + "$ref": "#/components/schemas/ObserveByoFact" }, "type": "array" }, - "passed": { - "type": "boolean" + "max_facts": { + "description": "Cap on extracted facts (clamped to 32).", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "model": { + "description": "`byo` | `resident`. Defaults to `resident` when the server has a\nplanner endpoint configured, else `byo`.", + "type": [ + "string", + "null" + ] } }, - "required": [ - "passed", - "checks" - ], "type": "object" }, - "ModelCheckResult": { + "ObserveFact": { + "description": "Per-fact outcome. `status`: `committed` | `rejected` | `needs_review`.", "properties": { - "details": { + "anchored": { + "description": "Both endpoints resolved to entities that already existed.", + "type": "boolean" + }, + "confidence": { + "format": "float", + "type": "number" + }, + "statement": { "type": "string" }, - "kind": { + "status": { "type": "string" }, - "passed": { - "type": "boolean" + "supersedes": { + "description": "The current edge this fact displaces (commit-ordered reducers only).", + "type": [ + "string", + "null" + ] + }, + "triplet": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TripletInput" + } + ] } }, "required": [ - "kind", - "passed", - "details" + "statement", + "anchored", + "confidence", + "status" ], "type": "object" }, - "ModelCheckSpec": { - "oneOf": [ - { - "properties": { - "entity": { - "$ref": "#/components/schemas/EntitySelector" - }, - "expected_targets": { - "items": { - "type": "string" - }, - "type": "array" - }, - "kind": { - "enum": [ - "neighbors" - ], - "type": "string" - }, - "relation": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "entity", - "expected_targets", - "kind" - ], - "type": "object" - }, - { - "properties": { - "as_of_valid_time": { - "type": [ - "string", - "null" - ] - }, - "entity": { - "$ref": "#/components/schemas/EntitySelector" - }, - "expected_target": { - "type": "string" - }, - "kind": { - "enum": [ - "temporal_state" - ], - "type": "string" - }, - "relation": { - "type": "string" - } - }, - "required": [ - "entity", - "relation", - "expected_target", - "kind" - ], - "type": "object" - }, - { - "properties": { - "from": { - "$ref": "#/components/schemas/EntitySelector" - }, - "kind": { - "enum": [ - "path" - ], - "type": "string" - }, - "max_hops": { - "format": "int32", - "minimum": 0, - "type": "integer" - }, - "relations": { - "items": { - "type": "string" - }, - "type": [ - "array", - "null" - ] - }, - "should_exist": { - "type": "boolean" - }, - "to": { - "$ref": "#/components/schemas/EntitySelector" - } - }, - "required": [ - "from", - "to", - "max_hops", - "should_exist", - "kind" - ], - "type": "object" - } - ] - }, - "ModelDataLineage": { + "ObserveRequest": { "properties": { - "example_count": { - "format": "int64", - "minimum": 0, - "type": "integer" + "auto_merge": { + "description": "Merge the branch back onto the scoped branch when validation is clean\n(the WS16 validate-then-merge).", + "type": "boolean" }, - "signal_from_seq": { - "description": "Signal-bus range the training examples were drawn from (commit seqs).", - "format": "int64", - "minimum": 0, - "type": "integer" + "branch": { + "description": "Branch the facts commit to. Defaults to `observe-`\n(branch names are `[a-z0-9-_]{1,32}`, so the session id is hashed, not\nembedded). Created from the scoped branch if absent.", + "type": [ + "string", + "null" + ] }, - "signal_to_seq": { - "format": "int64", - "minimum": 0, - "type": "integer" + "episode": { + "$ref": "#/components/schemas/ObserveEpisode" }, - "synthetic_fraction": { - "description": "Fraction of examples that were execution-verified synthetic pairs.", - "format": "float", - "type": "number" - } - }, - "required": [ - "signal_from_seq", - "signal_to_seq", - "example_count", - "synthetic_fraction" - ], - "type": "object" - }, - "ModelEval": { - "properties": { - "ledger_ref": { - "description": "Pointer into the quality/perf ledger row that gates promotion.", - "type": "string" + "extract": { + "description": "`false` stores the episode only (no facts, no branch).", + "type": "boolean" }, - "metrics": { - "additionalProperties": { - "format": "double", - "type": "number" - }, - "description": "Metric name → value (e.g. `ndcg10`).", - "propertyNames": { - "type": "string" - }, - "type": "object" + "extraction": { + "$ref": "#/components/schemas/ObserveExtraction" } }, "required": [ - "ledger_ref", - "metrics" + "episode" ], "type": "object" }, - "ModelRegistryResponse": { - "description": "`GET /v1/models/registry` — the runs of one kind, newest first.", + "ObserveResponse": { "properties": { - "current": { - "description": "The promoted run number, when a `CURRENT` pointer exists.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] + "branch": { + "description": "The branch the facts committed to (empty when `extract: false`).", + "type": "string" }, - "kind": { + "episode_id": { + "description": "Stable entity id of the stored `EPISODE` evidence entity.", "type": "string" }, - "runs": { - "items": { - "$ref": "#/components/schemas/ModelRunView" - }, - "type": "array" - } - }, - "required": [ - "kind", - "runs" - ], - "type": "object" - }, - "ModelRunManifest": { - "properties": { - "artifacts": { + "facts": { "items": { - "$ref": "#/components/schemas/ModelArtifact" + "$ref": "#/components/schemas/ObserveFact" }, "type": "array" }, - "base_model": { - "description": "The base model this run derives from (e.g. `bge-small-en-v1.5`,\n`Qwen3-1.7B`); free-form but stable within a kind.", - "type": "string" - }, - "data_lineage": { - "$ref": "#/components/schemas/ModelDataLineage" - }, - "eval": { - "$ref": "#/components/schemas/ModelEval" - }, - "kind": { - "description": "One of [`MODEL_KINDS`].", - "type": "string" + "idempotent_replay": { + "description": "True when this Idempotency-Key was already applied (episode replayed).", + "type": "boolean" }, - "promoted": { - "description": "Advisory at write time; promotion truth is the CAS `CURRENT` pointer.", + "merged": { "type": "boolean" }, - "recipe_id": { - "description": "The training/derivation recipe identifier (searchable; the flywheel\ndriver hill-climbs recipe space).", - "type": "string" + "snapshot": { + "$ref": "#/components/schemas/SnapshotView", + "description": "The scoped (main) branch snapshot after the observe." }, - "signature": { + "validation": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/ModelSignature", - "description": "Reserved post-quantum signature envelope (SLH-DSA; ECC forbidden for\nthese artifacts). `null` until signing lands — the field exists from\nday one so signed and unsigned manifests share one schema." + "$ref": "#/components/schemas/SchemaAuditReport", + "description": "SHACL audit of the branch commit (present when shapes are active)." } ] - }, - "snapshot_token": { - "type": "string" - }, - "source_job_id": { - "description": "Durable background job that produced this run. The server assigns this\nfrom the queue's stable job ID so redelivery returns the same run.", - "type": [ - "string", - "null" - ] - }, - "trained_at_commit_seq": { - "description": "The snapshot the run was derived from. Trainers MUST train on data\n≤ this commit and evaluate on > it (the temporal-split obligation);\nrecording it here is what lets audits verify the split.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "v": { - "description": "Manifest format version. Currently `1`.", - "format": "int32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "v", - "kind", - "base_model", - "recipe_id", - "trained_at_commit_seq", - "snapshot_token", - "data_lineage", - "eval", - "artifacts", - "promoted" - ], - "type": "object" - }, - "ModelRunView": { - "description": "One registry entry as reads report it: the manifest plus its run number\nand the *effective* promotion state (from the `CURRENT` pointer, not the\nmanifest's advisory flag).", - "properties": { - "manifest": { - "$ref": "#/components/schemas/ModelRunManifest" - }, - "promoted": { - "type": "boolean" - }, - "run": { - "format": "int64", - "minimum": 0, - "type": "integer" } }, "required": [ - "run", - "promoted", - "manifest" + "episode_id", + "branch", + "merged", + "snapshot" ], "type": "object" }, - "ModelServingDefaults": { - "description": "The serving defaults derived from promoted model runs, pinned to the\nbranch head like the embedding config (`model_defaults_ref`). One object\nserves every in-process kind; promotion truth stays the registry's\n`CURRENT` pointer — this is its read-optimized projection. **[PIN]**\nfield names (persisted object).", + "ObserveTurn": { + "description": "One conversation turn of an episode.", "properties": { - "calibration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CalibrationServingDefaults" - } - ] - }, - "extractor": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PlannerServingDefaults", - "description": "Extractor adapter serving default — same `{run, adapter}` shape as the\nplanner's (both are LoRA adapters on the resident model's volume);\nresident extraction passes it per generate call." - } - ] + "content": { + "type": "string" }, - "fusion": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FusionServingDefaults" - } + "name": { + "description": "Optional speaker/tool name.", + "type": [ + "string", + "null" ] }, - "planner": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PlannerServingDefaults" - } - ] + "role": { + "description": "`user` | `assistant` | `tool` (free-form label; not enforced).", + "type": "string" }, - "suggest": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SuggestServingDefaults" - } + "ts": { + "description": "Optional RFC 3339 timestamp of the turn.", + "type": [ + "string", + "null" ] - }, - "v": { - "description": "Format version. Currently `1`.", - "format": "int32", - "minimum": 0, - "type": "integer" } }, "required": [ - "v" + "role", + "content" ], "type": "object" }, - "ModelSignature": { + "OntologyCompetencyQuestion": { "properties": { - "alg": { - "type": "string" - }, - "key_id": { + "id": { "type": "string" }, - "sig": { + "question": { "type": "string" } }, "required": [ - "alg", - "key_id", - "sig" + "id", + "question" ], "type": "object" }, - "ModelSplitAudit": { - "description": "`GET /v1/models/split-audit` — makes the WS9 temporal-split obligation\ncheckable: a trainer MUST train on data ≤ `trained_at_commit_seq` and\nevaluate on data > it; the manifest records the lineage window so this\naudit can verify it after the fact.", + "OntologyConflict": { + "description": "A current-data conflict found while previewing a subtractive ontology change.\nReported back so the caller can decide whether to re-run with\n`allow_data_conflicts` (which keeps the affected records — Little Big Brain never\nrewrites or drops them — and applies the change in warn mode).", "properties": { - "conforms": { - "type": "boolean" - }, - "head_commit_seq": { + "affected": { + "description": "How many current records the change would orphan/flag.", "format": "int64", "minimum": 0, "type": "integer" }, "kind": { + "description": "`entities_of_removed_type` | `edges_of_removed_relation` |\n`edges_outside_narrowed_domain` | `edges_outside_narrowed_range`.", "type": "string" }, - "lineage_respects_split": { - "description": "The lineage window closes at or before the split pin\n(`signal_to_seq ≤ trained_at_commit_seq`).", - "type": "boolean" - }, - "run": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "split_within_history": { - "description": "The split pin lies within the graph's history (`≤ head`).", - "type": "boolean" + "message": { + "type": "string" }, - "trained_at_commit_seq": { - "format": "int64", - "minimum": 0, - "type": "integer" + "subject": { + "description": "`class:` or `relation:` the conflict is about.", + "type": "string" } }, "required": [ + "subject", "kind", - "run", - "trained_at_commit_seq", - "head_commit_seq", - "lineage_respects_split", - "split_within_history", - "conforms" + "affected", + "message" ], "type": "object" }, - "ModelTrainingConfig": { - "description": "Per-graph automatic-training configuration, stored as one small CAS\nobject under the branch prefix (purged with the tenant). **[PIN]** field\nnames. Default: off — training never starts without an explicit opt-in.", + "OntologyCqAnalysis": { "properties": { - "auto_train": { - "description": "Master switch for cadence-triggered training. Off by default.", + "covered": { "type": "boolean" }, - "kinds": { - "description": "Which [`TRAINABLE_KINDS`] the cadence loop may train. Empty with\n`auto_train: true` means \"all trainable kinds\".", + "id": { + "type": "string" + }, + "interpretation": { + "type": "string" + }, + "object": { + "type": "string" + }, + "predicate": { + "type": "string" + }, + "query_outline": { + "type": "string" + }, + "required_elements": { "items": { "type": "string" }, "type": "array" }, - "v": { - "description": "Config format version. Currently `1`.", - "format": "int32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "v", - "auto_train" - ], - "type": "object" - }, - "NameSemantics": { - "description": "Whether entity names look like natural language (embeddings will carry) or\nopaque identifiers (a hash/lexical approach fits better).", - "properties": { - "embeddable_pct": { - "format": "float", - "type": "number" - }, - "hash_like_pct": { - "format": "float", - "type": "number" - }, - "sampled": { - "description": "Entity names sampled for the heuristic.", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "embeddable_pct", - "hash_like_pct", - "sampled" - ], - "type": "object" - }, - "NamedCount": { - "properties": { - "count": { - "minimum": 0, - "type": "integer" + "selected_pattern": { + "type": [ + "string", + "null" + ] }, - "name": { + "subject": { "type": "string" } }, "required": [ - "name", - "count" + "id", + "interpretation", + "subject", + "predicate", + "object", + "required_elements", + "query_outline", + "covered" ], "type": "object" }, - "NamedEntityInput": { + "OntologyDefineRequest": { + "description": "Define a custom ontology for the scoped graph before its first commit.\nImports `source` (any [`crate`]-supported format), optionally merges the\nbuilt-in default so the standard entity types/relations stay available, and\ncreates the graph head with the result. Fails if the graph already exists.", "properties": { - "key": { - "description": "Optional stable external key. When set, entity identity is `(type, key)`\nand `name` is just a display label — so a later rename keeps the same\nentity, and two records that share a name stay distinct by key (e.g. two\n\"Cambridge\" universities in a relational import). Omit it to keep the\ndefault `(type, name)` identity. To attach properties or embeddings to a\nkeyed entity, set the same `key` on those inputs.", + "format": { + "description": "Import format hint. `auto` (the default) sniffs the content.", "type": [ "string", "null" ] }, - "name": { - "type": "string" + "merge_default": { + "description": "Merge the built-in `default_ai_context_ontology()` underneath the\nimported types so the standard AI-context vocabulary stays available.", + "type": "boolean" }, - "type": { + "source": { + "description": "Ontology document text: Little Big Brain JSON, JSON-LD, Turtle/N3, RDF/XML, or\nCSV/TSV. Detected from `format` (default `auto`).", "type": "string" } }, "required": [ - "type", - "name" + "source" ], "type": "object" }, - "NarrowRelationOp": { - "description": "Remove entity types from a relation's domain and/or range (a subtractive\nchange). Conflicts when current edges of the relation already use a\nremoved source/target type — those edges stay (append-only) but begin to\nwarn. Blocked unless `allow_data_conflicts` is set on the request.", - "properties": { - "op": { - "enum": [ - "narrow_relation" - ], - "type": "string" - }, - "relation": { - "type": "string" - }, - "remove_domain": { - "items": { - "type": "string" - }, - "type": "array" - }, - "remove_range": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "relation", - "op" - ], - "type": "object" - }, - "NarrowingRecall": { - "description": "Whether the graph's own entities are retrievable by their names — a proxy\nfor \"will narrowing/retrieval carry\". Computed by self-querying a sample and\nchecking top-10 membership; no LLM.", - "properties": { - "n": { - "minimum": 0, - "type": "integer" - }, - "recall_at_10": { - "format": "float", - "type": "number" - } - }, - "required": [ - "recall_at_10", - "n" - ], - "type": "object" - }, - "NeighborResponse": { - "properties": { - "entity": { - "$ref": "#/components/schemas/EntityView" - }, - "neighbors": { - "items": { - "$ref": "#/components/schemas/TripletView" - }, - "type": "array" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - } - }, - "required": [ - "entity", - "neighbors", - "snapshot" - ], - "type": "object" - }, - "NeighborhoodEdge": { - "description": "One current-edge projection touching the queried entity, materialized from\nthe entity's own adjacency slice (peer stub + relation + valid time). Unlike\n`StateEntry`/`TripletView` it carries no `previous`/`evidence`/single\n`edge_event_id`, because the ranged adjacency run does not store them — so\nthe ranged and snapshot code paths produce identical edges.", - "properties": { - "confidence": { - "format": "float", - "type": "number" - }, - "derived_from": { - "items": { - "$ref": "#/components/schemas/EdgeEventId" - }, - "type": "array" - }, - "peer": { - "$ref": "#/components/schemas/EntityView" - }, - "relation": { - "$ref": "#/components/schemas/RelationView" - }, - "valid_time": { - "$ref": "#/components/schemas/ValidTime" - } - }, - "required": [ - "relation", - "peer", - "confidence", - "valid_time", - "derived_from" - ], - "type": "object" - }, - "ObservationId": { - "type": "string" - }, - "ObservationRow": { - "properties": { - "created_at_commit": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "extracted_edge_event_count": { - "minimum": 0, - "type": "integer" - }, - "extracted_entity_count": { - "minimum": 0, - "type": "integer" - }, - "id": { - "$ref": "#/components/schemas/ObservationId" - }, - "observation_type": { - "type": "string" - }, - "source_id": { - "type": "string" - }, - "text": { - "type": [ - "string", - "null" - ] - }, - "text_preview": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "id", - "observation_type", - "source_id", - "created_at_commit", - "extracted_entity_count", - "extracted_edge_event_count" - ], - "type": "object" - }, - "ObserveByoFact": { - "description": "A caller-extracted candidate fact (`extraction.byo_completion`).", - "properties": { - "confidence": { - "format": "float", - "type": "number" - }, - "fact": { - "description": "Natural-language statement of the fact.", - "type": "string" - }, - "triplet": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TripletInput", - "description": "The structured form. Required for the fact to be committable — a bare\nstatement without structure is answered `needs_review` (structuring\nfree text is the resident extractor's job)." - } - ] - } - }, - "required": [ - "fact" - ], - "type": "object" - }, - "ObserveEpisode": { - "description": "The raw conversation slice to remember. Ground truth — stored verbatim on\nthe main branch as an `EPISODE` evidence entity.", - "properties": { - "session_id": { - "description": "Caller's conversation id (opaque; drives the default branch name).", - "type": "string" - }, - "source": { - "description": "Optional source label, e.g. `support-bot`.", - "type": [ - "string", - "null" - ] - }, - "turns": { - "description": "1..=500 turns, <= 1 MiB of content in total.", - "items": { - "$ref": "#/components/schemas/ObserveTurn" - }, - "type": "array" - } - }, - "required": [ - "turns", - "session_id" - ], - "type": "object" - }, - "ObserveExtraction": { - "properties": { - "byo_completion": { - "description": "Caller-side extraction: skip the model, run anchoring / supersedure /\ngating only.", - "items": { - "$ref": "#/components/schemas/ObserveByoFact" - }, - "type": "array" - }, - "max_facts": { - "description": "Cap on extracted facts (clamped to 32).", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "model": { - "description": "`byo` | `resident`. Defaults to `resident` when the server has a\nplanner endpoint configured, else `byo`.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "ObserveFact": { - "description": "Per-fact outcome. `status`: `committed` | `rejected` | `needs_review`.", - "properties": { - "anchored": { - "description": "Both endpoints resolved to entities that already existed.", - "type": "boolean" - }, - "confidence": { - "format": "float", - "type": "number" - }, - "statement": { - "type": "string" - }, - "status": { - "type": "string" - }, - "supersedes": { - "description": "The current edge this fact displaces (commit-ordered reducers only).", - "type": [ - "string", - "null" - ] - }, - "triplet": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TripletInput" - } - ] - } - }, - "required": [ - "statement", - "anchored", - "confidence", - "status" - ], - "type": "object" - }, - "ObserveRequest": { - "properties": { - "auto_merge": { - "description": "Merge the branch back onto the scoped branch when validation is clean\n(the WS16 validate-then-merge).", - "type": "boolean" - }, - "branch": { - "description": "Branch the facts commit to. Defaults to `observe-`\n(branch names are `[a-z0-9-_]{1,32}`, so the session id is hashed, not\nembedded). Created from the scoped branch if absent.", - "type": [ - "string", - "null" - ] - }, - "episode": { - "$ref": "#/components/schemas/ObserveEpisode" - }, - "extract": { - "description": "`false` stores the episode only (no facts, no branch).", - "type": "boolean" - }, - "extraction": { - "$ref": "#/components/schemas/ObserveExtraction" - } - }, - "required": [ - "episode" - ], - "type": "object" - }, - "ObserveResponse": { - "properties": { - "branch": { - "description": "The branch the facts committed to (empty when `extract: false`).", - "type": "string" - }, - "episode_id": { - "description": "Stable entity id of the stored `EPISODE` evidence entity.", - "type": "string" - }, - "facts": { - "items": { - "$ref": "#/components/schemas/ObserveFact" - }, - "type": "array" - }, - "idempotent_replay": { - "description": "True when this Idempotency-Key was already applied (episode replayed).", - "type": "boolean" - }, - "merged": { - "type": "boolean" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView", - "description": "The scoped (main) branch snapshot after the observe." - }, - "validation": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SchemaAuditReport", - "description": "SHACL audit of the branch commit (present when shapes are active)." - } - ] - } - }, - "required": [ - "episode_id", - "branch", - "merged", - "snapshot" - ], - "type": "object" - }, - "ObserveTurn": { - "description": "One conversation turn of an episode.", - "properties": { - "content": { - "type": "string" - }, - "name": { - "description": "Optional speaker/tool name.", - "type": [ - "string", - "null" - ] - }, - "role": { - "description": "`user` | `assistant` | `tool` (free-form label; not enforced).", - "type": "string" - }, - "ts": { - "description": "Optional RFC 3339 timestamp of the turn.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "role", - "content" - ], - "type": "object" - }, - "OntologyCompetencyQuestion": { - "properties": { - "id": { - "type": "string" - }, - "question": { - "type": "string" - } - }, - "required": [ - "id", - "question" - ], - "type": "object" - }, - "OntologyConflict": { - "description": "A current-data conflict found while previewing a subtractive ontology change.\nReported back so the caller can decide whether to re-run with\n`allow_data_conflicts` (which keeps the affected records — Little Big Brain never\nrewrites or drops them — and applies the change in warn mode).", - "properties": { - "affected": { - "description": "How many current records the change would orphan/flag.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "kind": { - "description": "`entities_of_removed_type` | `edges_of_removed_relation` |\n`edges_outside_narrowed_domain` | `edges_outside_narrowed_range`.", - "type": "string" - }, - "message": { - "type": "string" - }, - "subject": { - "description": "`class:` or `relation:` the conflict is about.", - "type": "string" - } - }, - "required": [ - "subject", - "kind", - "affected", - "message" - ], - "type": "object" - }, - "OntologyCqAnalysis": { - "properties": { - "covered": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "interpretation": { - "type": "string" - }, - "object": { - "type": "string" - }, - "predicate": { - "type": "string" - }, - "query_outline": { - "type": "string" - }, - "required_elements": { - "items": { - "type": "string" - }, - "type": "array" - }, - "selected_pattern": { - "type": [ - "string", - "null" - ] - }, - "subject": { - "type": "string" - } - }, - "required": [ - "id", - "interpretation", - "subject", - "predicate", - "object", - "required_elements", - "query_outline", - "covered" - ], - "type": "object" - }, - "OntologyDefineRequest": { - "description": "Define a custom ontology for the scoped graph before its first commit.\nImports `source` (any [`crate`]-supported format), optionally merges the\nbuilt-in default so the standard entity types/relations stay available, and\ncreates the graph head with the result. Fails if the graph already exists.", - "properties": { - "format": { - "description": "Import format hint. `auto` (the default) sniffs the content.", - "type": [ - "string", - "null" - ] - }, - "merge_default": { - "description": "Merge the built-in `default_ai_context_ontology()` underneath the\nimported types so the standard AI-context vocabulary stays available.", - "type": "boolean" - }, - "source": { - "description": "Ontology document text: Little Big Brain JSON, JSON-LD, Turtle/N3, RDF/XML, or\nCSV/TSV. Detected from `format` (default `auto`).", - "type": "string" - } - }, - "required": [ - "source" - ], - "type": "object" - }, - "OntologyDefineResponse": { + "OntologyDefineResponse": { "properties": { "entity_types": { "items": { @@ -10033,7 +8628,7 @@ "type": "object" }, "PlannerServingDefaults": { - "description": "Planner serving default derived from a promoted `planner` run: the LoRA\nadapter (a path on the model-serving volume) `/v1/ask` passes to the\nresident planner endpoint per generate call.", + "description": "Planner serving default derived from a promoted `planner` run: the LoRA\nadapter (a path on the model-serving volume) planner-backed workflows pass\nto the resident model per generate call.", "properties": { "adapter": { "description": "Adapter path on the serving volume (the run manifest's artifact key).", @@ -10200,63 +8795,199 @@ } ] }, - "ProvenanceLeafView": { - "description": "One leaf of a derived edge's provenance trail. A tagged union so a calibrated\nretrieval match can never be mistaken for an asserted fact\n(FAL-PROV-NOT-LAUNDERED): the two variants are distinct on the wire, and only\nthe rule engine emits `Asserted` while only the retrieval-premise producer\nemits `Retrieval`.", - "oneOf": [ - { - "description": "An asserted edge event this fact transitively rests on (hex id).", - "properties": { - "edge_event_id": { - "type": "string" - }, - "kind": { - "enum": [ - "asserted" - ], - "type": "string" - } - }, - "required": [ - "edge_event_id", - "kind" - ], - "type": "object" + "PublishedGenerationEnqueueDisposition": { + "description": "Whether an import's deterministic published-generation job was newly\nqueued or coalesced with equivalent pending work.", + "enum": [ + "queued", + "coalesced" + ], + "type": "string" + }, + "PublishedReadConformanceView": { + "description": "Published conformance provenance. `validated_at_seq` may trail the common\nquery watermark while the next durable validation is running.", + "properties": { + "artifact_format_version": { + "format": "int32", + "minimum": 0, + "type": "integer" }, - { - "description": "A calibrated retrieval match that *seeded* this fact — never an asserted\nleaf. Carries the embedding space it came from, the matched entity, and\nthe calibrated `P(relevant)` used as the premise confidence.", - "properties": { - "calibrated_score": { - "description": "Calibrated `P(relevant)` used as the premise confidence.", - "format": "float", - "type": "number" - }, - "kind": { - "enum": [ - "retrieval" - ], - "type": "string" - }, - "matched": { - "description": "Matched entity id (hex).", - "type": "string" - }, - "model_id": { - "type": "string" + "ontology_version": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "shapes_version": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "validated_at_seq": { + "$ref": "#/components/schemas/CommitSeq" + } + }, + "required": [ + "artifact_format_version", + "validated_at_seq", + "ontology_version" + ], + "type": "object" + }, + "PublishedReadFamilyView": { + "description": "One family present in an atomic published root. Object keys and ETags stay\ninternal; this is the bounded operational/API projection.", + "properties": { + "family": { + "$ref": "#/components/schemas/IndexVisibilityFamily" + }, + "model_hash": { + "type": [ + "string", + "null" + ] + }, + "root_format_version": { + "description": "That family's persisted root-codec version.", + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "target_hash": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "family", + "root_format_version" + ], + "type": "object" + }, + "PublishedReadSnapshotView": { + "description": "Bounded introspection view of an immutable published generation. It exposes\nsnapshot lineage and freshness without leaking object-store keys.", + "properties": { + "conformance": { + "oneOf": [ + { + "type": "null" }, - "target_kind": { - "$ref": "#/components/schemas/AnnTargetKind" + { + "$ref": "#/components/schemas/PublishedReadConformanceView" } + ] + }, + "epoch": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "families": { + "items": { + "$ref": "#/components/schemas/PublishedReadFamilyView" }, - "required": [ - "model_id", - "target_kind", - "matched", - "calibrated_score", - "kind" - ], - "type": "object" + "type": "array" + }, + "format_version": { + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "generation": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "graph": { + "$ref": "#/components/schemas/GraphKey" + }, + "predecessor_generation": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "projection_version": { + "format": "int32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "served_at_seq": { + "$ref": "#/components/schemas/CommitSeq" + }, + "source_head_generation": { + "description": "Graph-head generation whose metadata/configuration this root reflects.\nThis can trail the current head even when `served_at_seq` is unchanged.", + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "summary_available": { + "type": "boolean" } - ] + }, + "required": [ + "graph", + "epoch", + "source_head_generation", + "format_version", + "served_at_seq", + "families", + "summary_available" + ], + "type": "object" + }, + "PublishedReadStatusResponse": { + "description": "One coherent operational view of the graph head and the immutable read root\npinned while resolving it. Lag values are derived from this `head_seq`, not\nfrom a separately-polled status response.", + "properties": { + "conformance_lag_commits": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "generation_lag": { + "description": "Head-generation distance, including same-sequence ontology, shapes, or\nindex-configuration changes that commit-sequence lag cannot expose.", + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "head_generation": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "head_seq": { + "$ref": "#/components/schemas/CommitSeq" + }, + "query_lag_commits": { + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "snapshot": { + "$ref": "#/components/schemas/PublishedReadSnapshotView" + } + }, + "required": [ + "head_seq", + "head_generation", + "snapshot", + "query_lag_commits", + "generation_lag" + ], + "type": "object" }, "RangedReadStats": { "description": "Read accounting for ranged (block-level) persisted index runs. Reported\nwhen search served from a ranged layout instead of coarse whole objects.", @@ -10371,11 +9102,6 @@ "minimum": 0, "type": "integer" }, - "tail_commits_merged": { - "description": "Commits past the indexed run that were merged from the WAL tail\n(append-safe edges only; anything else falls back to the snapshot\nscan).", - "minimum": 0, - "type": "integer" - }, "topology_slices_fetched": { "format": "int64", "minimum": 0, @@ -10405,41 +9131,6 @@ ], "type": "object" }, - "RdfExportPreviewResponse": { - "description": "JSON envelope returned by `GET /v1/graph/export/rdf?truncate=true`.", - "properties": { - "data": { - "description": "RDF serialization (Turtle, N-Triples, TriG, or N-Quads) encoded as a JSON\nstring so the preview metadata stays in one typed response.", - "type": "string" - }, - "format": { - "type": "string" - }, - "returned_triples": { - "minimum": 0, - "type": "integer" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "total_triples": { - "minimum": 0, - "type": "integer" - }, - "truncated": { - "type": "boolean" - } - }, - "required": [ - "snapshot", - "format", - "data", - "returned_triples", - "total_triples", - "truncated" - ], - "type": "object" - }, "RegionAnchorInput": { "description": "A page-region provenance anchor on a fact's evidence (region provenance\n§4.1/§6.4(b) BYO import): where the evidence appears in the source\ndocument. Coordinates are **normalized to the page box** (`[0, 1]`, origin\ntop-left, y down) with `x0 <= x1` and `y0 <= y1`; `confidence` is the\nextraction confidence in `[0, 1]`. The commit path validates and quantizes\n(`round(v * 65535)` coords, `round(c * 255)` confidence) into the canonical\nstored anchor; out-of-range, non-finite, or inverted boxes are rejected.", "properties": { @@ -10774,16 +9465,9 @@ "type": "string" }, "ResolveTermRequest": { + "additionalProperties": false, "description": "WS11 — snap-back resolve: map a piece of free text (a model's guess at a\nclass, relation, property, or value) to the nearest item that actually\nexists in the graph's vocabulary. The output is a subset of real vocabulary\nby construction — the resolver never fabricates a term.", "properties": { - "as_of_commit_seq": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, "candidates": { "description": "Restrict resolution to this explicit candidate set (the narrowed\nshortlist — e.g. relations WS10 admitted for a type pair). Each candidate\nis classified against the ontology for its `kind`. When absent the\nresolver draws candidates from the graph's schema vocabulary.", "items": { @@ -10801,12 +9485,6 @@ }, "type": "array" }, - "snapshot_token": { - "type": [ - "string", - "null" - ] - }, "text": { "description": "The free text to snap to real vocabulary (1..=256 chars).", "type": "string" @@ -10979,150 +9657,6 @@ ], "type": "object" }, - "RetrievalPremiseRequest": { - "description": "Stage G — turn calibrated retrieval candidates into derived edges. Every\ncandidate scored `P >= threshold` becomes a derived edge `(anchor, relation,\nmatched)` with `confidence = P` and a single `Retrieval` provenance leaf\n(never `Asserted` — FAL-PROV-NOT-LAUNDERED). Candidates come from any\nretrieval channel; the server re-verifies each against the served snapshot.", - "properties": { - "anchor": { - "$ref": "#/components/schemas/EntitySelector", - "description": "Subject of every derived edge." - }, - "calibration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PlattCalibration", - "description": "The Platt curve mapping raw score → `P(relevant)`. Optional since the\ncalibration trainer landed: when omitted, the graph's promoted\n`calibration` run serves (the response stamps `calibration_run`);\nwith neither, the request is refused — a made-up curve is worse than\nan explicit error." - } - ] - }, - "candidates": { - "description": "Explicit candidates (client ran retrieval). Exactly one of `candidates` or\n`query` must be supplied.", - "items": { - "$ref": "#/components/schemas/ScoredCandidateInput" - }, - "type": "array" - }, - "materialize": { - "description": "Persist the derived premises as an immutable `derived/v1` object (separate\nfrom the asserted graph) and return its key in `materialized_key`. Default\nfalse — a plain preview that writes nothing.", - "type": [ - "boolean", - "null" - ] - }, - "max_premises": { - "description": "Fail-closed ceiling on emitted premises.", - "minimum": 0, - "type": "integer" - }, - "model_id": { - "description": "The embedding model the scores came from (names the `Retrieval` leaf).", - "type": "string" - }, - "query": { - "description": "Query-driven mode: when set, the server runs BM25 entity retrieval for this\ntext against the served snapshot and uses the matches (with their raw BM25\nscores) as candidates — so a caller can hand a query instead of pre-scoring.", - "type": [ - "string", - "null" - ] - }, - "query_top_k": { - "description": "Candidate-pool size for `query` mode (defaults to 50).", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "relation": { - "description": "Predicate of every derived edge; must resolve in the ontology.", - "type": "string" - }, - "target_kind": { - "$ref": "#/components/schemas/AnnTargetKind", - "description": "The retrieval target the scores ranked." - }, - "threshold": { - "description": "Minimum calibrated `P` for a candidate to become a premise (in `[0,1]`).", - "format": "double", - "type": "number" - } - }, - "required": [ - "anchor", - "relation", - "model_id", - "target_kind", - "threshold", - "max_premises" - ], - "type": "object" - }, - "RetrievalPremiseResponse": { - "description": "The derived edges plus the bound / candidate-not-final instrumentation.", - "properties": { - "calibration_run": { - "description": "The promoted `calibration` run whose scaler priced these premises;\nabsent when the request carried an inline `calibration`.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "considered": { - "description": "Candidates examined (`max_premises` may stop the scan early).", - "minimum": 0, - "type": "integer" - }, - "derived": { - "items": { - "$ref": "#/components/schemas/DerivedEdgeView" - }, - "type": "array" - }, - "dropped_below_threshold": { - "description": "Candidates whose calibrated `P` was below `threshold`.", - "minimum": 0, - "type": "integer" - }, - "dropped_not_visible": { - "description": "Candidates dropped because they were not visible in the served snapshot.", - "minimum": 0, - "type": "integer" - }, - "emitted": { - "description": "Premises emitted (`<= max_premises`).", - "minimum": 0, - "type": "integer" - }, - "materialized_key": { - "description": "Object key of the persisted `derived/v1` run when `materialize` was set;\n`None` for a plain preview.", - "type": [ - "string", - "null" - ] - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - }, - "truncated": { - "description": "True if the `max_premises` bound stopped emission early.", - "type": "boolean" - } - }, - "required": [ - "derived", - "snapshot", - "considered", - "emitted", - "dropped_below_threshold", - "dropped_not_visible", - "truncated" - ], - "type": "object" - }, "RetrievalProfileId": { "description": "Named retrieval profile selecting the fusion knobs (BM25 normalization,\nchannel weights, score floor, degree-boost mode, ontology class-intent +\nexpansion de-noise). A closed enum — the only profile identifier that may\nreach a metric label — so the cardinality stays bounded.\n\n- `ndcg_v1` is the **shipped default** (a search that names no profile\n resolves to it): `graph_aware_v1` plus candidate-scoped lexical scoring\n and a moderate vector lift, selected by the 2026-06-22 nDCG@10 gate.\n- `graph_aware_v1` is the graph-aware comparison anchor: ontology class-intent\n surfacing + entity-fold expansion de-noise, ≈2.5× nDCG@10 over the legacy\n blend on membership/dimension queries, generalising cross-corpus with the\n same knobs and inert on graphs without ontology class structure\n (retrieval-quality-ledger R21/R23).\n- `baseline` is the historical hardcoded blend — kept selectable as the\n comparison anchor and the instant rollback path.\n- `scored_atom_v1` flips BM25 to the candidate-set-independent theoretical-max\n normalizer (`S_max`): quality-neutral on a single lexical channel, better\n cross-channel fusion calibration (retrieval-quality-ledger R15/R16).", "enum": [ @@ -11172,61 +9706,6 @@ ], "type": "object" }, - "RuleSet": { - "description": "A versioned, immutable set of inference rules stored with a graph branch\n(Track B). Pinned from `GraphHead.rules_ref`; used by `infer` and SHACL\n`include_derived` when the request carries no inline rules.", - "properties": { - "rules": { - "items": { - "$ref": "#/components/schemas/InferenceRule" - }, - "type": "array" - }, - "version": { - "description": "Monotonically increasing; bumped on each define.", - "format": "int64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "version", - "rules" - ], - "type": "object" - }, - "RuleSetDefineRequest": { - "description": "Define (replace) the stored rule set for a graph branch.", - "properties": { - "rules": { - "items": { - "$ref": "#/components/schemas/InferenceRule" - }, - "type": "array" - } - }, - "required": [ - "rules" - ], - "type": "object" - }, - "RuleSetDefineResponse": { - "properties": { - "rule_count": { - "minimum": 0, - "type": "integer" - }, - "rules_version": { - "format": "int64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "rules_version", - "rule_count" - ], - "type": "object" - }, "SchemaAuditReport": { "properties": { "conforms": { @@ -11238,6 +9717,15 @@ }, "type": "array" }, + "ontology_version": { + "description": "Ontology identity the durable report validated.", + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, "result_count": { "minimum": 0, "type": "integer" @@ -11248,9 +9736,29 @@ }, "type": "array" }, + "shapes_version": { + "description": "Shapes identity the durable report validated.", + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, "truncated": { "description": "True when `result_count` is exact but `results` contains only the\ncaller-requested leading window. Whole-graph audits can produce one row\nper offending focus node, so HTTP responses are bounded by default.", "type": "boolean" + }, + "validated_at_seq": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CommitSeq", + "description": "Published conformance watermark. Present on every public durable\nconformance response; absent only on internal pre-publication\nvalidation results." + } + ] } }, "required": [ @@ -11335,7 +9843,7 @@ }, { "$ref": "#/components/schemas/SchemaAuditSummary", - "description": "Live audit health summary for the active shape bundle at the current\nsnapshot when `/v1/schema?audit=true` is requested. Full result rows\nremain on `/v1/schema/audit`." + "description": "Durable audit health summary recorded with the schema bundle, when one\nhas been published by background validation. The metadata-only\n`/v1/schema` route does not run validation in the request path." } ] }, @@ -11480,23 +9988,10 @@ ], "type": "string" }, - "SchemaPreviewRequest": { + "SchemaPublishRequest": { "properties": { - "base_ontology_version": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "base_shapes_version": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] + "confirm_restrictive": { + "type": "boolean" }, "desired_mode": { "$ref": "#/components/schemas/SchemaEnforceMode" @@ -11524,131 +10019,22 @@ }, "type": "object" }, - "SchemaPreviewResponse": { - "properties": { - "audit": { - "$ref": "#/components/schemas/SchemaAuditReport" - }, - "base_ontology_version": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "base_shapes_version": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "can_publish": { - "type": "boolean" - }, - "desired_mode": { - "$ref": "#/components/schemas/SchemaEnforceMode" - }, - "diff": { - "items": { - "$ref": "#/components/schemas/SchemaDiffEntry" - }, - "type": "array" - }, - "graph": { - "$ref": "#/components/schemas/GraphKey" - }, - "messages": { - "items": { - "type": "string" - }, - "type": "array" - }, - "preview_digest": { - "type": "string" - }, - "proposed_ontology_version": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "proposed_shapes_version": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "publish_mode_allowed": { - "items": { - "$ref": "#/components/schemas/SchemaEnforceMode" - }, - "type": "array" - }, - "verdict": { - "$ref": "#/components/schemas/SchemaCompatibilityVerdict" - } - }, - "required": [ - "graph", - "base_ontology_version", - "proposed_ontology_version", - "desired_mode", - "verdict", - "can_publish", - "publish_mode_allowed", - "preview_digest", - "diff", - "audit", - "messages" - ], - "type": "object" - }, - "SchemaPublishRequest": { + "SchemaPublishResponse": { "properties": { - "confirm_restrictive": { + "activated": { "type": "boolean" }, - "desired_mode": { - "$ref": "#/components/schemas/SchemaEnforceMode" - }, - "ontology": { + "audit": { "oneOf": [ { "type": "null" }, { - "$ref": "#/components/schemas/SchemaSource" + "$ref": "#/components/schemas/SchemaAuditReport", + "description": "Absent until maintenance publishes conformance for this exact shapes\nversion. Schema publication never performs whole-graph validation in an\nHTTP handler." } ] }, - "preview_digest": { - "type": "string" - }, - "shapes": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SchemaSource" - } - ] - } - }, - "required": [ - "preview_digest" - ], - "type": "object" - }, - "SchemaPublishResponse": { - "properties": { - "activated": { - "type": "boolean" - }, - "audit": { - "$ref": "#/components/schemas/SchemaAuditReport" - }, "enforce_mode": { "$ref": "#/components/schemas/SchemaEnforceMode" }, @@ -11680,7 +10066,6 @@ "ontology_version", "enforce_mode", "activated", - "audit", "messages" ], "type": "object" @@ -11865,7 +10250,7 @@ "type": "object" }, "SearchConsistency": { - "description": "Read consistency for a query surface (search, graph summary, SPARQL).\n\nA5 (2026-07-21 product decision): `Eventual` is the **default**. It serves the\nlast published index/dataset state at its watermark with no in-memory fold of\nthe un-indexed tail — the lowest-latency mode and the availability floor\nduring any indexing backlog. The served watermark rides back on\n`SnapshotView::served_at_seq`. `Strong` (fold the un-indexed tail up to the\nquery head) is now explicit opt-in; the precise read-your-writes contract\n(`min_indexed_seq`) replaces most former uses of strong. See\n`docs/architecture/segment-native-indexing.md` §6.", + "description": "Read consistency for a query surface (search, graph summary, SPARQL).\n\nA5 (2026-07-21 product decision): `Eventual` is the **default**. It serves the\npinned published generation at its watermark with no request-time graph\nassembly — the lowest-latency mode and the availability floor during any\npublication backlog. The served watermark rides back on\n`SnapshotView::served_at_seq`. `Strong` requires the immutable published\ngeneration itself to cover the query head and is explicit opt-in; the precise\nread-your-writes contract (`min_indexed_seq`) replaces most former uses of strong. See\n`docs/architecture/segment-native-indexing.md` §6.", "enum": [ "strong", "eventual" @@ -11877,16 +10262,6 @@ "bm25": { "type": "boolean" }, - "bm25_source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FullTextIndexSource" - } - ] - }, "consistency": { "oneOf": [ { @@ -12020,16 +10395,6 @@ "vector": { "type": "boolean" }, - "vector_source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EmbeddingIndexSource" - } - ] - }, "weights": { "oneOf": [ { @@ -13232,236 +11597,6 @@ ], "type": "object" }, - "SearchIndexFamilyRun": { - "properties": { - "family": { - "type": "string" - }, - "indexed_commit_seq_after": { - "$ref": "#/components/schemas/CommitSeq" - }, - "indexed_commit_seq_before": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommitSeq" - } - ] - }, - "manifest_key": { - "type": [ - "string", - "null" - ] - }, - "objects_written": { - "minimum": 0, - "type": "integer" - }, - "skipped": { - "type": "boolean" - } - }, - "required": [ - "family", - "indexed_commit_seq_after", - "skipped", - "objects_written" - ], - "type": "object" - }, - "SearchIndexJobStatusResponse": { - "description": "Durable background full-index job status with per-family terminal result.", - "properties": { - "attempts": { - "format": "int32", - "minimum": 0, - "type": "integer" - }, - "enqueued_at_micros": { - "format": "int64", - "type": "integer" - }, - "graph": { - "$ref": "#/components/schemas/GraphKey" - }, - "job_id": { - "type": "string" - }, - "result": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchIndexRunResponse" - } - ] - }, - "stage": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "`pending` | `running` | `succeeded` | `failed` | `cancelled`.", - "type": "string" - }, - "terminal_error": { - "type": [ - "string", - "null" - ] - }, - "updated_at_micros": { - "format": "int64", - "type": "integer" - } - }, - "required": [ - "job_id", - "status", - "graph", - "attempts", - "enqueued_at_micros", - "updated_at_micros" - ], - "type": "object" - }, - "SearchIndexRunRequest": { - "properties": { - "build_adjacency": { - "description": "Build the ranged adjacency run for traversal. Off by default.", - "type": "boolean" - }, - "build_embeddings": { - "type": "boolean" - }, - "build_full_text": { - "type": "boolean" - }, - "build_permutation": { - "description": "Build the object-storage-native permutation view (PSO) for native SHACL\ntarget/path evaluation and analytic graph queries. Off by default.", - "type": "boolean" - }, - "dim": { - "format": "int32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "include_clusters": { - "type": "boolean" - }, - "include_raw_rerank": { - "description": "Append a raw-f32 region to the embedding run so vector search can opt\ninto exact rerank. Off by default (compact 4-bit-only runs).", - "type": "boolean" - }, - "include_terms": { - "type": "boolean" - }, - "max_clusters": { - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "provider": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EmbeddingProviderConfig" - } - ] - }, - "targets": { - "items": { - "$ref": "#/components/schemas/AnnTargetKind" - }, - "type": "array" - }, - "tokenizer": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FullTextTokenizerConfig" - } - ] - } - }, - "required": [ - "targets", - "include_terms", - "include_clusters" - ], - "type": "object" - }, - "SearchIndexRunResponse": { - "properties": { - "adjacency": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchIndexFamilyRun" - } - ] - }, - "embeddings": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchIndexFamilyRun" - } - ] - }, - "full_text": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchIndexFamilyRun" - } - ] - }, - "index_lineage": { - "$ref": "#/components/schemas/IndexLineage", - "description": "One coherent observation of every serving index family after this run.\nUnlike the per-family build outcomes, this also includes families the\nrequest did not rebuild and is therefore the convergence contract." - }, - "permutation": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SearchIndexFamilyRun" - } - ] - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - } - }, - "required": [ - "snapshot", - "index_lineage" - ], - "type": "object" - }, "SearchOrder": { "description": "Sort direction for a query's `order_by` key. `Desc` is the default for the\nimplicit relevance ordering (highest score first); `Asc` is most useful when\nordering by a metadata field.", "enum": [ @@ -13510,12 +11645,9 @@ ] }, "SearchSessionCommitRequest": { - "description": "`POST /v1/search/session/commit` — execute the search against the session's\npinned snapshot. The warmed cache makes it read warm; the results are exactly\nwhat the same request would return without any prior `prefix` frames.", + "additionalProperties": false, + "description": "`POST /v1/search/session/commit` — execute the search against the current\npublished snapshot. The warmed cache makes it read warm; the results are\nexactly what the same request would return without any prior `prefix`\nframes.", "properties": { - "pin": { - "description": "Enforce the session's snapshot pin: the search runs with\n`as_of_commit_seq` set to the commit the session opened at, so a write\nthat landed mid-session cannot change what this commit returns\n(reproducible runs / retry determinism). An explicit conflicting\n`request.as_of_commit_seq` is an `invalid_input`. Default false — the\ncommit reads the current head, exactly like `POST /v1/graph/search`.", - "type": "boolean" - }, "request": { "$ref": "#/components/schemas/SemanticGraphSearchRequest" }, @@ -13700,17 +11832,9 @@ "type": "object" }, "SearchSuggestRequest": { + "additionalProperties": false, "description": "Turn-level grounding: complete a prefix from the index's own vocabulary\n(BM25 term dictionary, attribute directory) and the graph ontology\n(classes, relations, properties). Never reads doc/postings blocks; the\ncompletions are strings that provably exist in the graph at this snapshot.", "properties": { - "as_of_commit_seq": { - "description": "Transaction-time vocabulary pin. Mutually exclusive with\n`snapshot_token`.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, "context": { "oneOf": [ { @@ -13758,13 +11882,6 @@ } ] }, - "snapshot_token": { - "description": "Opaque graph snapshot identity previously returned by LBB. Mutually\nexclusive with `as_of_commit_seq`.", - "type": [ - "string", - "null" - ] - }, "vocabulary_filter": { "oneOf": [ { @@ -13868,7 +11985,7 @@ "type": "object" }, "SearchTemporalCoverage": { - "description": "How a temporally-pinned (or head) search resolved run selection: the\neffective `as_of` ceiling, the base snapshot of the selected persisted\nrun(s), and the highest commit each leg's run+segments actually covered\n(the forward WAL overlay covers `(covered_through, ceiling]`). Distinct from\nthe ontology-inspect `TemporalCoverage` type. Per-leg fields are `None` when\nthat leg served from an ephemeral rebuild (no persisted run at the ceiling).", + "description": "Provenance for the immutable family roots selected from one pinned published\ngeneration. `ceiling_commit_seq` is that generation's common query\nwatermark; per-leg fields are `None` only when the corresponding leg was\ndisabled.", "properties": { "bm25_covered_through": { "oneOf": [ @@ -13877,7 +11994,7 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "Highest commit the BM25 run + applicable delta segments cover at the\nceiling; the BM25 overlay covers `(bm25_covered_through, ceiling]`." + "description": "Highest commit covered by the selected immutable BM25 root." } ] }, @@ -13888,13 +12005,13 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "Base snapshot commit_seq of the selected BM25 run (`None` if the BM25 leg\nwas disabled or degraded to an ephemeral rebuild)." + "description": "Base snapshot commit sequence of the selected BM25 run, or `None` when\nthe BM25 leg was disabled." } ] }, "ceiling_commit_seq": { "$ref": "#/components/schemas/CommitSeq", - "description": "Resolved transaction-time ceiling: the `as_of_commit_seq` pin, or the\nhead commit_seq when the query was unpinned." + "description": "Common query watermark of the pinned published generation." }, "vector_covered_through": { "oneOf": [ @@ -13903,7 +12020,7 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "Highest commit the ANN run + applicable delta segments cover at the\nceiling (same semantics as `bm25_covered_through`); the ANN overlay\ncovers `(vector_covered_through, ceiling]`." + "description": "Highest commit covered by the selected immutable ANN root." } ] }, @@ -13914,7 +12031,7 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "Base snapshot commit_seq of the selected ANN run (`None` if the vector\nleg was disabled or degraded to an ephemeral rebuild)." + "description": "Base snapshot commit sequence of the selected ANN run, or `None` when\nthe vector leg was disabled." } ] } @@ -13925,23 +12042,8 @@ "type": "object" }, "SemanticGraphSearchRequest": { + "additionalProperties": false, "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. BM25/ANN\nindexes still generate candidates from the head; the pin is enforced\nwhere results are verified against the snapshot, never by candidate\ngeneration. Omitted means the current head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "description": "Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.", - "type": [ - "string", - "null" - ] - }, "explain": { "type": "boolean" }, @@ -14130,10 +12232,6 @@ "minimum": 0, "type": "integer" }, - "bm25_degraded_to_ephemeral": { - "description": "True when a **persisted** BM25 index was requested but none matched the\nquery's resolved target set, so the search silently fell back to a full\nephemeral rebuild (much slower). A common cause is building the index for\na narrower target set than the query resolves to (e.g. `[Entity]` vs the\n`{Entity, Neighborhood}` that `Entities` resolves to). Also bumps the\n`lbb_search_degraded_total{family=\"bm25\"}` metric.", - "type": "boolean" - }, "bm25_documents": { "minimum": 0, "type": "integer" @@ -14159,10 +12257,6 @@ "minimum": 0, "type": "integer" }, - "bm25_overlay_candidates": { - "minimum": 0, - "type": "integer" - }, "bm25_ranged": { "oneOf": [ { @@ -14241,6 +12335,11 @@ "minimum": 0, "type": "integer" }, + "published_lag_commits": { + "description": "Commit distance from the graph head to the pinned published generation.", + "minimum": 0, + "type": "integer" + }, "retrieval_profile": { "oneOf": [ { @@ -14295,22 +12394,10 @@ "null" ] }, - "unindexed_tail_commits": { - "minimum": 0, - "type": "integer" - }, "vector_candidates": { "minimum": 0, "type": "integer" }, - "vector_channel_skipped": { - "description": "True when latest-head hybrid search requested the persisted vector/ANN\nchannel but no matching run existed, so the optional vector channel was\nskipped instead of silently rebuilding an O(corpus) ephemeral ANN on the\nrequest path. Explicit ephemeral and historical pinned searches retain\ntheir existing behavior.", - "type": "boolean" - }, - "vector_degraded_to_ephemeral": { - "description": "As `bm25_degraded_to_ephemeral`, for the persisted vector/ANN index.", - "type": "boolean" - }, "vector_indexed_commit_seq": { "oneOf": [ { @@ -14339,10 +12426,6 @@ "minimum": 0, "type": "integer" }, - "vector_overlay_candidates": { - "minimum": 0, - "type": "integer" - }, "vector_ranged": { "oneOf": [ { @@ -14370,9 +12453,7 @@ "vector_spaces_searched", "hybrid_ranked", "search_mode", - "unindexed_tail_commits", - "bm25_overlay_candidates", - "vector_overlay_candidates", + "published_lag_commits", "filter_prefiltered_candidates", "filter_skipped_candidates" ], @@ -14432,22 +12513,8 @@ "type": "object" }, "SemanticTraverseRequest": { + "additionalProperties": false, "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin (transaction-time ceiling): seeds and expansion reproduce\nthe graph as of this commit sequence. Any as-of (valid time or pin)\nroutes traversal through the snapshot scan — the persisted-vector\nranged fast path serves head reads only. Omitted means head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "type": [ - "string", - "null" - ] - }, "direction": { "$ref": "#/components/schemas/ExpansionDirection" }, @@ -15451,17 +13518,9 @@ "type": "object" }, "ShadowEvalRequest": { + "additionalProperties": false, "description": "`POST /v1/models/shadow-eval` — champion vs challenger retrieval over the\nsame pinned snapshot: the challenger is a search configuration (a\nchallenger embedding run's space, different weights, a profile), replayed\nagainst the same queries the champion serves. Promotion stays a decision\non this evidence — the endpoint never promotes.", "properties": { - "as_of_commit_seq": { - "description": "Pin both arms to one snapshot for reproducibility.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, "challenger": { "$ref": "#/components/schemas/SearchEngineOptions" }, @@ -15738,7 +13797,7 @@ "type": "object" }, "SignalKind": { - "description": "The closed set of signal kinds (v1). Extending this is a deliberate format\nchange, not an open string.\n\nv1.1 (2026-07-07, planner-feedback capture): adds `ask_trace`\n(server-emitted per `/v1/ask`: the question, the decoded plan + its\nshortlists, verification flags, retrieval outcome) and `ask_feedback`\n(client verdict on an ask, joined to its trace by `request_id`) — the raw\nmaterial the planner fine-tune trains on.", + "description": "The closed set of signal kinds (v1). Extending this is a deliberate format\nchange, not an open string.\n\nv1.1 (2026-07-07, planner-feedback capture): adds the legacy\n`ask_trace`/`ask_feedback` supervision records. They remain decodable for\ndurable training data, but no public Ask endpoint emits them.", "enum": [ "suggestion_shown", "suggestion_adopted", @@ -15852,7 +13911,7 @@ }, "compacted_seq": { "$ref": "#/components/schemas/CommitSeq", - "description": "Highest commit folded into the **compacted graph snapshot base** (the\nmaterialized segment base). Commits in `(compacted_seq, commit_seq]` live in\nthe WAL tail and are replayed on read — so `compacted_seq: 0` is the normal\nstate of a small or freshly-created graph (no base built yet) and does\n**not** mean the data is unreadable: every read replays the full tail.\n\nThis is *not* search-index coverage. Whether BM25/vector search indexes\nare built — what `/v1/index/run` advances — is reported separately as\n`bm25_indexed_commit_seq` / `ann_indexed_commit_seq` on\n`GET /v1/graph/metadata` and on the entity read's metadata." + "description": "Highest durable graph-truth commit folded by background compaction.\nThis is maintenance provenance, not the query-serving watermark.\nPublished reads expose their one common `served_at_seq` through the\nresponse and `/v1/graph/read-snapshot`; handlers never fold the WAL tail\nor assemble derived indexes to satisfy a request." }, "served_at_seq": { "oneOf": [ @@ -15861,7 +13920,7 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "The coherent watermark this response was actually served through when it\ntrails graph head. Usually this is the published index/dataset watermark.\nExplorer's adjacency-backed reads report the newest published adjacency\nbase+delta coverage without inspecting the WAL tail. For a multi-family\nsearch this is the MIN of the enabled families' published watermarks, so\nevery surface (BM25, vector, …) agrees on one snapshot. Omitted when the\nresponse is served at `commit_seq`." + "description": "The coherent watermark named by the one immutable published generation\npinned for this response. All enabled families (RDF, Base, BM25, ANN,\nadjacency, summary, and conformance) are interpreted against this same\nwatermark; request pressure cannot select an older family or change it\nmid-request. Omitted only for responses that do not use published state." } ] }, @@ -15870,7 +13929,7 @@ "type": "boolean" }, "stale_reason": { - "description": "The reason a read is `stale`. `\"storage_degraded\"` (F2),\n`\"eventual_consistency\"` (A3: served from the last published index/dataset\nstate), `\"adjacency_coverage\"` (served from the newest published\nranged-adjacency snapshot), `\"tail_budget_exceeded\"` (the eventual RDF\nWAL tail exceeded a per-read bound), `\"merge_lag\"` (the RDF L0 chain was\ncapped at a coherent prefix), or `\"assembly_pool_exhausted\"` (the shared\neventual-read byte pool was saturated); omitted when not stale.", + "description": "The reason a read is `stale`. `\"storage_degraded\"` (F2),\n`\"eventual_consistency\"` (served from the immutable published\ngeneration) or `\"adjacency_coverage\"` (served from that generation's\nbounded ranged-adjacency snapshot); omitted when not stale.", "type": [ "string", "null" @@ -16262,6 +14321,7 @@ ] }, "SparqlSelectRequest": { + "additionalProperties": false, "description": "A SPARQL-subset SELECT/ASK query: a conjunctive basic graph pattern (the\nWHERE) evaluated over the object-storage permutation view, with variable\nprojection, DISTINCT, and LIMIT/OFFSET. Structured-request-first — the SPARQL\ntext syntax is a later addition behind a dialect field, and FILTER plus\naggregation arrive in later milestones.", "properties": { "aggregates": { @@ -16271,21 +14331,6 @@ }, "type": "array" }, - "as_of_commit_seq": { - "description": "Snapshot pin: evaluate as of this `commit_seq`, hiding later commits.\nErrors if it exceeds the head; forces the snapshot reduce path.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "type": [ - "string", - "null" - ] - }, "ask": { "description": "`ASK` form: return only `boolean` (whether the pattern has any solution).\nProjection, DISTINCT, and limit/offset are ignored.", "type": "boolean" @@ -16297,7 +14342,7 @@ }, { "$ref": "#/components/schemas/SearchConsistency", - "description": "Read consistency (A3 serving; A5 default). `eventual` (the **default**\nsince A5) serves ENTIRELY from the last published conformant prepared\ndataset (the maintenance-owned, asserted-only default family, discovered\nvia the W9c pointer) at its watermark — no in-memory gap fold, so a query\nstays available even while background indexing lags the snapshot. The\nserved watermark is surfaced as `snapshot.served_at_seq`. Eventual serving\nrequires a published dataset; a graph with none yet returns a retryable\n429. `strong` (explicit opt-in) evaluates against the head snapshot,\nfolding any un-indexed WAL tail into the conformant dataset in memory." + "description": "Read consistency. `eventual` (the default) pins the native RDF runset in\nthe current `PublishedReadSnapshot`; it never folds a gap or discovers\nanother family. The served watermark is surfaced as\n`snapshot.served_at_seq`. A graph without a published generation returns\na retryable readiness error. `strong` requires that same immutable\ngeneration to cover head and otherwise returns\n`strong_read_pending`." } ] }, @@ -16372,7 +14417,7 @@ }, { "$ref": "#/components/schemas/CommitSeq", - "description": "A5 read-your-writes floor: require the read to be served from state whose\nwatermark ≥ this `commit_seq` (the `new_commit_seq` a commit/import\nreturned). Under the default `eventual`, a floor not yet covered by the\npublished dataset returns a retryable `read_your_writes_pending` 429 (poll\nuntil it lands); under `strong` the floor is satisfied by construction and a\nfloor above head is a client error. `None` == no floor. See\n`docs/architecture/segment-native-indexing.md` §6." + "description": "A5 read-your-writes floor: require the read to be served from state whose\nwatermark ≥ this `commit_seq` (the `new_commit_seq` a commit/import\nreturned). Under the default `eventual`, a floor not yet covered by the\npublished generation returns a retryable `read_your_writes_pending` 429 (poll\nuntil it lands); under `strong` the floor is satisfied by construction and a\nfloor above head is a client error. `None` == no floor. See\n`docs/architecture/segment-native-indexing.md` §6." } ] }, @@ -16399,7 +14444,7 @@ "type": "array" }, "reason": { - "description": "Reason over the graph's stored inference rules: fold the rule-derived\nfacts into the snapshot the query sees, so a pattern matches asserted **and**\nderived edges in one shot. Off by default (asserted-only). Forces the\noverlay reduce path (the prebuilt index holds no derived facts), and is a\nno-op when the branch has no stored rules.", + "description": "Reason over the graph's stored inference rules so a pattern matches\nasserted **and** derived edges in one shot. Off by default\n(asserted-only). Public serving requires a compatible reasoned\nprojection in the pinned published generation and fails closed when it\nis absent; it never forces an overlay reduce.", "type": "boolean" }, "select": { @@ -16529,27 +14574,12 @@ ] }, "SparqlTextRequest": { + "additionalProperties": false, "description": "Run a SPARQL 1.1 query supplied as **text** (SELECT or ASK) through the\nconformant engine over the live graph, returning SPARQL 1.1 Query Results\nJSON. Distinct from [`SparqlSelectRequest`] (the structured-request form);\nthis is the raw-text dialect. CONSTRUCT/DESCRIBE are rejected (they yield an\nRDF graph, not a results table).", "properties": { - "as_of_commit_seq": { - "description": "Snapshot pin: project the graph as of this `commit_seq` before running the\nconformant engine, hiding later commits. Errors if it exceeds the head.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "as_of_valid_time": { - "description": "RFC3339 valid-time; query the graph as of that instant. `None` = now.", - "type": [ - "string", - "null" - ] - }, "entailment": { "$ref": "#/components/schemas/SparqlEntailment", - "description": "RDFS entailment regime. `Subclass` (default) makes a query for a class\nmatch instances of its subtypes; `None` matches only the declared type." + "description": "RDFS entailment regime. `None` (default) reads the asserted published\nprojection. `Subclass` requires a compatible reasoned projection and\nfails closed while one is unavailable." }, "limit": { "description": "Return at most this many result rows. Applied to SELECT bindings after the\nconformant engine has produced the complete result document.", @@ -16572,7 +14602,7 @@ "type": "string" }, "reason": { - "description": "Reason over the branch's stored inference rules: project the rule-derived\nfacts into the dataset the conformant engine runs over, so a query reasons\nover asserted **and** derived edges. Off by default; a no-op when the branch\nhas no stored rules. Combine with `entailment: subclass` (the default) for\nfull reasoning — rule-derived facts plus `rdfs:subClassOf` type closure.", + "description": "Reason over the branch's stored inference rules: project the rule-derived\nfacts into the dataset the conformant engine runs over, so a query reasons\nover asserted **and** derived edges. Off by default; a no-op when the branch\nhas no stored rules. Combine with `entailment: subclass` for full\nreasoning—rule-derived facts plus `rdfs:subClassOf` type closure—once\nmaintenance publishes a compatible reasoned projection.", "type": "boolean" } }, @@ -17005,88 +15035,6 @@ ], "type": "object" }, - "TemporalCoverage": { - "description": "A self-describing summary of a snapshot's two temporal axes, so an agent can\ndecide up front which temporal queries are meaningful on this graph.\n\nThe product motivation: a graph backfilled in one batch with no per-fact\n`valid_time` looks fully populated but cannot be bisected by date — every\n`as_of` returns the same snapshot. The two `*_degenerate` flags say so\nexplicitly rather than letting a caller render N identical daily panels.", - "properties": { - "as_of_valid_time_degenerate": { - "description": "True when no event carries a `valid_time` bound: an `as_of_valid_time`\nquery returns all-or-nothing, never a daily progression.", - "type": "boolean" - }, - "distinct_commit_count": { - "description": "Distinct `commit_seq` values among the events: how many commits the data\narrived in. `1` means a single bulk backfill, so `as_of_commit_seq` can\nonly distinguish \"before\" vs \"after\" that one batch.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "earliest_commit_time_micros": { - "description": "Transaction-time span (when facts were recorded), in epoch micros.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "earliest_valid_time_micros": { - "description": "World-time span over events that carry a `valid_time` bound, in micros.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "edge_event_count": { - "description": "Total append-only edge events in the snapshot overlay.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "edges_with_valid_time": { - "description": "Events whose `valid_time` carries a bounded start and/or end.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "head_commit_seq": { - "description": "Head `commit_seq` — the largest snapshot pin (`as_of_commit_seq`) a read\ncan request right now.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "latest_commit_time_micros": { - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "latest_valid_time_micros": { - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "single_commit": { - "description": "True when every event arrived in a single commit (a one-shot backfill):\nthere is only one snapshot to pin to, and `as_of` by wall-clock date\ncannot bisect the history. For multi-commit graphs, inspect the\n`*_commit_time_micros` span to judge whether daily bisection is possible.", - "type": "boolean" - }, - "valid_time_coverage": { - "description": "`edges_with_valid_time / edge_event_count`, in `[0,1]`. Near zero means\nan `as_of_valid_time` query cannot bisect this graph by world-time.", - "format": "float", - "type": "number" - } - }, - "required": [ - "edge_event_count", - "edges_with_valid_time", - "valid_time_coverage", - "head_commit_seq", - "distinct_commit_count", - "as_of_valid_time_degenerate", - "single_commit" - ], - "type": "object" - }, "TenantId": { "type": "string" }, @@ -17568,7 +15516,7 @@ "TraverseRequest": { "properties": { "as_of_commit_seq": { - "description": "Snapshot pin: reproduce the graph state as of this `commit_seq`, hiding\nany event committed later. Errors if it exceeds the current head, and\nforces the snapshot scan (the ranged adjacency fast path declines a\npinned read). Omit for the latest snapshot.", + "description": "Snapshot pin: reproduce the graph state as of this `commit_seq`, hiding\nany event committed later. Public serving reduces the bounded edge\ndomains from the Base family in the one pinned published generation;\nit never discovers or assembles another snapshot. Historical entity\nfilters/field projection fail explicitly because Base does not carry a\npoint-indexed entity-mutation history. Omit for the latest snapshot.", "format": "int64", "minimum": 0, "type": [ @@ -17604,7 +15552,7 @@ ] }, "max_block_bytes": { - "description": "Decoded adjacency-block working-set byte budget for the ranged path.\nDefaults to the server/store budget. A request may lower the budget,\nbut not raise it. Ignored on the snapshot path.", + "description": "Decoded adjacency-block working-set byte budget for the ranged path.\nDefaults to the server/store budget. A request may lower the budget,\nbut not raise it. Ignored on the bounded Base-family reducer path.", "format": "int64", "minimum": 0, "type": [ @@ -17613,7 +15561,7 @@ ] }, "max_block_reads": { - "description": "Object-read budget for the ranged adjacency path; defaults to a value\nderived from `max_frontier_entities`. Ignored on the snapshot path.", + "description": "Object-read budget for the ranged adjacency path; defaults to a value\nderived from `max_frontier_entities`. Ignored on the bounded Base-family\nreducer path.", "minimum": 0, "type": [ "integer", @@ -17691,7 +15639,7 @@ }, { "$ref": "#/components/schemas/RangedTraverseStats", - "description": "Present when the traversal ran against ranged adjacency blocks; `None`\nmeans the snapshot-scan path served the request." + "description": "Present when the traversal ran against ranged adjacency blocks; `None`\nmeans the same published generation's bounded Base reducer served it." } ] }, @@ -18219,7429 +16167,192 @@ }, "WarmBudget": { "description": "A session's remaining warm budget (reads and bytes), decremented as `prefix`\nframes warm the cache. Bounds wasted speculative work per session.", - "properties": { - "bytes": { - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "reads": { - "format": "int64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "reads", - "bytes" - ], - "type": "object" - }, - "WarmedStats": { - "description": "What a `prefix` frame warmed: new terms diffed in, cache blocks fetched, and\nbytes read. `exhausted` is set once the session hits a warm budget.", - "properties": { - "blocks": { - "description": "Cache blocks fetched by this frame.", - "minimum": 0, - "type": "integer" - }, - "bytes": { - "description": "Bytes read into the cache by this frame.", - "format": "int64", - "minimum": 0, - "type": "integer" - }, - "exhausted": { - "description": "`true` once a session budget stopped further warming this frame.", - "type": [ - "boolean", - "null" - ] - }, - "terms": { - "description": "New complete terms warmed by this frame (already-warmed terms are skipped).", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "terms", - "blocks", - "bytes" - ], - "type": "object" - }, - "WhyRequest": { - "properties": { - "relation": { - "type": "string" - }, - "source": { - "$ref": "#/components/schemas/EntitySelector" - }, - "target": { - "$ref": "#/components/schemas/EntitySelector" - } - }, - "required": [ - "source", - "relation", - "target" - ], - "type": "object" - }, - "WhyResponse": { - "properties": { - "current_edge": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EdgeEventId" - } - ] - }, - "evidence": { - "items": { - "$ref": "#/components/schemas/ObservationId" - }, - "type": "array" - }, - "previous_edges": { - "items": { - "$ref": "#/components/schemas/EdgeEventId" - }, - "type": "array" - }, - "snapshot": { - "$ref": "#/components/schemas/SnapshotView" - } - }, - "required": [ - "previous_edges", - "evidence", - "snapshot" - ], - "type": "object" - }, - "WidenRelationOp": { - "description": "Add already-declared entity types (by name) to a relation's declared\ndomain (`add_domain`) and/or range (`add_range`). The relation and every\nnamed type must already exist. Ids already present are skipped, so the op\nis idempotent and a re-run is a no-op.", - "properties": { - "add_domain": { - "description": "Entity-type names to add to the relation's domain (source types).", - "items": { - "type": "string" - }, - "type": "array" - }, - "add_range": { - "description": "Entity-type names to add to the relation's range (target types).", - "items": { - "type": "string" - }, - "type": "array" - }, - "op": { - "enum": [ - "widen_relation" - ], - "type": "string" - }, - "relation": { - "description": "Relation to widen, by name (case-insensitive).", - "type": "string" - } - }, - "required": [ - "relation", - "op" - ], - "type": "object" - }, - "WritePreconditions": { - "properties": { - "expected_head_commit_seq": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "expected_ontology_version": { - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "expected_snapshot_token": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - } - }, - "securitySchemes": { - "bearer": { - "description": "Stack API key (lbb_sk_test_… / lbb_sk_live_…) or single-mode token", - "scheme": "bearer", - "type": "http" - } - } - }, - "info": { - "description": "Object-storage-native temporal graph and hybrid search engine. Public data-plane integrations use `/v1/*`, scoped by `?graph=`/`?branch=` (default `main`) and authenticated with a stack API key (`lbb_sk_test_…` or `lbb_sk_live_…`) or single-mode token as a bearer. Send `Lbb-Version: 2026-07-22` to pin this beta-breaking contract.", - "title": "Little Big Brain HTTP API", - "version": "2026-07-22" - }, - "openapi": "3.1.0", - "paths": { - "/v1/ask": { - "post": { - "operationId": "post_v1_ask", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Ground a question to real vocabulary, retrieve, and answer with citations", - "tags": [ - "system" - ] - } - }, - "/v1/ask/feedback": { - "post": { - "operationId": "post_v1_ask_feedback", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskFeedbackRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskFeedbackResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Verdict on an ask (accepted|rejected|corrected {plan}), joined to its ask_trace signal by ask_id — the planner fine-tune's explicit feedback capture", - "tags": [ - "system" - ] - } - }, - "/v1/decode": { - "post": { - "operationId": "post_v1_decode", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DecodeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DecodeResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Narrow a relation to real vocabulary (type signatures) and decode it with the graph-native model", - "tags": [ - "system" - ] - } - }, - "/v1/demo/datasets": { - "get": { - "operationId": "get_v1_demo_datasets", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "List built-in demo datasets", - "tags": [ - "demo" - ] - } - }, - "/v1/demo/download-public-datasets": { - "post": { - "operationId": "post_v1_demo_download_public_datasets", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Public dataset id", - "in": "query", - "name": "dataset", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Download one public benchmark dataset sample into the local dataset cache", - "tags": [ - "demo" - ] - } - }, - "/v1/demo/load": { - "post": { - "operationId": "post_v1_demo_load", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Dataset id", - "in": "query", - "name": "dataset", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Build indexes after loading", - "in": "query", - "name": "build", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Load a demo dataset, optionally building indexes", - "tags": [ - "demo" - ] - } - }, - "/v1/demo/public-datasets": { - "get": { - "operationId": "get_v1_demo_public_datasets", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "List public benchmark dataset availability", - "tags": [ - "demo" - ] - } - }, - "/v1/demo/run": { - "post": { - "operationId": "post_v1_demo_run", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Dataset id", - "in": "query", - "name": "dataset", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Index source: persisted or ephemeral", - "in": "query", - "name": "source", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Run canned checks against a demo dataset", - "tags": [ - "demo" - ] - } - }, - "/v1/graph/branch": { - "delete": { - "operationId": "delete_v1_graph_branch", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Must equal the target branch id", - "in": "query", - "name": "confirm", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphBranchDeleteResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Delete the scoped branch; refuses to delete a graph's final live branch", - "tags": [ - "graph" - ] - }, - "post": { - "operationId": "post_v1_graph_branch", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphBranchCreateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphBranchCreateResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Fork the scoped branch from an existing branch in the same graph", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/branch/merge": { - "post": { - "operationId": "post_v1_graph_branch_merge", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphBranchMergeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphBranchMergeResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Replay a child branch's post-fork commits onto the scoped branch (its fork parent) as one commit — validate-then-merge; requires an Idempotency-Key", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/card": { - "get": { - "operationId": "get_v1_graph_card", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphCard" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Per-snapshot self-description (types, relations, properties, top values)", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/changes": { - "get": { - "operationId": "get_v1_graph_changes", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Exclusive lower bound commit_seq (default 0)", - "in": "query", - "name": "since", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Max records per page (default 500, max 5000)", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphChangesResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Changes since a commit_seq (delta read); 409 with reset when since predates compaction", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/commit": { - "post": { - "operationId": "post_v1_graph_commit", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": true, - "schema": { - "type": "string" - } - }, - { - "description": "Validate only and return a GraphCommitDryRunResponse without writing (no Idempotency-Key required)", - "in": "query", - "name": "dry_run", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TripletCommitFile" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphCommitResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Commit triplets and optional entity embeddings", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/compact": { - "post": { - "operationId": "post_v1_graph_compact", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Minimum tail commits before compaction", - "in": "query", - "name": "min_tail_commits", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Merge into at most this many segments", - "in": "query", - "name": "max_segments", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WalCompactResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Fold the WAL tail into snapshot segments", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/create": { - "post": { - "operationId": "post_v1_graph_create", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGraphResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Create the scoped graph and branch", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/delete": { - "post": { - "operationId": "post_v1_graph_delete", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Must equal the target graph id to authorize deletion", - "in": "query", - "name": "confirm", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphDeleteResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Delete every branch and deregister the scoped graph; destructive and idempotent", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/edges": { - "get": { - "operationId": "get_v1_graph_edges", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Search text", - "in": "query", - "name": "q", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Relation filter", - "in": "query", - "name": "relation", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Max rows", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Opaque cursor from the previous page (legacy `offset` also accepted)", - "in": "query", - "name": "cursor", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Browse current edges", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/embedding": { - "get": { - "operationId": "get_v1_graph_embedding", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingConfigResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Read the graph branch's default managed embedding configuration", - "tags": [ - "graph" - ] - }, - "post": { - "operationId": "post_v1_graph_embedding", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingConfigRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingConfigResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Set the graph branch's default managed embedding configuration", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/embedding/backfill": { - "post": { - "operationId": "post_v1_graph_embedding_backfill", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Embedding batch size (default 128, max 512)", - "in": "query", - "name": "batch_size", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Maximum entities to consider (default 100000)", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Re-embed all entities instead of only new entities", - "in": "query", - "name": "full", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Submit a durable managed-embedding backfill job (legacy path alias)", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/embedding/backfill-jobs": { - "delete": { - "operationId": "delete_v1_graph_embedding_backfill_jobs", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable backfill job id", - "in": "query", - "name": "job_id", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Request cancellation of a managed-embedding backfill job", - "tags": [ - "graph" - ] - }, - "get": { - "operationId": "get_v1_graph_embedding_backfill_jobs", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable backfill job id", - "in": "query", - "name": "job_id", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Read one managed-embedding backfill job", - "tags": [ - "graph" - ] - }, - "post": { - "operationId": "post_v1_graph_embedding_backfill_jobs", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "Submit a durable managed-embedding backfill job", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/embedding/models": { - "get": { - "operationId": "get_v1_graph_embedding_models", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingModelsResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ], - "summary": "List the embedding models available on this deployment", - "tags": [ - "graph" - ] - } - }, - "/v1/graph/embedding/promote": { - "post": { - "operationId": "post_v1_graph_embedding_promote", - "parameters": [ - { - "description": "Graph name (default `main`)", - "in": "query", - "name": "graph", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Branch name (default `main`)", - "in": "query", - "name": "branch", - "required": false, - "schema": { - "type": "string" - } + "properties": { + "bytes": { + "format": "int64", + "minimum": 0, + "type": "integer" }, - { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", - "in": "header", - "name": "Lbb-Version", - "required": false, - "schema": { - "type": "string" - } + "reads": { + "format": "int64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "reads", + "bytes" + ], + "type": "object" + }, + "WarmedStats": { + "description": "What a `prefix` frame warmed: new terms diffed in, cache blocks fetched, and\nbytes read. `exhausted` is set once the session hits a warm budget.", + "properties": { + "blocks": { + "description": "Cache blocks fetched by this frame.", + "minimum": 0, + "type": "integer" }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } + "bytes": { + "description": "Bytes read into the cache by this frame.", + "format": "int64", + "minimum": 0, + "type": "integer" }, - { - "description": "Finished training run identifier", - "in": "query", - "name": "run_id", - "required": false, - "schema": { - "type": "string" - } + "exhausted": { + "description": "`true` once a session budget stopped further warming this frame.", + "type": [ + "boolean", + "null" + ] }, - { - "description": "Allow promotion when evaluation quality regressed", - "in": "query", - "name": "allow_regression", - "required": false, - "schema": { - "type": "string" - } + "terms": { + "description": "New complete terms warmed by this frame (already-warmed terms are skipped).", + "minimum": 0, + "type": "integer" } + }, + "required": [ + "terms", + "blocks", + "bytes" ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedEmbeddingPromoteResponse" - } - } - }, - "description": "OK", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "type": "object" + }, + "WhyRequest": { + "properties": { + "relation": { + "type": "string" }, - "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Bad request", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "source": { + "$ref": "#/components/schemas/EntitySelector" }, - "401": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Unauthorized", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } + "target": { + "$ref": "#/components/schemas/EntitySelector" + } + }, + "required": [ + "source", + "relation", + "target" + ], + "type": "object" + }, + "WhyResponse": { + "properties": { + "current_edge": { + "oneOf": [ + { + "type": "null" }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } + { + "$ref": "#/components/schemas/EdgeEventId" } - } + ] }, - "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } + "evidence": { + "items": { + "$ref": "#/components/schemas/ObservationId" }, - "description": "Forbidden", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "type": "array" }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } + "previous_edges": { + "items": { + "$ref": "#/components/schemas/EdgeEventId" }, - "description": "Not found", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "type": "array" }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } + "snapshot": { + "$ref": "#/components/schemas/SnapshotView" + } + }, + "required": [ + "previous_edges", + "evidence", + "snapshot" + ], + "type": "object" + }, + "WidenRelationOp": { + "description": "Add already-declared entity types (by name) to a relation's declared\ndomain (`add_domain`) and/or range (`add_range`). The relation and every\nnamed type must already exist. Ids already present are skipped, so the op\nis idempotent and a re-run is a no-op.", + "properties": { + "add_domain": { + "description": "Entity-type names to add to the relation's domain (source types).", + "items": { + "type": "string" }, - "description": "Conflict", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "type": "array" }, - "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } + "add_range": { + "description": "Entity-type names to add to the relation's range (target types).", + "items": { + "type": "string" }, - "description": "Rate limit exceeded", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "type": "array" }, - "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Internal server error", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "op": { + "enum": [ + "widen_relation" + ], + "type": "string" }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LbbErrorEnvelope" - } - } - }, - "description": "Service unavailable", - "headers": { - "Lbb-Version": { - "description": "API contract version used for the response", - "schema": { - "type": "string" - } - }, - "X-Request-Id": { - "description": "Request correlation id", - "schema": { - "type": "string" - } - } - } + "relation": { + "description": "Relation to widen, by name (case-insensitive).", + "type": "string" } }, - "security": [ - { - "bearer": [] - } + "required": [ + "relation", + "op" ], - "summary": "Promote a successful fine-tuned embedding run to the graph default", - "tags": [ - "graph" - ] + "type": "object" + }, + "WritePreconditions": { + "properties": { + "expected_head_commit_seq": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "expected_ontology_version": { + "format": "int64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "expected_snapshot_token": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" } }, - "/v1/graph/entities": { - "get": { - "operationId": "get_v1_graph_entities", + "securitySchemes": { + "bearer": { + "description": "Stack API key (lbb_sk_test_… / lbb_sk_live_…) or single-mode token", + "scheme": "bearer", + "type": "http" + } + } + }, + "info": { + "description": "Object-storage-native temporal graph and hybrid search engine. Public data-plane integrations use `/v1/*`, scoped by `?graph=`/`?branch=` (default `main`) and authenticated with a stack API key (`lbb_sk_test_…` or `lbb_sk_live_…`) or single-mode token as a bearer. Send `Lbb-Version: 2026-07-23` to pin this beta-breaking contract.", + "title": "Little Big Brain HTTP API", + "version": "2026-07-23" + }, + "openapi": "3.1.0", + "paths": { + "/v1/decode": { + "post": { + "operationId": "post_v1_decode", "parameters": [ { "description": "Graph name (default `main`)", @@ -25662,7 +16373,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -25671,66 +16382,31 @@ } }, { - "description": "Search text", - "in": "query", - "name": "q", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Entity type filter", - "in": "query", - "name": "type", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Max rows", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Opaque cursor from the previous page", - "in": "query", - "name": "cursor", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Comma-separated property names to inline on each row (typed, native JSON); `*` for all. Omit for the lean default row.", - "in": "query", - "name": "fields", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Comma-separated entity ids to fetch in one call (bulk lookup); bypasses the q/type browse filters.", - "in": "query", - "name": "ids", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DecodeRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/DecodeResponse" } } }, @@ -25948,15 +16624,15 @@ "bearer": [] } ], - "summary": "Browse entities", + "summary": "Decode a relation using bounded published vocabulary and relation-signature artifacts", "tags": [ - "graph" + "system" ] } }, - "/v1/graph/entities/filter": { - "post": { - "operationId": "post_v1_graph_entities_filter", + "/v1/demo/datasets": { + "get": { + "operationId": "get_v1_demo_datasets", "parameters": [ { "description": "Graph name (default `main`)", @@ -25977,40 +16653,21 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EntityFilterRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityFilterResponse" + "type": "object" } } }, @@ -26228,15 +16885,15 @@ "bearer": [] } ], - "summary": "Filter entities by typed properties in one loaded snapshot", + "summary": "List built-in demo datasets", "tags": [ - "graph" + "demo" ] } }, - "/v1/graph/entities/sample": { - "get": { - "operationId": "get_v1_graph_entities_sample", + "/v1/demo/download-public-datasets": { + "post": { + "operationId": "post_v1_demo_download_public_datasets", "parameters": [ { "description": "Graph name (default `main`)", @@ -26257,7 +16914,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -26266,27 +16923,18 @@ } }, { - "description": "Exact entity type", - "in": "query", - "name": "type", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Max sampled rows (up to 128)", - "in": "query", - "name": "limit", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } }, { - "description": "Accepted as strong or eventual; adjacency serves its newest published base+delta coverage without inspecting the live WAL tail in either mode", + "description": "Public dataset id", "in": "query", - "name": "consistency", + "name": "dataset", "required": false, "schema": { "type": "string" @@ -26298,7 +16946,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityTypeSampleResponse" + "type": "object" } } }, @@ -26516,15 +17164,15 @@ "bearer": [] } ], - "summary": "Bounded class sample from the ranged adjacency index", + "summary": "Download one public benchmark dataset sample into the local dataset cache", "tags": [ - "graph" + "demo" ] } }, - "/v1/graph/entity": { - "get": { - "operationId": "get_v1_graph_entity", + "/v1/demo/load": { + "post": { + "operationId": "post_v1_demo_load", "parameters": [ { "description": "Graph name (default `main`)", @@ -26545,7 +17193,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -26554,27 +17202,27 @@ } }, { - "description": "Entity id", - "in": "query", - "name": "id", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } }, { - "description": "Entity type for name-addressed lookup", + "description": "Dataset id", "in": "query", - "name": "type", + "name": "dataset", "required": false, "schema": { "type": "string" } }, { - "description": "Entity canonical name for name-addressed lookup", + "description": "Build indexes after loading", "in": "query", - "name": "name", + "name": "build", "required": false, "schema": { "type": "string" @@ -26586,7 +17234,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityDetailResponse" + "type": "object" } } }, @@ -26804,15 +17452,15 @@ "bearer": [] } ], - "summary": "Entity detail", + "summary": "Load a demo dataset, optionally building indexes", "tags": [ - "graph" + "demo" ] } }, - "/v1/graph/entity/metadata": { + "/v1/demo/public-datasets": { "get": { - "operationId": "get_v1_graph_entity_metadata", + "operationId": "get_v1_demo_public_datasets", "parameters": [ { "description": "Graph name (default `main`)", @@ -26833,45 +17481,288 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + }, + "description": "OK", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Bad request", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Unauthorized", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Forbidden", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Not found", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Conflict", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "429": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Rate limit exceeded", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Internal server error", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LbbErrorEnvelope" + } + } + }, + "description": "Service unavailable", + "headers": { + "Lbb-Version": { + "description": "API contract version used for the response", + "schema": { + "type": "string" + } + }, + "X-Request-Id": { + "description": "Request correlation id", + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ { - "description": "Entity id", + "bearer": [] + } + ], + "summary": "List public benchmark dataset availability", + "tags": [ + "demo" + ] + } + }, + "/v1/demo/run": { + "post": { + "operationId": "post_v1_demo_run", + "parameters": [ + { + "description": "Graph name (default `main`)", "in": "query", - "name": "id", + "name": "graph", "required": false, "schema": { "type": "string" } }, { - "description": "Entity type for name-addressed lookup", + "description": "Branch name (default `main`)", "in": "query", - "name": "type", + "name": "branch", "required": false, "schema": { "type": "string" } }, { - "description": "Entity canonical name for name-addressed lookup", - "in": "query", - "name": "name", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", + "in": "header", + "name": "Lbb-Version", "required": false, "schema": { "type": "string" } }, { - "description": "RFC3339 as-of timestamp", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Dataset id", "in": "query", - "name": "as_of", + "name": "dataset", "required": false, "schema": { "type": "string" @@ -26883,7 +17774,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityMetadataResponse" + "type": "object" } } }, @@ -27101,15 +17992,15 @@ "bearer": [] } ], - "summary": "Entity metadata, stored attributes, and immutable object reference status", + "summary": "Run canned checks against a demo dataset", "tags": [ - "graph" + "demo" ] } }, - "/v1/graph/entity/neighborhood": { - "get": { - "operationId": "get_v1_graph_entity_neighborhood", + "/v1/graph/branch": { + "delete": { + "operationId": "delete_v1_graph_branch", "parameters": [ { "description": "Graph name (default `main`)", @@ -27130,7 +18021,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -27139,54 +18030,18 @@ } }, { - "description": "Entity id", - "in": "query", - "name": "id", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Entity type for name-addressed lookup", - "in": "query", - "name": "type", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Entity canonical name for name-addressed lookup", - "in": "query", - "name": "name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Comma-separated relation filter", - "in": "query", - "name": "relations", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "RFC3339 as-of timestamp", - "in": "query", - "name": "as_of", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } }, { - "description": "When true, require ranged adjacency and never fall back to a whole-snapshot scan", + "description": "Must equal the target branch id", "in": "query", - "name": "indexed", + "name": "confirm", "required": false, "schema": { "type": "string" @@ -27198,7 +18053,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityNeighborhoodResponse" + "$ref": "#/components/schemas/GraphBranchDeleteResponse" } } }, @@ -27416,15 +18271,13 @@ "bearer": [] } ], - "summary": "Entity point lookup with its out/in neighborhood", + "summary": "Delete the scoped branch; refuses to delete a graph's final live branch", "tags": [ "graph" ] - } - }, - "/v1/graph/export": { - "get": { - "operationId": "get_v1_graph_export", + }, + "post": { + "operationId": "post_v1_graph_branch", "parameters": [ { "description": "Graph name (default `main`)", @@ -27445,7 +18298,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -27454,39 +18307,31 @@ } }, { - "description": "Records (entity+edge lines) per page (default 1000, clamped 1-50000)", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Opaque page cursor from a prior page's meta.next_cursor; pins the snapshot across pages", - "in": "query", - "name": "cursor", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Pin the export to a past snapshot commit_seq (first page only)", - "in": "query", - "name": "as_of_commit_seq", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GraphBranchCreateRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/GraphBranchCreateResponse" } } }, @@ -27704,15 +18549,15 @@ "bearer": [] } ], - "summary": "Stream a full-fidelity NDJSON export (inverse of /v1/graph/import): a kind-tagged meta header (with the source ontology), then entity and edge lines that reconstruct an equivalent graph on re-import. Paginated via meta.next_cursor echoed as ?cursor=", + "summary": "Fork the scoped branch from an existing branch in the same graph", "tags": [ "graph" ] } }, - "/v1/graph/export/job": { - "get": { - "operationId": "get_v1_graph_export_job", + "/v1/graph/branch/merge": { + "post": { + "operationId": "post_v1_graph_branch_merge", "parameters": [ { "description": "Graph name (default `main`)", @@ -27733,7 +18578,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -27742,21 +18587,31 @@ } }, { - "description": "The export job id returned by the enqueue call", - "in": "query", - "name": "job_id", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GraphBranchMergeRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/GraphBranchMergeResponse" } } }, @@ -27974,13 +18829,15 @@ "bearer": [] } ], - "summary": "Poll an enqueued background export job by ?job_id= (scoped to the requesting tenant)", + "summary": "Replay a child branch's post-fork commits onto the scoped branch (its fork parent) as one commit — validate-then-merge; requires an Idempotency-Key", "tags": [ "graph" ] - }, - "post": { - "operationId": "post_v1_graph_export_job", + } + }, + "/v1/graph/card": { + "get": { + "operationId": "get_v1_graph_card", "parameters": [ { "description": "Graph name (default `main`)", @@ -28001,31 +18858,13 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Pin the export to a past snapshot commit_seq", - "in": "query", - "name": "as_of_commit_seq", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -28033,7 +18872,7 @@ "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/GraphCard" } } }, @@ -28251,15 +19090,15 @@ "bearer": [] } ], - "summary": "Enqueue a background full-fidelity export for a large tenant; writes zstd NDJSON parts + a manifest under tenants//exports//. Returns the job id; poll with GET /v1/graph/export/job?job_id=", + "summary": "Per-snapshot self-description (types, relations, properties, top values)", "tags": [ "graph" ] } }, - "/v1/graph/export/rdf": { + "/v1/graph/changes": { "get": { - "operationId": "get_v1_graph_export_rdf", + "operationId": "get_v1_graph_changes", "parameters": [ { "description": "Graph name (default `main`)", @@ -28280,7 +19119,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -28289,63 +19128,18 @@ } }, { - "description": "RDF format: turtle (default), nt/ntriples, trig, or nq/nquads", - "in": "query", - "name": "format", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Output ceiling; rejects the full export, or bounds the JSON preview when truncate=true", - "in": "query", - "name": "max_triples", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Return a deterministic bounded JSON preview instead of rejecting when the graph is larger than max_triples", - "in": "query", - "name": "truncate", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "RFC3339 valid-time snapshot pin", - "in": "query", - "name": "as_of_valid_time", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Commit-sequence snapshot pin", - "in": "query", - "name": "as_of_commit_seq", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "subclass (default) or none", + "description": "Exclusive lower bound commit_seq (default 0)", "in": "query", - "name": "entailment", + "name": "since", "required": false, "schema": { "type": "string" } }, { - "description": "Include stored rule-derived facts when true", + "description": "Max records per page (default 500, max 5000)", "in": "query", - "name": "reason", + "name": "limit", "required": false, "schema": { "type": "string" @@ -28357,31 +19151,11 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RdfExportPreviewResponse" - } - }, - "application/n-quads": { - "schema": { - "type": "string" - } - }, - "application/n-triples": { - "schema": { - "type": "string" - } - }, - "application/trig": { - "schema": { - "type": "string" - } - }, - "text/turtle": { - "schema": { - "type": "string" + "$ref": "#/components/schemas/GraphChangesResponse" } } }, - "description": "RDF graph", + "description": "OK", "headers": { "Lbb-Version": { "description": "API contract version used for the response", @@ -28595,15 +19369,15 @@ "bearer": [] } ], - "summary": "Export the snapshot-visible RDF projection as Turtle, N-Triples, TriG, or N-Quads (hard 100,000-statement materialization ceiling)", + "summary": "Changes since a commit_seq (delta read); 409 with reset when since predates compaction", "tags": [ "graph" ] } }, - "/v1/graph/fork": { + "/v1/graph/commit": { "post": { - "operationId": "post_v1_graph_fork", + "operationId": "post_v1_graph_commit", "parameters": [ { "description": "Graph name (default `main`)", @@ -28624,7 +19398,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -28636,45 +19410,37 @@ "description": "Stable client-generated key for safely retrying mutations and supervision writes.", "in": "header", "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Source graph id to fork from", - "in": "query", - "name": "src", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Destination graph id to create (must not exist)", - "in": "query", - "name": "dst", - "required": false, + "required": true, "schema": { "type": "string" } }, { - "description": "Must equal the destination graph id to authorize the fork", + "description": "Validate only and return a GraphCommitDryRunResponse without writing (no Idempotency-Key required)", "in": "query", - "name": "confirm", + "name": "dry_run", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TripletCommitFile" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphForkResponse" + "$ref": "#/components/schemas/GraphCommitResponse" } } }, @@ -28892,15 +19658,15 @@ "bearer": [] } ], - "summary": "Fork a graph: copy-based clone of the source graph's current head into a new graph in the same tenant — no data replay, no re-embedding; runs as a durable job (poll the destination's metadata)", + "summary": "Commit triplets and optional entity embeddings", "tags": [ "graph" ] } }, - "/v1/graph/groundability": { - "get": { - "operationId": "get_v1_graph_groundability", + "/v1/graph/compact": { + "post": { + "operationId": "post_v1_graph_compact", "parameters": [ { "description": "Graph name (default `main`)", @@ -28921,7 +19687,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -28930,9 +19696,27 @@ } }, { - "description": "Entities to sample for name/recall probes (default 50, max 200)", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Minimum tail commits before compaction", "in": "query", - "name": "sample", + "name": "min_tail_commits", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Merge into at most this many segments", + "in": "query", + "name": "max_segments", "required": false, "schema": { "type": "string" @@ -28944,7 +19728,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroundabilityReport" + "$ref": "#/components/schemas/WalCompactResponse" } } }, @@ -29162,15 +19946,15 @@ "bearer": [] } ], - "summary": "Which completion mechanisms will carry on this graph", + "summary": "Fold the WAL tail into snapshot segments", "tags": [ "graph" ] } }, - "/v1/graph/import": { + "/v1/graph/create": { "post": { - "operationId": "post_v1_graph_import", + "operationId": "post_v1_graph_create", "parameters": [ { "description": "Graph name (default `main`)", @@ -29191,7 +19975,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -29207,33 +19991,6 @@ "schema": { "type": "string" } - }, - { - "description": "Records per internal commit (default 1000, clamped 1-10000)", - "in": "query", - "name": "batch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Abort on the first malformed line instead of skipping it", - "in": "query", - "name": "strict", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "RFC3339 backfill instant stamped on every batch", - "in": "query", - "name": "observed_at", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -29241,7 +19998,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphImportResponse" + "$ref": "#/components/schemas/CreateGraphResponse" } } }, @@ -29459,15 +20216,15 @@ "bearer": [] } ], - "summary": "Bulk-ingest a dataset as NDJSON (one triplet or entity-properties object per line); lines are batched into bounded internal commits", + "summary": "Create the scoped graph and branch", "tags": [ "graph" ] } }, - "/v1/graph/import/rdf": { + "/v1/graph/delete": { "post": { - "operationId": "post_v1_graph_import_rdf", + "operationId": "post_v1_graph_delete", "parameters": [ { "description": "Graph name (default `main`)", @@ -29488,7 +20245,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -29506,81 +20263,9 @@ } }, { - "description": "RDF statements per internal commit (default 1000, clamped 1-1000000)", - "in": "query", - "name": "batch", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Abort on the first malformed RDF parse error instead of reporting it", - "in": "query", - "name": "strict", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "RFC3339 backfill instant stamped on every batch", - "in": "query", - "name": "observed_at", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Edge duplicate handling: skip_unchanged (default) or append for fresh high-throughput loads", - "in": "query", - "name": "edge_idempotency", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "RDF format: ntriples (default), turtle, nquads, or trig", - "in": "query", - "name": "format", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Optional base IRI for resolving relative IRIs in Turtle or TriG", - "in": "query", - "name": "base_iri", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Optional named-graph IRI for N-Triples or Turtle input", - "in": "query", - "name": "graph_uri", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Optional stable document scope for blank-node labels across chunks; omit to preserve labels exactly across retries and chunk boundaries", - "in": "query", - "name": "blank_node_scope", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Entity type name for imported RDF resources (default Resource)", + "description": "Must equal the target graph id to authorize deletion", "in": "query", - "name": "resource_type", + "name": "confirm", "required": false, "schema": { "type": "string" @@ -29592,7 +20277,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphRdfImportResponse" + "$ref": "#/components/schemas/GraphDeleteResponse" } } }, @@ -29810,15 +20495,15 @@ "bearer": [] } ], - "summary": "Bulk-ingest N-Triples, Turtle, N-Quads, or TriG through the fixed RDF_TRIPLE relation; RDF terms and named-graph labels are preserved as edge metadata", + "summary": "Delete every branch and deregister the scoped graph; destructive and idempotent", "tags": [ "graph" ] } }, - "/v1/graph/metadata": { + "/v1/graph/embedding": { "get": { - "operationId": "get_v1_graph_metadata", + "operationId": "get_v1_graph_embedding", "parameters": [ { "description": "Graph name (default `main`)", @@ -29839,7 +20524,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -29853,7 +20538,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphMetadataResponse" + "$ref": "#/components/schemas/ManagedEmbeddingConfigResponse" } } }, @@ -30071,15 +20756,13 @@ "bearer": [] } ], - "summary": "Graph footprint, WAL tail, and index coverage", + "summary": "Read the graph branch's default managed embedding configuration", "tags": [ "graph" ] - } - }, - "/v1/graph/observations": { - "get": { - "operationId": "get_v1_graph_observations", + }, + "post": { + "operationId": "post_v1_graph_embedding", "parameters": [ { "description": "Graph name (default `main`)", @@ -30100,7 +20783,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -30109,39 +20792,31 @@ } }, { - "description": "Search text", - "in": "query", - "name": "q", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Max rows", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Opaque cursor from the previous page", - "in": "query", - "name": "cursor", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagedEmbeddingConfigRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/ManagedEmbeddingConfigResponse" } } }, @@ -30359,15 +21034,15 @@ "bearer": [] } ], - "summary": "Browse observations", + "summary": "Set the graph branch's default managed embedding configuration", "tags": [ "graph" ] } }, - "/v1/graph/query": { + "/v1/graph/embedding/backfill": { "post": { - "operationId": "post_v1_graph_query", + "operationId": "post_v1_graph_embedding_backfill", "parameters": [ { "description": "Graph name (default `main`)", @@ -30388,7 +21063,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -30404,13 +21079,40 @@ "schema": { "type": "string" } + }, + { + "description": "Embedding batch size (default 128, max 512)", + "in": "query", + "name": "batch_size", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Maximum entities to consider (default 100000)", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Re-embed all entities instead of only new entities", + "in": "query", + "name": "full", + "required": false, + "schema": { + "type": "string" + } } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlTextRequest" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobRequest" } } }, @@ -30421,7 +21123,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlTextResponse" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" } } }, @@ -30639,15 +21341,15 @@ "bearer": [] } ], - "summary": "Run a SPARQL query (text) against the graph — discoverable alias for /v1/query/sparql-text", + "summary": "Submit a durable managed-embedding backfill job (legacy path alias)", "tags": [ "graph" ] } }, - "/v1/graph/reload": { - "post": { - "operationId": "post_v1_graph_reload", + "/v1/graph/embedding/backfill-jobs": { + "delete": { + "operationId": "delete_v1_graph_embedding_backfill_jobs", "parameters": [ { "description": "Graph name (default `main`)", @@ -30668,7 +21370,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -30686,36 +21388,9 @@ } }, { - "description": "Must equal the target graph id (reload is semi-destructive)", - "in": "query", - "name": "confirm", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "true = preview the delta; nothing durable changes", - "in": "query", - "name": "dry_run", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "true = malformed payload lines fail the reload instead of being skipped and reported", - "in": "query", - "name": "strict", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Optional RFC3339 observation timestamp applied to the reload's writes", + "description": "Stable backfill job id", "in": "query", - "name": "observed_at", + "name": "job_id", "required": false, "schema": { "type": "string" @@ -30727,7 +21402,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphReloadResponse" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" } } }, @@ -30945,15 +21620,13 @@ "bearer": [] } ], - "summary": "Declarative full-state replace: body is bulk-import NDJSON of the desired state; entities absent from the payload leave current state (history kept for as_of), payload entities are upserted, and the cutover is one atomic visibility boundary. dry_run=true previews the full delta without changing anything", + "summary": "Request cancellation of a managed-embedding backfill job", "tags": [ "graph" ] - } - }, - "/v1/graph/retract": { - "post": { - "operationId": "post_v1_graph_retract", + }, + "get": { + "operationId": "get_v1_graph_embedding_backfill_jobs", "parameters": [ { "description": "Graph name (default `main`)", @@ -30974,7 +21647,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -30983,31 +21656,21 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "Stable backfill job id", + "in": "query", + "name": "job_id", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GraphRetractRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphRetractResponse" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" } } }, @@ -31225,15 +21888,13 @@ "bearer": [] } ], - "summary": "Retract specific edges and/or every edge touching given entities; appends superseding retract events (history is kept for as_of reads)", + "summary": "Read one managed-embedding backfill job", "tags": [ "graph" ] - } - }, - "/v1/graph/search": { + }, "post": { - "operationId": "post_v1_graph_search", + "operationId": "post_v1_graph_embedding_backfill_jobs", "parameters": [ { "description": "Graph name (default `main`)", @@ -31254,7 +21915,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -31276,7 +21937,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SemanticGraphSearchRequest" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobRequest" } } }, @@ -31287,7 +21948,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SemanticGraphSearchResponse" + "$ref": "#/components/schemas/ManagedEmbeddingBackfillJobStatusResponse" } } }, @@ -31505,15 +22166,15 @@ "bearer": [] } ], - "summary": "Full semantic hybrid search", + "summary": "Submit a durable managed-embedding backfill job", "tags": [ "graph" ] } }, - "/v1/graph/semantic-traverse": { - "post": { - "operationId": "post_v1_graph_semantic_traverse", + "/v1/graph/embedding/models": { + "get": { + "operationId": "get_v1_graph_embedding_models", "parameters": [ { "description": "Graph name (default `main`)", @@ -31534,40 +22195,21 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SemanticTraverseRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SemanticTraverseResponse" + "$ref": "#/components/schemas/ManagedEmbeddingModelsResponse" } } }, @@ -31785,15 +22427,15 @@ "bearer": [] } ], - "summary": "Resolve a query to seeds, then return bounded paths", + "summary": "List the embedding models available on this deployment", "tags": [ "graph" ] } }, - "/v1/graph/summary": { - "get": { - "operationId": "get_v1_graph_summary", + "/v1/graph/embedding/promote": { + "post": { + "operationId": "post_v1_graph_embedding_promote", "parameters": [ { "description": "Graph name (default `main`)", @@ -31814,13 +22456,40 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } + }, + { + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Finished training run identifier", + "in": "query", + "name": "run_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Allow promotion when evaluation quality regressed", + "in": "query", + "name": "allow_regression", + "required": false, + "schema": { + "type": "string" + } } ], "responses": { @@ -31828,7 +22497,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphSummaryResponse" + "$ref": "#/components/schemas/ManagedEmbeddingPromoteResponse" } } }, @@ -32046,15 +22715,15 @@ "bearer": [] } ], - "summary": "Graph counts and type/relation buckets", + "summary": "Promote a successful fine-tuned embedding run to the graph default", "tags": [ "graph" ] } }, - "/v1/graph/traverse": { + "/v1/graph/entities/sample": { "get": { - "operationId": "get_v1_graph_traverse", + "operationId": "get_v1_graph_entities_sample", "parameters": [ { "description": "Graph name (default `main`)", @@ -32075,7 +22744,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -32084,27 +22753,27 @@ } }, { - "description": "Start entity id", + "description": "Exact entity type", "in": "query", - "name": "id", + "name": "type", "required": false, "schema": { "type": "string" } }, { - "description": "out, in, or both", + "description": "Max sampled rows (up to 128)", "in": "query", - "name": "direction", + "name": "limit", "required": false, "schema": { "type": "string" } }, { - "description": "Hop budget", + "description": "Accepted as strong or eventual; adjacency serves the exact immutable base pinned by the published generation without inspecting the live WAL in either mode", "in": "query", - "name": "max_hops", + "name": "consistency", "required": false, "schema": { "type": "string" @@ -32116,7 +22785,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TraverseResponse" + "$ref": "#/components/schemas/EntityTypeSampleResponse" } } }, @@ -32334,13 +23003,15 @@ "bearer": [] } ], - "summary": "Bounded graph traversal (query-string convenience)", + "summary": "Bounded class sample from the ranged adjacency index", "tags": [ "graph" ] - }, - "post": { - "operationId": "post_v1_graph_traverse", + } + }, + "/v1/graph/entity": { + "get": { + "operationId": "get_v1_graph_entity", "parameters": [ { "description": "Graph name (default `main`)", @@ -32361,7 +23032,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -32370,31 +23041,39 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "Entity id", + "in": "query", + "name": "id", "required": false, "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TraverseRequest" - } + }, + { + "description": "Entity type for name-addressed lookup", + "in": "query", + "name": "type", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "Entity canonical name for name-addressed lookup", + "in": "query", + "name": "name", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TraverseResponse" + "$ref": "#/components/schemas/EntityDetailResponse" } } }, @@ -32612,15 +23291,15 @@ "bearer": [] } ], - "summary": "Bounded graph traversal", + "summary": "Entity detail", "tags": [ "graph" ] } }, - "/v1/graphs": { + "/v1/graph/entity/metadata": { "get": { - "operationId": "get_v1_graphs", + "operationId": "get_v1_graph_entity_metadata", "parameters": [ { "description": "Graph name (default `main`)", @@ -32641,7 +23320,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -32650,18 +23329,36 @@ } }, { - "description": "Max rows", + "description": "Entity id", "in": "query", - "name": "limit", + "name": "id", "required": false, "schema": { "type": "string" } }, { - "description": "Opaque cursor from the previous page", + "description": "Entity type for name-addressed lookup", "in": "query", - "name": "cursor", + "name": "type", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Entity canonical name for name-addressed lookup", + "in": "query", + "name": "name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "RFC3339 as-of timestamp", + "in": "query", + "name": "as_of", "required": false, "schema": { "type": "string" @@ -32673,7 +23370,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GraphListResponse" + "$ref": "#/components/schemas/EntityMetadataResponse" } } }, @@ -32891,15 +23588,15 @@ "bearer": [] } ], - "summary": "List the graphs (and branches) under the scoped tenant", + "summary": "Entity metadata, stored attributes, and immutable object reference status", "tags": [ "graph" ] } }, - "/v1/index": { + "/v1/graph/entity/neighborhood": { "get": { - "operationId": "get_v1_index", + "operationId": "get_v1_graph_entity_neighborhood", "parameters": [ { "description": "Graph name (default `main`)", @@ -32920,7 +23617,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -32929,9 +23626,45 @@ } }, { - "description": "Index source: persisted or ephemeral", + "description": "Entity id", "in": "query", - "name": "source", + "name": "id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Entity type for name-addressed lookup", + "in": "query", + "name": "type", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Entity canonical name for name-addressed lookup", + "in": "query", + "name": "name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Comma-separated relation filter", + "in": "query", + "name": "relations", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "RFC3339 as-of timestamp", + "in": "query", + "name": "as_of", "required": false, "schema": { "type": "string" @@ -32943,7 +23676,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EmbeddingIndexInspectResponse" + "$ref": "#/components/schemas/EntityNeighborhoodResponse" } } }, @@ -33161,15 +23894,15 @@ "bearer": [] } ], - "summary": "Inspect the embedding index", + "summary": "Entity point lookup with its out/in neighborhood", "tags": [ - "indexes" + "graph" ] } }, - "/v1/index/build": { - "post": { - "operationId": "post_v1_index_build", + "/v1/graph/export/job": { + "get": { + "operationId": "get_v1_graph_export_job", "parameters": [ { "description": "Graph name (default `main`)", @@ -33190,7 +23923,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -33199,34 +23932,15 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Run the build detached and return immediately; poll /v1/graph/metadata for completion", + "description": "The export job id returned by the enqueue call", "in": "query", - "name": "background", + "name": "job_id", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IndexBuildOptions" - } - } - }, - "required": true - }, "responses": { "200": { "content": { @@ -33450,15 +24164,13 @@ "bearer": [] } ], - "summary": "Build default ANN and BM25 indexes; optional body selects the embedding provider (e.g. stored BYO vectors)", + "summary": "Poll an enqueued background export job by ?job_id= (scoped to the requesting tenant)", "tags": [ - "indexes" + "graph" ] - } - }, - "/v1/index/delta": { + }, "post": { - "operationId": "post_v1_index_delta", + "operationId": "post_v1_graph_export_job", "parameters": [ { "description": "Graph name (default `main`)", @@ -33479,7 +24191,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -33495,6 +24207,15 @@ "schema": { "type": "string" } + }, + { + "description": "Pin the export to a past snapshot commit_seq", + "in": "query", + "name": "as_of_commit_seq", + "required": false, + "schema": { + "type": "string" + } } ], "responses": { @@ -33502,7 +24223,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IndexDeltaResponse" + "type": "object" } } }, @@ -33720,15 +24441,15 @@ "bearer": [] } ], - "summary": "Append a BM25 delta segment for the unindexed WAL tail", + "summary": "Enqueue a background full-fidelity export for a large tenant; writes zstd NDJSON parts + a manifest under tenants//exports//. Returns the job id; poll with GET /v1/graph/export/job?job_id=", "tags": [ - "indexes" + "graph" ] } }, - "/v1/index/gc": { + "/v1/graph/fork": { "post": { - "operationId": "post_v1_index_gc", + "operationId": "post_v1_graph_fork", "parameters": [ { "description": "Graph name (default `main`)", @@ -33749,7 +24470,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -33767,27 +24488,27 @@ } }, { - "description": "Number of newest runs to keep", + "description": "Source graph id to fork from", "in": "query", - "name": "keep_runs", + "name": "src", "required": false, "schema": { "type": "string" } }, { - "description": "Retain runs within this many commits of head so in-flight searches are not collected mid-read", + "description": "Destination graph id to create (must not exist)", "in": "query", - "name": "reader_grace_commits", + "name": "dst", "required": false, "schema": { "type": "string" } }, { - "description": "Report without deleting", + "description": "Must equal the destination graph id to authorize the fork", "in": "query", - "name": "dry_run", + "name": "confirm", "required": false, "schema": { "type": "string" @@ -33799,7 +24520,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IndexGcResponse" + "$ref": "#/components/schemas/GraphForkResponse" } } }, @@ -34017,15 +24738,15 @@ "bearer": [] } ], - "summary": "Preview or delete superseded persisted index runs", + "summary": "Fork a graph: copy-based clone of the source graph's current head into a new graph in the same tenant — no data replay, no re-embedding; runs as a durable job (poll the destination's metadata)", "tags": [ - "indexes" + "graph" ] } }, - "/v1/index/gc-jobs": { - "delete": { - "operationId": "delete_v1_index_gc_jobs", + "/v1/graph/groundability": { + "get": { + "operationId": "get_v1_graph_groundability", "parameters": [ { "description": "Graph name (default `main`)", @@ -34046,7 +24767,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -34055,18 +24776,9 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable id returned by the submit call", + "description": "Requested published sample window (default 50, max 200)", "in": "query", - "name": "job_id", + "name": "sample", "required": false, "schema": { "type": "string" @@ -34078,7 +24790,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IndexGcJobStatusResponse" + "$ref": "#/components/schemas/GroundabilityReport" } } }, @@ -34296,13 +25008,15 @@ "bearer": [] } ], - "summary": "Cancel a graph-scoped index garbage-collection job", + "summary": "Read the bounded published groundability artifact; returns typed unavailable until maintenance has published one", "tags": [ - "indexes" + "graph" ] - }, - "get": { - "operationId": "get_v1_index_gc_jobs", + } + }, + "/v1/graph/import": { + "post": { + "operationId": "post_v1_graph_import", "parameters": [ { "description": "Graph name (default `main`)", @@ -34323,7 +25037,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -34332,9 +25046,45 @@ } }, { - "description": "Stable id returned by the submit call", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Records per internal commit (default 1000, clamped 1-10000)", "in": "query", - "name": "job_id", + "name": "batch", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Abort on the first malformed line instead of skipping it", + "in": "query", + "name": "strict", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "RFC3339 backfill instant stamped on every batch", + "in": "query", + "name": "observed_at", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Durably enqueue one atomic published-generation build after the final batch", + "in": "query", + "name": "publish", "required": false, "schema": { "type": "string" @@ -34346,7 +25096,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IndexGcJobStatusResponse" + "$ref": "#/components/schemas/GraphImportResponse" } } }, @@ -34564,13 +25314,15 @@ "bearer": [] } ], - "summary": "Poll a graph-scoped index garbage-collection job", + "summary": "Bulk-ingest a dataset as NDJSON (one triplet or entity-properties object per line); lines are batched into bounded internal commits", "tags": [ - "indexes" + "graph" ] - }, + } + }, + "/v1/graph/import/rdf": { "post": { - "operationId": "post_v1_index_gc_jobs", + "operationId": "post_v1_graph_import_rdf", "parameters": [ { "description": "Graph name (default `main`)", @@ -34591,7 +25343,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -34607,24 +25359,104 @@ "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IndexGcRequest" - } + }, + { + "description": "RDF statements per internal commit (default 1000, clamped 1-1000000)", + "in": "query", + "name": "batch", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "Abort on the first malformed RDF parse error instead of reporting it", + "in": "query", + "name": "strict", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "RFC3339 backfill instant stamped on every batch", + "in": "query", + "name": "observed_at", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Edge duplicate handling: skip_unchanged (default) or append for fresh high-throughput loads", + "in": "query", + "name": "edge_idempotency", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "RDF format: ntriples (default), turtle, nquads, or trig", + "in": "query", + "name": "format", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Optional base IRI for resolving relative IRIs in Turtle or TriG", + "in": "query", + "name": "base_iri", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Optional named-graph IRI for N-Triples or Turtle input", + "in": "query", + "name": "graph_uri", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Optional stable document scope for blank-node labels across chunks; omit to preserve labels exactly across retries and chunk boundaries", + "in": "query", + "name": "blank_node_scope", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Entity type name for imported RDF resources (default Resource)", + "in": "query", + "name": "resource_type", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Durably enqueue one atomic published-generation build after the final batch", + "in": "query", + "name": "publish", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IndexGcJobStatusResponse" + "$ref": "#/components/schemas/GraphRdfImportResponse" } } }, @@ -34842,15 +25674,15 @@ "bearer": [] } ], - "summary": "Idempotently enqueue durable index garbage collection with byte/object progress", + "summary": "Bulk-ingest N-Triples, Turtle, N-Quads, or TriG through the fixed RDF_TRIPLE relation; RDF terms and named-graph labels are preserved as edge metadata", "tags": [ - "indexes" + "graph" ] } }, - "/v1/index/jobs": { - "delete": { - "operationId": "delete_v1_index_jobs", + "/v1/graph/metadata": { + "get": { + "operationId": "get_v1_graph_metadata", "parameters": [ { "description": "Graph name (default `main`)", @@ -34871,31 +25703,13 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Stable id returned by the submit call", - "in": "query", - "name": "job_id", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -34903,7 +25717,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchIndexJobStatusResponse" + "$ref": "#/components/schemas/GraphMetadataResponse" } } }, @@ -35121,13 +25935,15 @@ "bearer": [] } ], - "summary": "Cancel a graph-scoped durable full-index job", + "summary": "Graph footprint, WAL tail, and index coverage", "tags": [ - "indexes" + "graph" ] - }, - "get": { - "operationId": "get_v1_index_jobs", + } + }, + "/v1/graph/query": { + "post": { + "operationId": "post_v1_graph_query", "parameters": [ { "description": "Graph name (default `main`)", @@ -35148,7 +25964,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -35157,21 +25973,31 @@ } }, { - "description": "Stable id returned by the submit call", - "in": "query", - "name": "job_id", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SparqlTextRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchIndexJobStatusResponse" + "$ref": "#/components/schemas/SparqlTextResponse" } } }, @@ -35389,13 +26215,15 @@ "bearer": [] } ], - "summary": "Poll a graph-scoped index job for progress, terminal error, and per-family coverage", + "summary": "Run a SPARQL query (text) against the graph — discoverable alias for /v1/query/sparql-text", "tags": [ - "indexes" + "graph" ] - }, - "post": { - "operationId": "post_v1_index_jobs", + } + }, + "/v1/graph/read-snapshot": { + "get": { + "operationId": "get_v1_graph_read_snapshot", "parameters": [ { "description": "Graph name (default `main`)", @@ -35416,40 +26244,21 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IndexBuildOptions" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchIndexJobStatusResponse" + "$ref": "#/components/schemas/PublishedReadStatusResponse" } } }, @@ -35667,15 +26476,15 @@ "bearer": [] } ], - "summary": "Idempotently enqueue a durable full-index job with typed per-family terminal status", + "summary": "Pinned published read root, same-epoch graph head, and query/conformance lag", "tags": [ - "indexes" + "graph" ] } }, - "/v1/index/run": { + "/v1/graph/reload": { "post": { - "operationId": "post_v1_index_run", + "operationId": "post_v1_graph_reload", "parameters": [ { "description": "Graph name (default `main`)", @@ -35696,7 +26505,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -35714,31 +26523,48 @@ } }, { - "description": "Run the build detached and return immediately; poll /v1/graph/metadata for completion", + "description": "Must equal the target graph id (reload is semi-destructive)", "in": "query", - "name": "background", + "name": "confirm", "required": false, "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IndexBuildOptions" - } + }, + { + "description": "true = preview the delta; nothing durable changes", + "in": "query", + "name": "dry_run", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "true = malformed payload lines fail the reload instead of being skipped and reported", + "in": "query", + "name": "strict", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Optional RFC3339 observation timestamp applied to the reload's writes", + "in": "query", + "name": "observed_at", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SearchIndexRunResponse" + "$ref": "#/components/schemas/GraphReloadResponse" } } }, @@ -35956,15 +26782,15 @@ "bearer": [] } ], - "summary": "Build BM25, ANN/vector, and adjacency index families; optional body selects the embedding provider (e.g. stored BYO vectors)", + "summary": "Declarative full-state replace: body is bulk-import NDJSON of the desired state; entities absent from the payload leave current state (history kept for as_of), payload entities are upserted, and the cutover is one atomic visibility boundary. dry_run=true previews the full delta without changing anything", "tags": [ - "indexes" + "graph" ] } }, - "/v1/inference/retrieval-premises": { + "/v1/graph/retract": { "post": { - "operationId": "post_v1_inference_retrieval_premises", + "operationId": "post_v1_graph_retract", "parameters": [ { "description": "Graph name (default `main`)", @@ -35985,7 +26811,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -36007,7 +26833,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RetrievalPremiseRequest" + "$ref": "#/components/schemas/GraphRetractRequest" } } }, @@ -36018,7 +26844,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RetrievalPremiseResponse" + "$ref": "#/components/schemas/GraphRetractResponse" } } }, @@ -36236,15 +27062,15 @@ "bearer": [] } ], - "summary": "Stage G — derive edges from calibrated retrieval candidates (typed Retrieval provenance, snapshot-pinned confidence)", + "summary": "Retract specific edges and/or every edge touching given entities; appends superseding retract events (history is kept for as_of reads)", "tags": [ - "inference" + "graph" ] } }, - "/v1/inference/rules": { - "get": { - "operationId": "get_v1_inference_rules", + "/v1/graph/search": { + "post": { + "operationId": "post_v1_graph_search", "parameters": [ { "description": "Graph name (default `main`)", @@ -36265,21 +27091,40 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } + }, + { + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SemanticGraphSearchRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleSet" + "$ref": "#/components/schemas/SemanticGraphSearchResponse" } } }, @@ -36497,13 +27342,15 @@ "bearer": [] } ], - "summary": "Read the branch's stored inference rule set", + "summary": "Full semantic hybrid search", "tags": [ - "inference" + "graph" ] - }, + } + }, + "/v1/graph/semantic-traverse": { "post": { - "operationId": "post_v1_inference_rules", + "operationId": "post_v1_graph_semantic_traverse", "parameters": [ { "description": "Graph name (default `main`)", @@ -36524,7 +27371,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -36546,7 +27393,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleSetDefineRequest" + "$ref": "#/components/schemas/SemanticTraverseRequest" } } }, @@ -36557,7 +27404,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleSetDefineResponse" + "$ref": "#/components/schemas/SemanticTraverseResponse" } } }, @@ -36775,15 +27622,15 @@ "bearer": [] } ], - "summary": "Define (replace) the branch's stored inference rule set", + "summary": "Resolve a query to seeds, then return bounded paths", "tags": [ - "inference" + "graph" ] } }, - "/v1/inference/run": { - "post": { - "operationId": "post_v1_inference_run", + "/v1/graph/summary": { + "get": { + "operationId": "get_v1_graph_summary", "parameters": [ { "description": "Graph name (default `main`)", @@ -36804,40 +27651,21 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InferenceRunRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InferenceRunResponse" + "$ref": "#/components/schemas/GraphSummaryResponse" } } }, @@ -37055,15 +27883,15 @@ "bearer": [] } ], - "summary": "Run inference rules to a bounded fixpoint; preview derived edges (never written)", + "summary": "Graph counts and type/relation buckets", "tags": [ - "inference" + "graph" ] } }, - "/v1/memory/observe": { - "post": { - "operationId": "post_v1_memory_observe", + "/v1/graph/traverse": { + "get": { + "operationId": "get_v1_graph_traverse", "parameters": [ { "description": "Graph name (default `main`)", @@ -37084,7 +27912,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -37093,31 +27921,39 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "Start entity id", + "in": "query", + "name": "id", "required": false, "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ObserveRequest" - } + }, + { + "description": "out, in, or both", + "in": "query", + "name": "direction", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "Hop budget", + "in": "query", + "name": "max_hops", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ObserveResponse" + "$ref": "#/components/schemas/TraverseResponse" } } }, @@ -37335,15 +28171,13 @@ "bearer": [] } ], - "summary": "Observe a conversation episode: store it verbatim as EPISODE evidence, anchor and gate extracted facts on an observe branch, optionally auto-merge when validation is clean; requires an Idempotency-Key (flag-gated: --enable-observe)", + "summary": "Bounded graph traversal (query-string convenience)", "tags": [ - "system" + "graph" ] - } - }, - "/v1/models/cadence": { - "get": { - "operationId": "get_v1_models_cadence", + }, + "post": { + "operationId": "post_v1_graph_traverse", "parameters": [ { "description": "Graph name (default `main`)", @@ -37364,7 +28198,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -37373,21 +28207,31 @@ } }, { - "description": "Model kind", - "in": "query", - "name": "kind", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TraverseRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelCadenceResponse" + "$ref": "#/components/schemas/TraverseResponse" } } }, @@ -37605,15 +28449,15 @@ "bearer": [] } ], - "summary": "Doubling retrain policy for a model kind: retrain_due when the graph doubled since the promoted run trained", + "summary": "Bounded graph traversal", "tags": [ - "system" + "graph" ] } }, - "/v1/models/extractor-dataset": { + "/v1/graphs": { "get": { - "operationId": "get_v1_models_extractor_dataset", + "operationId": "get_v1_graphs", "parameters": [ { "description": "Graph name (default `main`)", @@ -37634,7 +28478,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -37643,7 +28487,7 @@ } }, { - "description": "Max episodes (default 200, cap 500)", + "description": "Max rows", "in": "query", "name": "limit", "required": false, @@ -37652,9 +28496,9 @@ } }, { - "description": "Consume facts committed ≤ this seq (default: head)", + "description": "Opaque cursor from the previous page", "in": "query", - "name": "split_seq", + "name": "cursor", "required": false, "schema": { "type": "string" @@ -37666,7 +28510,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ExtractorDatasetResponse" + "$ref": "#/components/schemas/GraphListResponse" } } }, @@ -37884,15 +28728,15 @@ "bearer": [] } ], - "summary": "The extractor fine-tune's training feed: EPISODE transcripts joined (via evidence observations) to the facts the observe pipeline committed from them, plus the serving prompt's ontology vocabulary", + "summary": "List the graphs (and branches) under the scoped tenant", "tags": [ - "system" + "graph" ] } }, - "/v1/models/planner-dataset": { - "get": { - "operationId": "get_v1_models_planner_dataset", + "/v1/memory/observe": { + "post": { + "operationId": "post_v1_memory_observe", "parameters": [ { "description": "Graph name (default `main`)", @@ -37913,7 +28757,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -37922,30 +28766,31 @@ } }, { - "description": "Max examples (default 500, cap 2000)", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Consume signals ≤ this seq (default: head — recorded for the split audit)", - "in": "query", - "name": "split_seq", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObserveRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlannerDatasetResponse" + "$ref": "#/components/schemas/ObserveResponse" } } }, @@ -38163,15 +29008,15 @@ "bearer": [] } ], - "summary": "The planner fine-tune's training feed: accepted/corrected feedback joined to traces (signals ≤ the split pin), topped up with execution-verified synthetic plans", + "summary": "Observe a conversation episode: store it verbatim as EPISODE evidence, anchor and gate extracted facts on an observe branch, optionally auto-merge when validation is clean; requires an Idempotency-Key (flag-gated: --enable-observe)", "tags": [ "system" ] } }, - "/v1/models/planner-preference-dataset": { + "/v1/models/cadence": { "get": { - "operationId": "get_v1_models_planner_preference_dataset", + "operationId": "get_v1_models_cadence", "parameters": [ { "description": "Graph name (default `main`)", @@ -38192,7 +29037,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -38201,18 +29046,9 @@ } }, { - "description": "Max pairs (default 500, cap 2000)", - "in": "query", - "name": "limit", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Consume signals ≤ this seq (default: head — recorded for the split audit)", + "description": "Model kind", "in": "query", - "name": "split_seq", + "name": "kind", "required": false, "schema": { "type": "string" @@ -38224,7 +29060,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlannerPreferenceDatasetResponse" + "$ref": "#/components/schemas/ModelCadenceResponse" } } }, @@ -38442,15 +29278,15 @@ "bearer": [] } ], - "summary": "The DPO pass's training feed: preference pairs from corrected verdicts (decoded vs corrected plan), rejections paired with same-question accepted plans, and synthetic corrupted-slot pairs; unpaired rejections are counted", + "summary": "Doubling retrain policy for a model kind: retrain_due when the graph doubled since the promoted run trained", "tags": [ "system" ] } }, - "/v1/models/promote": { - "post": { - "operationId": "post_v1_models_promote", + "/v1/models/extractor-dataset": { + "get": { + "operationId": "get_v1_models_extractor_dataset", "parameters": [ { "description": "Graph name (default `main`)", @@ -38471,7 +29307,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -38480,27 +29316,18 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "Model kind (embedding|calibration|fusion|suggest_ranker|planner|extractor)", + "description": "Max episodes (default 200, cap 500)", "in": "query", - "name": "kind", + "name": "limit", "required": false, "schema": { "type": "string" } }, { - "description": "Run number to promote", + "description": "Maximum fact sequence included", "in": "query", - "name": "run", + "name": "split_seq", "required": false, "schema": { "type": "string" @@ -38512,7 +29339,7 @@ "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/ExtractorDatasetResponse" } } }, @@ -38730,15 +29557,15 @@ "bearer": [] } ], - "summary": "CAS-promote a recorded run to CURRENT for its kind (manifests stay immutable; replay is a no-op)", + "summary": "Fetch the bounded published extractor training artifact", "tags": [ "system" ] } }, - "/v1/models/promote-extractor": { - "post": { - "operationId": "post_v1_models_promote_extractor", + "/v1/models/planner-dataset": { + "get": { + "operationId": "get_v1_models_planner_dataset", "parameters": [ { "description": "Graph name (default `main`)", @@ -38759,7 +29586,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -38768,27 +29595,18 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "The extractor_lora training run to promote", + "description": "Max examples (default 500, cap 2000)", "in": "query", - "name": "run_id", + "name": "limit", "required": false, "schema": { "type": "string" } }, { - "description": "Promote even when tuned fact F1 regressed", + "description": "Maximum signal sequence included", "in": "query", - "name": "allow_regression", + "name": "split_seq", "required": false, "schema": { "type": "string" @@ -38800,7 +29618,7 @@ "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/PlannerDatasetResponse" } } }, @@ -39018,15 +29836,15 @@ "bearer": [] } ], - "summary": "Promote a finished extractor_lora run: gate on held-out fact F1 (?allow_regression=true to override), record a WS9 kind=extractor manifest with the adapter artifact, CAS-promote — resident extraction then serves the adapter", + "summary": "Fetch the bounded published planner training artifact", "tags": [ "system" ] } }, - "/v1/models/promote-planner": { - "post": { - "operationId": "post_v1_models_promote_planner", + "/v1/models/planner-preference-dataset": { + "get": { + "operationId": "get_v1_models_planner_preference_dataset", "parameters": [ { "description": "Graph name (default `main`)", @@ -39047,7 +29865,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -39056,27 +29874,18 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, - { - "description": "The planner_lora training run to promote", + "description": "Max pairs (default 500, cap 2000)", "in": "query", - "name": "run_id", + "name": "limit", "required": false, "schema": { "type": "string" } }, { - "description": "Promote even when tuned slot exactness regressed", + "description": "Maximum signal sequence included", "in": "query", - "name": "allow_regression", + "name": "split_seq", "required": false, "schema": { "type": "string" @@ -39088,7 +29897,7 @@ "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/PlannerPreferenceDatasetResponse" } } }, @@ -39306,15 +30115,15 @@ "bearer": [] } ], - "summary": "Promote a finished planner_lora run: gate on held-out slot exactness (?allow_regression=true to override), record a WS9 kind=planner manifest with the adapter artifact, CAS-promote — /v1/ask then serves the adapter", + "summary": "Fetch the bounded published planner preference artifact", "tags": [ "system" ] } }, - "/v1/models/record": { + "/v1/models/promote": { "post": { - "operationId": "post_v1_models_record", + "operationId": "post_v1_models_promote", "parameters": [ { "description": "Graph name (default `main`)", @@ -39335,7 +30144,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -39351,18 +30160,26 @@ "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelRunManifest" - } + }, + { + "description": "Model kind (embedding|calibration|fusion|suggest_ranker|planner|extractor)", + "in": "query", + "name": "kind", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "Run number to promote", + "in": "query", + "name": "run", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -39586,15 +30403,15 @@ "bearer": [] } ], - "summary": "Record one immutable model-as-run manifest in the registry (WS9); runs number sequentially per kind", + "summary": "CAS-promote a recorded run to CURRENT for its kind (manifests stay immutable; replay is a no-op)", "tags": [ "system" ] } }, - "/v1/models/registry": { - "get": { - "operationId": "get_v1_models_registry", + "/v1/models/promote-extractor": { + "post": { + "operationId": "post_v1_models_promote_extractor", "parameters": [ { "description": "Graph name (default `main`)", @@ -39615,7 +30432,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -39624,9 +30441,27 @@ } }, { - "description": "Model kind", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "The extractor_lora training run to promote", "in": "query", - "name": "kind", + "name": "run_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Promote even when tuned fact F1 regressed", + "in": "query", + "name": "allow_regression", "required": false, "schema": { "type": "string" @@ -39638,7 +30473,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelRegistryResponse" + "type": "object" } } }, @@ -39856,15 +30691,15 @@ "bearer": [] } ], - "summary": "List a kind's model runs newest-first with effective promotion state", + "summary": "Promote a finished extractor_lora run: gate on held-out fact F1 (?allow_regression=true to override), record a WS9 kind=extractor manifest with the adapter artifact, CAS-promote — resident extraction then serves the adapter", "tags": [ "system" ] } }, - "/v1/models/registry/gc": { + "/v1/models/promote-planner": { "post": { - "operationId": "post_v1_models_registry_gc", + "operationId": "post_v1_models_promote_planner", "parameters": [ { "description": "Graph name (default `main`)", @@ -39885,7 +30720,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -39903,18 +30738,18 @@ } }, { - "description": "Model kind", + "description": "The planner_lora training run to promote", "in": "query", - "name": "kind", + "name": "run_id", "required": false, "schema": { "type": "string" } }, { - "description": "Most-recent runs to keep besides the promoted one (default 3)", + "description": "Promote even when tuned slot exactness regressed", "in": "query", - "name": "keep", + "name": "allow_regression", "required": false, "schema": { "type": "string" @@ -40144,15 +30979,15 @@ "bearer": [] } ], - "summary": "Delete run prefixes beyond the promoted run + the last N; reports deleted runs", + "summary": "Promote a finished planner_lora run: gate on held-out slot exactness (?allow_regression=true to override), record a WS9 kind=planner manifest with the adapter artifact, then CAS-promote", "tags": [ "system" ] } }, - "/v1/models/shadow-eval": { + "/v1/models/record": { "post": { - "operationId": "post_v1_models_shadow_eval", + "operationId": "post_v1_models_record", "parameters": [ { "description": "Graph name (default `main`)", @@ -40173,7 +31008,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -40195,7 +31030,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ShadowEvalRequest" + "$ref": "#/components/schemas/ModelRunManifest" } } }, @@ -40206,7 +31041,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ShadowEvalResponse" + "type": "object" } } }, @@ -40424,15 +31259,15 @@ "bearer": [] } ], - "summary": "Champion vs challenger retrieval over one pinned snapshot: per-arm hit-rate@k + latency + per-query overlap; returns evidence, never promotes", + "summary": "Record one immutable model-as-run manifest in the registry (WS9); runs number sequentially per kind", "tags": [ "system" ] } }, - "/v1/models/split-audit": { + "/v1/models/registry": { "get": { - "operationId": "get_v1_models_split_audit", + "operationId": "get_v1_models_registry", "parameters": [ { "description": "Graph name (default `main`)", @@ -40453,7 +31288,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -40469,15 +31304,6 @@ "schema": { "type": "string" } - }, - { - "description": "Run number", - "in": "query", - "name": "run", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -40485,7 +31311,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelSplitAudit" + "$ref": "#/components/schemas/ModelRegistryResponse" } } }, @@ -40703,15 +31529,15 @@ "bearer": [] } ], - "summary": "Verify a run's temporal-split obligation from its recorded lineage (train ≤ pin, eval > pin)", + "summary": "List a kind's model runs newest-first with effective promotion state", "tags": [ "system" ] } }, - "/v1/models/suggest-dataset": { - "get": { - "operationId": "get_v1_models_suggest_dataset", + "/v1/models/registry/gc": { + "post": { + "operationId": "post_v1_models_registry_gc", "parameters": [ { "description": "Graph name (default `main`)", @@ -40732,7 +31558,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -40741,18 +31567,27 @@ } }, { - "description": "Max probes (default 100, cap 200)", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Model kind", "in": "query", - "name": "limit", + "name": "kind", "required": false, "schema": { "type": "string" } }, { - "description": "Consume signals ≤ this seq (default: head — recorded for the split audit)", + "description": "Most-recent runs to keep besides the promoted one (default 3)", "in": "query", - "name": "split_seq", + "name": "keep", "required": false, "schema": { "type": "string" @@ -40764,7 +31599,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SuggestDatasetResponse" + "type": "object" } } }, @@ -40982,15 +31817,15 @@ "bearer": [] } ], - "summary": "The suggest-ranker trainer's probe feed: suggestion_adopted signals (typed prefix + adopted text) ≤ the split pin, topped up with execution-verified synthetic vocabulary pairs", + "summary": "Delete run prefixes beyond the promoted run + the last N; reports deleted runs", "tags": [ "system" ] } }, - "/v1/models/synthetic-eval": { - "get": { - "operationId": "get_v1_models_synthetic_eval", + "/v1/models/shadow-eval": { + "post": { + "operationId": "post_v1_models_shadow_eval", "parameters": [ { "description": "Graph name (default `main`)", @@ -41011,7 +31846,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -41020,21 +31855,31 @@ } }, { - "description": "Max probes (default 100, max 500)", - "in": "query", - "name": "limit", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShadowEvalRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SyntheticEvalResponse" + "$ref": "#/components/schemas/ShadowEvalResponse" } } }, @@ -41252,15 +32097,15 @@ "bearer": [] } ], - "summary": "Execution-verified QA probes generated from current edges (labels are the executed projections; deterministic per snapshot)", + "summary": "Run a bounded champion/challenger evaluation on one published generation; returns typed unavailable until the generation-pinned evaluator artifact is enabled", "tags": [ "system" ] } }, - "/v1/models/train-jobs": { + "/v1/models/split-audit": { "get": { - "operationId": "get_v1_models_train_jobs", + "operationId": "get_v1_models_split_audit", "parameters": [ { "description": "Graph name (default `main`)", @@ -41281,7 +32126,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -41290,9 +32135,18 @@ } }, { - "description": "Stable job id returned by the submit call", + "description": "Model kind", "in": "query", - "name": "job_id", + "name": "kind", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Run number", + "in": "query", + "name": "run", "required": false, "schema": { "type": "string" @@ -41304,7 +32158,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TrainModelJobStatusResponse" + "$ref": "#/components/schemas/ModelSplitAudit" } } }, @@ -41522,13 +32376,15 @@ "bearer": [] } ], - "summary": "Read durable trainer job state, progress, terminal error, and the full gated training result", + "summary": "Verify a run's temporal-split obligation from its recorded lineage (train ≤ pin, eval > pin)", "tags": [ "system" ] - }, - "post": { - "operationId": "post_v1_models_train_jobs", + } + }, + "/v1/models/suggest-dataset": { + "get": { + "operationId": "get_v1_models_suggest_dataset", "parameters": [ { "description": "Graph name (default `main`)", @@ -41549,7 +32405,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -41558,31 +32414,30 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "Max probes (default 100, cap 200)", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Maximum signal sequence included", + "in": "query", + "name": "split_seq", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TrainModelRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TrainModelJobStatusResponse" + "$ref": "#/components/schemas/SuggestDatasetResponse" } } }, @@ -41800,15 +32655,15 @@ "bearer": [] } ], - "summary": "Idempotently enqueue a durable background trainer job; reconnect through the returned stable job id", + "summary": "Fetch the bounded published suggestion-ranker training artifact", "tags": [ "system" ] } }, - "/v1/models/train-tick": { - "post": { - "operationId": "post_v1_models_train_tick", + "/v1/models/synthetic-eval": { + "get": { + "operationId": "get_v1_models_synthetic_eval", "parameters": [ { "description": "Graph name (default `main`)", @@ -41829,7 +32684,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -41838,31 +32693,21 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "Max probes (default 100, max 500)", + "in": "query", + "name": "limit", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TrainModelRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TrainModelResponse" + "$ref": "#/components/schemas/SyntheticEvalResponse" } } }, @@ -42080,15 +32925,15 @@ "bearer": [] } ], - "summary": "One deterministic trainer tick: probe set (synthetic or BYO) → bounded candidate search on the train slice → held-out eval gate → record run (held or promoted) → CAS promote only when the gate passes", + "summary": "Execution-verified QA probes generated from current edges (labels are the executed projections; deterministic per snapshot)", "tags": [ "system" ] } }, - "/v1/models/training-config": { + "/v1/models/train-jobs": { "get": { - "operationId": "get_v1_models_training_config", + "operationId": "get_v1_models_train_jobs", "parameters": [ { "description": "Graph name (default `main`)", @@ -42109,13 +32954,22 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } + }, + { + "description": "Stable job id returned by the submit call", + "in": "query", + "name": "job_id", + "required": false, + "schema": { + "type": "string" + } } ], "responses": { @@ -42123,7 +32977,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelTrainingConfig" + "$ref": "#/components/schemas/TrainModelJobStatusResponse" } } }, @@ -42341,13 +33195,13 @@ "bearer": [] } ], - "summary": "The graph's automatic-training configuration (default: off)", + "summary": "Read durable trainer job state, progress, terminal error, and the full gated training result", "tags": [ "system" ] }, "post": { - "operationId": "post_v1_models_training_config", + "operationId": "post_v1_models_train_jobs", "parameters": [ { "description": "Graph name (default `main`)", @@ -42368,7 +33222,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -42390,7 +33244,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelTrainingConfig" + "$ref": "#/components/schemas/TrainModelRequest" } } }, @@ -42401,7 +33255,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ModelTrainingConfig" + "$ref": "#/components/schemas/TrainModelJobStatusResponse" } } }, @@ -42619,15 +33473,15 @@ "bearer": [] } ], - "summary": "Set the automatic-training configuration (auto_train toggle + trainable kinds)", + "summary": "Idempotently enqueue a durable background trainer job; reconnect through the returned stable job id", "tags": [ "system" ] } }, - "/v1/ontology": { - "get": { - "operationId": "get_v1_ontology", + "/v1/models/train-tick": { + "post": { + "operationId": "post_v1_models_train_tick", "parameters": [ { "description": "Graph name (default `main`)", @@ -42648,21 +33502,40 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } + }, + { + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", + "required": false, + "schema": { + "type": "string" + } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TrainModelRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyView" + "$ref": "#/components/schemas/TrainModelResponse" } } }, @@ -42880,15 +33753,15 @@ "bearer": [] } ], - "summary": "Active ontology vocabulary (entity types and relations) for the scoped graph", + "summary": "One deterministic trainer tick: probe set (synthetic or BYO) → bounded candidate search on the train slice → held-out eval gate → record run (held or promoted) → CAS promote only when the gate passes", "tags": [ - "ontology" + "system" ] } }, - "/v1/ontology/conformance": { + "/v1/models/training-config": { "get": { - "operationId": "get_v1_ontology_conformance", + "operationId": "get_v1_models_training_config", "parameters": [ { "description": "Graph name (default `main`)", @@ -42909,7 +33782,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -42923,7 +33796,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SchemaAuditReport" + "$ref": "#/components/schemas/ModelTrainingConfig" } } }, @@ -43141,15 +34014,13 @@ "bearer": [] } ], - "summary": "Audit the current snapshot against the ontology's implied SHACL constraints (capped cardinality -> sh:maxCount), derived on the fly; whole-snapshot, never blocks a write, independent of any published shape bundle", + "summary": "The graph's automatic-training configuration (default: off)", "tags": [ - "ontology" + "system" ] - } - }, - "/v1/ontology/define": { + }, "post": { - "operationId": "post_v1_ontology_define", + "operationId": "post_v1_models_training_config", "parameters": [ { "description": "Graph name (default `main`)", @@ -43170,7 +34041,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -43192,7 +34063,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyDefineRequest" + "$ref": "#/components/schemas/ModelTrainingConfig" } } }, @@ -43203,7 +34074,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyDefineResponse" + "$ref": "#/components/schemas/ModelTrainingConfig" } } }, @@ -43421,15 +34292,15 @@ "bearer": [] } ], - "summary": "Import a custom ontology and create the scoped graph head with it; fails if the graph already exists", + "summary": "Set the automatic-training configuration (auto_train toggle + trainable kinds)", "tags": [ - "ontology" + "system" ] } }, - "/v1/ontology/drafts": { + "/v1/ontology": { "get": { - "operationId": "get_v1_ontology_drafts", + "operationId": "get_v1_ontology", "parameters": [ { "description": "Graph name (default `main`)", @@ -43450,22 +34321,13 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable ontology draft identifier", - "in": "query", - "name": "draft_id", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -43473,7 +34335,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyDraft" + "$ref": "#/components/schemas/OntologyView" } } }, @@ -43691,13 +34553,15 @@ "bearer": [] } ], - "summary": "Read a durable ontology review artifact", + "summary": "Active ontology vocabulary (entity types and relations) for the scoped graph", "tags": [ "ontology" ] - }, - "post": { - "operationId": "post_v1_ontology_drafts", + } + }, + "/v1/ontology/conformance": { + "get": { + "operationId": "get_v1_ontology_conformance", "parameters": [ { "description": "Graph name (default `main`)", @@ -43718,7 +34582,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -43727,31 +34591,30 @@ } }, { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", + "description": "eventual (default) serves the referenced durable report; strong requires validation at current head with current ontology/shapes", + "in": "query", + "name": "consistency", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Maximum returned result rows; result_count remains exact", + "in": "query", + "name": "limit", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OntologyDraftCreateRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyDraft" + "$ref": "#/components/schemas/SchemaAuditReport" } } }, @@ -43969,15 +34832,15 @@ "bearer": [] } ], - "summary": "Create a deterministic, snapshot-pinned ontology proposal from connector samples without inserting those samples", + "summary": "Read the durable ontology-conformance report referenced by the published snapshot, including its validation watermark and ontology/shapes provenance", "tags": [ "ontology" ] } }, - "/v1/ontology/drafts/promote": { + "/v1/ontology/define": { "post": { - "operationId": "post_v1_ontology_drafts_promote", + "operationId": "post_v1_ontology_define", "parameters": [ { "description": "Graph name (default `main`)", @@ -43998,7 +34861,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -44010,27 +34873,28 @@ "description": "Stable client-generated key for safely retrying mutations and supervision writes.", "in": "header", "name": "Idempotency-Key", - "required": true, - "schema": { - "type": "string" - } - }, - { - "description": "Stable ontology draft identifier", - "in": "query", - "name": "draft_id", "required": false, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OntologyDefineRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyDraft" + "$ref": "#/components/schemas/OntologyDefineResponse" } } }, @@ -44248,15 +35112,15 @@ "bearer": [] } ], - "summary": "Atomically publish a validated ontology draft; requires Idempotency-Key", + "summary": "Import a custom ontology and create the scoped graph head with it; fails if the graph already exists", "tags": [ "ontology" ] } }, - "/v1/ontology/drafts/reject": { - "post": { - "operationId": "post_v1_ontology_drafts_reject", + "/v1/ontology/drafts": { + "get": { + "operationId": "get_v1_ontology_drafts", "parameters": [ { "description": "Graph name (default `main`)", @@ -44277,7 +35141,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -44285,15 +35149,6 @@ "type": "string" } }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } - }, { "description": "Stable ontology draft identifier", "in": "query", @@ -44302,15 +35157,6 @@ "schema": { "type": "string" } - }, - { - "description": "Auditable rejection reason", - "in": "query", - "name": "reason", - "required": false, - "schema": { - "type": "string" - } } ], "responses": { @@ -44536,15 +35382,13 @@ "bearer": [] } ], - "summary": "Reject a reviewable ontology draft without changing the graph ontology", + "summary": "Read a durable ontology review artifact", "tags": [ "ontology" ] - } - }, - "/v1/ontology/drafts/validate": { + }, "post": { - "operationId": "post_v1_ontology_drafts_validate", + "operationId": "post_v1_ontology_drafts", "parameters": [ { "description": "Graph name (default `main`)", @@ -44565,7 +35409,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -44581,17 +35425,18 @@ "schema": { "type": "string" } - }, - { - "description": "Stable ontology draft identifier", - "in": "query", - "name": "draft_id", - "required": false, - "schema": { - "type": "string" - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OntologyDraftCreateRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { @@ -44815,15 +35660,15 @@ "bearer": [] } ], - "summary": "Revalidate the exact proposed operations at the draft's pinned graph snapshot", + "summary": "Create a deterministic, snapshot-pinned ontology proposal from connector samples without inserting those samples", "tags": [ "ontology" ] } }, - "/v1/ontology/evolve": { + "/v1/ontology/drafts/promote": { "post": { - "operationId": "post_v1_ontology_evolve", + "operationId": "post_v1_ontology_drafts_promote", "parameters": [ { "description": "Graph name (default `main`)", @@ -44844,7 +35689,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -44856,37 +35701,27 @@ "description": "Stable client-generated key for safely retrying mutations and supervision writes.", "in": "header", "name": "Idempotency-Key", - "required": false, + "required": true, "schema": { "type": "string" } }, { - "description": "Validate and return the exact predicted evolution without writing an ontology object or graph head", + "description": "Stable ontology draft identifier", "in": "query", - "name": "dry_run", + "name": "draft_id", "required": false, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OntologyEvolveRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyEvolveResponse" + "$ref": "#/components/schemas/OntologyDraft" } } }, @@ -45104,15 +35939,15 @@ "bearer": [] } ], - "summary": "Evolve the scoped graph's ontology with ordered operations, or preview the exact diff, conflicts, and resulting version without mutation", + "summary": "Atomically publish a validated ontology draft; requires Idempotency-Key", "tags": [ "ontology" ] } }, - "/v1/ontology/induce": { + "/v1/ontology/drafts/reject": { "post": { - "operationId": "post_v1_ontology_induce", + "operationId": "post_v1_ontology_drafts_reject", "parameters": [ { "description": "Graph name (default `main`)", @@ -45133,7 +35968,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -45149,24 +35984,32 @@ "schema": { "type": "string" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OntologyInduceRequest" - } + }, + { + "description": "Stable ontology draft identifier", + "in": "query", + "name": "draft_id", + "required": false, + "schema": { + "type": "string" } }, - "required": true - }, + { + "description": "Auditable rejection reason", + "in": "query", + "name": "reason", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyInduceResponse" + "$ref": "#/components/schemas/OntologyDraft" } } }, @@ -45384,15 +36227,15 @@ "bearer": [] } ], - "summary": "Embedding-cluster ontology induction (MVP): mine tight embedding clusters among currently under-typed entities/edges and return suggested ontology patches. Suggestions only -- never applies anything; accept one via /v1/ontology/evolve with its suggested_ops", + "summary": "Reject a reviewable ontology draft without changing the graph ontology", "tags": [ "ontology" ] } }, - "/v1/ontology/resolve": { + "/v1/ontology/drafts/validate": { "post": { - "operationId": "post_v1_ontology_resolve", + "operationId": "post_v1_ontology_drafts_validate", "parameters": [ { "description": "Graph name (default `main`)", @@ -45413,7 +36256,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -45429,24 +36272,23 @@ "schema": { "type": "string" } + }, + { + "description": "Stable ontology draft identifier", + "in": "query", + "name": "draft_id", + "required": false, + "schema": { + "type": "string" + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OntologyResolveRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologyResolveResponse" + "$ref": "#/components/schemas/OntologyDraft" } } }, @@ -45664,15 +36506,15 @@ "bearer": [] } ], - "summary": "Resolve mentions to concepts/entities", + "summary": "Revalidate the exact proposed operations at the draft's pinned graph snapshot", "tags": [ "ontology" ] } }, - "/v1/ontology/search": { + "/v1/ontology/evolve": { "post": { - "operationId": "post_v1_ontology_search", + "operationId": "post_v1_ontology_evolve", "parameters": [ { "description": "Graph name (default `main`)", @@ -45693,7 +36535,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -45709,13 +36551,22 @@ "schema": { "type": "string" } + }, + { + "description": "Validate and return the exact predicted evolution without writing an ontology object or graph head", + "in": "query", + "name": "dry_run", + "required": false, + "schema": { + "type": "string" + } } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologySearchRequest" + "$ref": "#/components/schemas/OntologyEvolveRequest" } } }, @@ -45726,7 +36577,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OntologySearchResponse" + "$ref": "#/components/schemas/OntologyEvolveResponse" } } }, @@ -45944,15 +36795,15 @@ "bearer": [] } ], - "summary": "Discover ontology concepts, terms, and relations", + "summary": "Evolve the scoped graph's ontology with ordered operations, or preview the exact diff, conflicts, and resulting version without mutation", "tags": [ "ontology" ] } }, - "/v1/query/analytics": { + "/v1/ontology/induce": { "post": { - "operationId": "post_v1_query_analytics", + "operationId": "post_v1_ontology_induce", "parameters": [ { "description": "Graph name (default `main`)", @@ -45973,7 +36824,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -45995,7 +36846,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AnalyticQueryRequest" + "$ref": "#/components/schemas/OntologyInduceRequest" } } }, @@ -46006,7 +36857,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AnalyticQueryResponse" + "$ref": "#/components/schemas/OntologyInduceResponse" } } }, @@ -46224,15 +37075,15 @@ "bearer": [] } ], - "summary": "Basic-graph-pattern (BGP) analytic query over the permutation view", + "summary": "Embedding-cluster ontology induction (MVP): mine tight embedding clusters among currently under-typed entities/edges and return suggested ontology patches. Suggestions only -- never applies anything; accept one via /v1/ontology/evolve with its suggested_ops", "tags": [ - "query" + "ontology" ] } }, - "/v1/query/conflicts": { + "/v1/ontology/resolve": { "post": { - "operationId": "post_v1_query_conflicts", + "operationId": "post_v1_ontology_resolve", "parameters": [ { "description": "Graph name (default `main`)", @@ -46253,7 +37104,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -46275,7 +37126,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GovernedConflictAggregationRequest" + "$ref": "#/components/schemas/OntologyResolveRequest" } } }, @@ -46286,7 +37137,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GovernedConflictAggregationResponse" + "$ref": "#/components/schemas/OntologyResolveResponse" } } }, @@ -46504,15 +37355,15 @@ "bearer": [] } ], - "summary": "ACL-first snapshot aggregation returning only keys with multiple distinct values and bounded evidence entity ids", + "summary": "Resolve mentions to concepts/entities", "tags": [ - "query" + "ontology" ] } }, - "/v1/query/history": { + "/v1/ontology/search": { "post": { - "operationId": "post_v1_query_history", + "operationId": "post_v1_ontology_search", "parameters": [ { "description": "Graph name (default `main`)", @@ -46533,7 +37384,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -46555,7 +37406,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelationshipHistoryRequest" + "$ref": "#/components/schemas/OntologySearchRequest" } } }, @@ -46566,7 +37417,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RelationshipHistoryResponse" + "$ref": "#/components/schemas/OntologySearchResponse" } } }, @@ -46784,15 +37635,15 @@ "bearer": [] } ], - "summary": "Relationship history", + "summary": "Discover ontology concepts, terms, and relations", "tags": [ - "query" + "ontology" ] } }, - "/v1/query/shacl": { + "/v1/query/analytics": { "post": { - "operationId": "post_v1_query_shacl", + "operationId": "post_v1_query_analytics", "parameters": [ { "description": "Graph name (default `main`)", @@ -46813,7 +37664,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -46835,7 +37686,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ShaclQueryRequest" + "$ref": "#/components/schemas/AnalyticQueryRequest" } } }, @@ -46846,7 +37697,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ShaclQueryResponse" + "$ref": "#/components/schemas/AnalyticQueryResponse" } } }, @@ -47064,15 +37915,15 @@ "bearer": [] } ], - "summary": "SHACL-style shape query", + "summary": "Basic-graph-pattern (BGP) analytic query over the permutation view", "tags": [ "query" ] } }, - "/v1/query/sparql": { + "/v1/query/conflicts": { "post": { - "operationId": "post_v1_query_sparql", + "operationId": "post_v1_query_conflicts", "parameters": [ { "description": "Graph name (default `main`)", @@ -47093,7 +37944,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -47115,7 +37966,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlSelectRequest" + "$ref": "#/components/schemas/GovernedConflictAggregationRequest" } } }, @@ -47126,7 +37977,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlSelectResponse" + "$ref": "#/components/schemas/GovernedConflictAggregationResponse" } } }, @@ -47344,15 +38195,15 @@ "bearer": [] } ], - "summary": "SPARQL-subset SELECT/ASK query (BGP WHERE, projection, DISTINCT, LIMIT/OFFSET)", + "summary": "ACL-first snapshot aggregation returning only keys with multiple distinct values and bounded evidence entity ids", "tags": [ "query" ] } }, - "/v1/query/sparql-text": { + "/v1/query/history": { "post": { - "operationId": "post_v1_query_sparql_text", + "operationId": "post_v1_query_history", "parameters": [ { "description": "Graph name (default `main`)", @@ -47373,7 +38224,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -47395,7 +38246,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlTextRequest" + "$ref": "#/components/schemas/RelationshipHistoryRequest" } } }, @@ -47406,7 +38257,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SparqlTextResponse" + "$ref": "#/components/schemas/RelationshipHistoryResponse" } } }, @@ -47624,15 +38475,15 @@ "bearer": [] } ], - "summary": "SPARQL 1.1 query from text (SELECT/ASK) over the live graph -> SPARQL Results JSON", + "summary": "Relationship history", "tags": [ "query" ] } }, - "/v1/query/state": { + "/v1/query/sparql": { "post": { - "operationId": "post_v1_query_state", + "operationId": "post_v1_query_sparql", "parameters": [ { "description": "Graph name (default `main`)", @@ -47653,7 +38504,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -47675,7 +38526,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CurrentStateRequest" + "$ref": "#/components/schemas/SparqlSelectRequest" } } }, @@ -47686,7 +38537,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CurrentStateResponse" + "$ref": "#/components/schemas/SparqlSelectResponse" } } }, @@ -47904,15 +38755,15 @@ "bearer": [] } ], - "summary": "Current state of an entity's relations, optionally as-of", + "summary": "SPARQL-subset SELECT/ASK query (BGP WHERE, projection, DISTINCT, LIMIT/OFFSET)", "tags": [ "query" ] } }, - "/v1/query/transitions": { + "/v1/query/sparql-text": { "post": { - "operationId": "post_v1_query_transitions", + "operationId": "post_v1_query_sparql_text", "parameters": [ { "description": "Graph name (default `main`)", @@ -47933,7 +38784,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -47955,7 +38806,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityTransitionsRequest" + "$ref": "#/components/schemas/SparqlTextRequest" } } }, @@ -47966,7 +38817,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EntityTransitionsResponse" + "$ref": "#/components/schemas/SparqlTextResponse" } } }, @@ -48184,15 +39035,15 @@ "bearer": [] } ], - "summary": "State-transition log for an entity's relation, with dwell time", + "summary": "SPARQL 1.1 query from text (SELECT/ASK) over the live graph -> SPARQL Results JSON", "tags": [ "query" ] } }, - "/v1/query/why": { + "/v1/query/state": { "post": { - "operationId": "post_v1_query_why", + "operationId": "post_v1_query_state", "parameters": [ { "description": "Graph name (default `main`)", @@ -48213,7 +39064,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -48235,7 +39086,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WhyRequest" + "$ref": "#/components/schemas/CurrentStateRequest" } } }, @@ -48246,7 +39097,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WhyResponse" + "$ref": "#/components/schemas/CurrentStateResponse" } } }, @@ -48464,15 +39315,15 @@ "bearer": [] } ], - "summary": "Lineage and evidence for a single edge", + "summary": "Current state of an entity's relations, optionally as-of", "tags": [ "query" ] } }, - "/v1/schema": { - "get": { - "operationId": "get_v1_schema", + "/v1/query/transitions": { + "post": { + "operationId": "post_v1_query_transitions", "parameters": [ { "description": "Graph name (default `main`)", @@ -48493,7 +39344,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -48502,21 +39353,31 @@ } }, { - "description": "Run the live SHACL audit and include `audit_summary`. Default false keeps schema reads metadata-only.", - "in": "query", - "name": "audit", + "description": "Stable client-generated key for safely retrying mutations and supervision writes.", + "in": "header", + "name": "Idempotency-Key", "required": false, "schema": { - "type": "boolean" + "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntityTransitionsRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SchemaBundleView" + "$ref": "#/components/schemas/EntityTransitionsResponse" } } }, @@ -48734,15 +39595,15 @@ "bearer": [] } ], - "summary": "Read the active graph schema bundle (ontology plus activated SHACL shapes)", + "summary": "State-transition log for an entity's relation, with dwell time", "tags": [ - "schema" + "query" ] } }, - "/v1/schema/audit": { + "/v1/query/why": { "post": { - "operationId": "post_v1_schema_audit", + "operationId": "post_v1_query_why", "parameters": [ { "description": "Graph name (default `main`)", @@ -48763,7 +39624,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -48779,37 +39640,28 @@ "schema": { "type": "string" } - }, - { - "description": "Response format: json (default), turtle, or nt/ntriples", - "in": "query", - "name": "format", - "required": false, - "schema": { - "type": "string" - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WhyRequest" + } + } + }, + "required": true + }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SchemaAuditReport" - } - }, - "application/n-triples": { - "schema": { - "type": "string" - } - }, - "text/turtle": { - "schema": { - "type": "string" + "$ref": "#/components/schemas/WhyResponse" } } }, - "description": "SHACL validation report", + "description": "OK", "headers": { "Lbb-Version": { "description": "API contract version used for the response", @@ -49023,15 +39875,15 @@ "bearer": [] } ], - "summary": "Audit current graph data against the active SHACL schema bundle; JSON by default, or a standard RDF sh:ValidationReport as Turtle/N-Triples", + "summary": "Lineage and evidence for a single edge", "tags": [ - "schema" + "query" ] } }, - "/v1/schema/preview": { - "post": { - "operationId": "post_v1_schema_preview", + "/v1/schema": { + "get": { + "operationId": "get_v1_schema", "parameters": [ { "description": "Graph name (default `main`)", @@ -49052,40 +39904,21 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, "schema": { "type": "string" } - }, - { - "description": "Stable client-generated key for safely retrying mutations and supervision writes.", - "in": "header", - "name": "Idempotency-Key", - "required": false, - "schema": { - "type": "string" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SchemaPreviewRequest" - } - } - }, - "required": true - }, "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SchemaPreviewResponse" + "$ref": "#/components/schemas/SchemaBundleView" } } }, @@ -49303,7 +40136,7 @@ "bearer": [] } ], - "summary": "Preview a proposed graph schema bundle and audit it against current data", + "summary": "Read active ontology and SHACL shapes metadata without running validation", "tags": [ "schema" ] @@ -49332,7 +40165,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -49583,7 +40416,7 @@ "bearer": [] } ], - "summary": "Activate a previewed SHACL schema bundle for the graph branch", + "summary": "Atomically activate a SHACL shapes bundle and enqueue durable conformance validation", "tags": [ "schema" ] @@ -49612,7 +40445,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -49638,15 +40471,6 @@ "type": "string" } }, - { - "description": "Index source", - "in": "query", - "name": "source", - "required": false, - "schema": { - "type": "string" - } - }, { "description": "strong or eventual", "in": "query", @@ -49909,7 +40733,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -50189,7 +41013,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -50469,7 +41293,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -50749,7 +41573,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -51010,7 +41834,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -51271,7 +42095,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -51551,7 +42375,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -51831,7 +42655,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -52111,7 +42935,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -52362,7 +43186,7 @@ "bearer": [] } ], - "summary": "Snap free text to the nearest real vocabulary item", + "summary": "Snap free text to vocabulary from the pinned published read root", "tags": [ "search" ] @@ -52391,7 +43215,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -52661,7 +43485,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -52941,7 +43765,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -53221,7 +44045,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -53501,7 +44325,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -53780,7 +44604,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -54066,7 +44890,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -54346,7 +45170,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, @@ -54607,7 +45431,7 @@ } }, { - "description": "API contract version to pin. Use `2026-07-22` for this beta-breaking shape.", + "description": "API contract version to pin. Use `2026-07-23` for this beta-breaking shape.", "in": "header", "name": "Lbb-Version", "required": false, diff --git a/lbb/_async_client.py b/lbb/_async_client.py index c1ddd20..8fa5885 100644 --- a/lbb/_async_client.py +++ b/lbb/_async_client.py @@ -4,7 +4,7 @@ import asyncio import inspect -from collections.abc import AsyncIterator, Callable, Mapping, Sequence +from collections.abc import Callable, Mapping, Sequence from typing import Any, cast import httpx @@ -44,11 +44,6 @@ class _AsyncContextNamespace(_ContextNamespace): - async def ask( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.AskResponse: - return cast(models.AskResponse, await super().ask(body, options=options)) - async def suggest( self, body: Body, *, options: RequestOptions | None = None ) -> models.SearchSuggestResponse: @@ -76,7 +71,6 @@ async def groundability( await super().groundability(sample=sample, options=options), ) - class _AsyncOntologyNamespace(_OntologyNamespace): async def view( self, *, counts: bool = False, options: RequestOptions | None = None @@ -86,10 +80,14 @@ async def view( ) async def conformance( - self, *, options: RequestOptions | None = None + self, + *, + consistency: str | None = None, + options: RequestOptions | None = None, ) -> models.SchemaAuditReport: return cast( - models.SchemaAuditReport, await super().conformance(options=options) + models.SchemaAuditReport, + await super().conformance(consistency=consistency, options=options), ) async def search( @@ -176,8 +174,6 @@ async def sparql( *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -189,8 +185,6 @@ async def sparql( query, reason=reason, entailment=entailment, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, limit=limit, offset=offset, consistency=consistency, @@ -206,28 +200,6 @@ async def analytics( await super().analytics(body, options=options), ) - async def shacl( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.ShaclQueryResponse: - return cast( - models.ShaclQueryResponse, await super().shacl(body, options=options) - ) - - async def infer( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.InferenceRunResponse: - return cast( - models.InferenceRunResponse, await super().infer(body, options=options) - ) - - async def premises( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.RetrievalPremiseResponse: - return cast( - models.RetrievalPremiseResponse, - await super().premises(body, options=options), - ) - async def conflicts( self, body: Body, *, options: RequestOptions | None = None ) -> models.GovernedConflictAggregationResponse: @@ -246,6 +218,18 @@ async def create_model( await super().create_model(body, idempotency_key=idempotency_key), ) +class _AsyncSchemaNamespace(_SchemaNamespace): + async def view_model(self) -> models.SchemaBundleView: + return cast(models.SchemaBundleView, await super().view_model()) + + async def publish_model( + self, body: Body, *, idempotency_key: str | None = None + ) -> models.SchemaPublishResponse: + return cast( + models.SchemaPublishResponse, + await super().publish_model(body, idempotency_key=idempotency_key), + ) + class _AsyncGraphNamespace(_GraphNamespace): facts: _AsyncFactsNamespace @@ -369,43 +353,6 @@ async def retract_model( await super().retract_model(body, idempotency_key=idempotency_key), ) - async def export_rdf_preview( - self, - *, - format: str = "turtle", - max_triples: int = 100, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> models.RdfExportPreviewResponse: - return cast( - models.RdfExportPreviewResponse, - await super().export_rdf_preview( - format=format, - max_triples=max_triples, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, - entailment=entailment, - reason=reason, - ), - ) - - -class _AsyncSchemaNamespace(_SchemaNamespace): - async def view_model(self, *, audit: bool = False) -> models.SchemaBundleView: - return cast(models.SchemaBundleView, await super().view_model(audit=audit)) - - async def preview_model(self, body: Body) -> models.SchemaPreviewResponse: - return cast(models.SchemaPreviewResponse, await super().preview_model(body)) - - async def publish_model(self, body: Body) -> models.SchemaPublishResponse: - return cast(models.SchemaPublishResponse, await super().publish_model(body)) - - async def audit_model(self) -> models.SchemaAuditReport: - return cast(models.SchemaAuditReport, await super().audit_model()) - - class _AsyncEntityNamespace(_EntityNamespace): async def sample( self, @@ -419,19 +366,6 @@ async def sample( await super().sample(type=type, limit=limit, options=options), ) - async def list_page(self, **kwargs: Any) -> ListPage[models.EntityExplorerRow]: - return cast( - ListPage[models.EntityExplorerRow], await super().list_page(**kwargs) - ) - - async def filter( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.EntityFilterResponse: - return cast( - models.EntityFilterResponse, - await super().filter(body, options=options), - ) - async def filter_by_attributes_model( self, **kwargs: Any ) -> models.SparqlSelectResponse: @@ -440,15 +374,6 @@ async def filter_by_attributes_model( await super().filter_by_attributes_model(**kwargs), ) - def pages(self, **kwargs: Any) -> AsyncIterator[ListPage[models.EntityExplorerRow]]: - return cast( - AsyncIterator[ListPage[models.EntityExplorerRow]], super().pages(**kwargs) - ) - - def iter(self, **kwargs: Any) -> AsyncIterator[models.EntityExplorerRow]: - return cast(AsyncIterator[models.EntityExplorerRow], super().iter(**kwargs)) - - class AsyncLbbClient(_BaseLbbClient): """Asynchronous client. Usable as an async context manager.""" @@ -465,7 +390,7 @@ def __init__( api_key: str | None = None, graph: str | None = None, branch: str | None = None, - api_version: str = "2026-07-22", + api_version: str = "2026-07-23", max_retries: int = DEFAULT_MAX_RETRIES, retry_delay: float = 0.1, retry_budget_ms: float = DEFAULT_RETRY_BUDGET_MS, @@ -665,28 +590,6 @@ async def promote_embedding( ), ) - async def export_rdf_preview( - self, - *, - format: str = "turtle", - max_triples: int = 100, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> models.RdfExportPreviewResponse: - return cast( - models.RdfExportPreviewResponse, - await super().export_rdf_preview( - format=format, - max_triples=max_triples, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, - entailment=entailment, - reason=reason, - ), - ) - async def train_submit( self, body: Body, *, idempotency_key: str ) -> models.TrainModelJobStatusResponse: @@ -723,9 +626,12 @@ async def governed_conflicts( await super().governed_conflicts(body), ) - async def ontology_conformance_model(self) -> models.SchemaAuditReport: + async def ontology_conformance_model( + self, *, consistency: str | None = None + ) -> models.SchemaAuditReport: return cast( - models.SchemaAuditReport, await super().ontology_conformance_model() + models.SchemaAuditReport, + await super().ontology_conformance_model(consistency=consistency), ) async def ontology_view_model(self, *, counts: bool = False) -> models.OntologyView: @@ -733,44 +639,6 @@ async def ontology_view_model(self, *, counts: bool = False) -> models.OntologyV models.OntologyView, await super().ontology_view_model(counts=counts) ) - async def index_submit( - self, body: Body | None = None, *, idempotency_key: str - ) -> models.SearchIndexJobStatusResponse: - return cast( - models.SearchIndexJobStatusResponse, - await super().index_submit(body, idempotency_key=idempotency_key), - ) - - async def index_job(self, job_id: str) -> models.SearchIndexJobStatusResponse: - return cast( - models.SearchIndexJobStatusResponse, await super().index_job(job_id) - ) - - async def cancel_index_job( - self, job_id: str - ) -> models.SearchIndexJobStatusResponse: - return cast( - models.SearchIndexJobStatusResponse, - await super().cancel_index_job(job_id), - ) - - async def index_gc_submit( - self, body: Body | None = None, *, idempotency_key: str - ) -> models.IndexGcJobStatusResponse: - return cast( - models.IndexGcJobStatusResponse, - await super().index_gc_submit(body, idempotency_key=idempotency_key), - ) - - async def index_gc_job(self, job_id: str) -> models.IndexGcJobStatusResponse: - return cast(models.IndexGcJobStatusResponse, await super().index_gc_job(job_id)) - - async def cancel_index_gc_job(self, job_id: str) -> models.IndexGcJobStatusResponse: - return cast( - models.IndexGcJobStatusResponse, - await super().cancel_index_gc_job(job_id), - ) - async def metadata_model(self) -> models.GraphMetadataResponse: return cast(models.GraphMetadataResponse, await super().metadata_model()) @@ -816,9 +684,10 @@ async def wait_for_index_lineage( async def summary_model(self) -> models.GraphSummaryResponse: return cast(models.GraphSummaryResponse, await super().summary_model()) - async def graph_edges_page(self, **kwargs: Any) -> ListPage[models.GraphEdgeRow]: + async def read_snapshot_model(self) -> models.PublishedReadStatusResponse: return cast( - ListPage[models.GraphEdgeRow], await super().graph_edges_page(**kwargs) + models.PublishedReadStatusResponse, + await super().read_snapshot_model(), ) async def list_graphs_model(self) -> models.GraphListResponse: @@ -970,43 +839,12 @@ async def _page_request( payload = await payload return ListPage.from_payload(payload, row_model) - async def _iter_entity_pages( - self, **kwargs: Any - ) -> AsyncIterator[ListPage[models.EntityExplorerRow]]: - cursor = kwargs.pop("cursor", None) - initial_offset = kwargs.pop("offset", None) - seen: set[str] = set() - while True: - page = await self.entities.list_page( - **kwargs, - cursor=cursor, - offset=initial_offset if cursor is None else None, - ) - yield page - if not page.has_more or page.next_cursor is None: - return - if page.next_cursor in seen: - raise RuntimeError( - f"entity pagination cursor repeated: {page.next_cursor}" - ) - seen.add(page.next_cursor) - cursor = page.next_cursor - - async def _iter_entity_rows( - self, **kwargs: Any - ) -> AsyncIterator[models.EntityExplorerRow]: - async for page in self._iter_entity_pages(**kwargs): - for row in page: - yield row - async def sparql( self, query: str, *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -1017,8 +855,6 @@ async def sparql( query, reason=reason, entailment=entailment, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, limit=limit, offset=offset, consistency=consistency, diff --git a/lbb/_client_base.py b/lbb/_client_base.py index e3a476a..1b765e3 100644 --- a/lbb/_client_base.py +++ b/lbb/_client_base.py @@ -34,9 +34,8 @@ from ._version import __version__ DEFAULT_BASE_URL = "http://127.0.0.1:7400" -# Generous default: commits over a large corpus and synchronous index builds run -# well past a few seconds. Background index builds (index_run(background=True)) -# return immediately regardless. +# Generous default: commits over a large corpus and long administration calls +# can run well past a few seconds. DEFAULT_TIMEOUT = 120.0 # Retry count is now a secondary safety ceiling; the binding limit is the # deadline budget below. Raised 2 → 6 so a multi-second `Retry-After` sequence @@ -479,7 +478,7 @@ def __init__( api_key: str | None = None, graph: str | None = None, branch: str | None = None, - api_version: str = "2026-07-22", + api_version: str = "2026-07-23", max_retries: int = DEFAULT_MAX_RETRIES, retry_delay: float = 0.1, retry_budget_ms: float = DEFAULT_RETRY_BUDGET_MS, @@ -501,7 +500,6 @@ def __init__( self._default_consistency = default_consistency self.search = _SearchNamespace(self) self.context = _ContextNamespace(self) - self.indexes = _IndexNamespace(self) self.entities = _EntityNamespace(self) self.ontology = _OntologyNamespace(self) self.query = _QueryNamespace(self) @@ -871,7 +869,7 @@ def import_ndjson( batch: int | None = None, strict: bool | None = None, observed_at: str | None = None, - index: bool | None = None, + publish: bool | None = None, idempotency_key: str | None = None, ) -> Any: """Bulk-ingest a dataset as NDJSON. @@ -881,13 +879,10 @@ def import_ndjson( batched into bounded internal commits server-side, so a whole dataset loads in one streamed request without a single oversized commit. - Set ``index=True`` to run one full index build after the last batch, so the - data is served from the persisted runs (not just the ephemeral snapshot - fallback) by the time the call returns — the "bulk load, queryable on - return" path for connector backfills. This replaces the anti-pattern of - indexing per batch (which serializes builds and races the throttle): import - the whole dataset, index once. The response's ``index`` object reports - whether the build ran (``built``) or was skipped (``skipped_reason``). + Set ``publish=True`` to durably enqueue one complete + published-generation build after the final batch. The import does not + wait for visibility; ``published_generation`` carries the durable job + identity and due sequence to observe. """ ndjson = ( lines @@ -901,7 +896,7 @@ def import_ndjson( "batch": batch, "strict": strict, "observed_at": observed_at, - "index": index, + "publish": publish, }, content=ndjson, content_type="application/x-ndjson", @@ -958,9 +953,8 @@ def reload( def import_rdf( self, - rdf: str | None = None, + rdf: str, *, - ntriples: str | None = None, format: str = "ntriples", base_iri: str | None = None, graph_uri: str | None = None, @@ -970,6 +964,7 @@ def import_rdf( observed_at: str | None = None, resource_type: str | None = None, edge_idempotency: str | None = None, + publish: bool | None = None, idempotency_key: str | None = None, ) -> Any: """Bulk-ingest N-Triples, Turtle, N-Quads, or TriG through the native RDF import endpoint. @@ -978,16 +973,6 @@ def import_rdf( source RDF predicates and literal term details are preserved as edge metadata. """ - if rdf is not None and ntriples is not None: - raise TypeError("pass exactly one of rdf= or the deprecated ntriples=") - if rdf is None: - rdf = ntriples - if rdf is None: - raise TypeError("import_rdf() requires RDF text via rdf= or ntriples=") - if ntriples is not None and format != "ntriples": - raise ValueError( - "the deprecated ntriples= keyword requires format='ntriples'" - ) content_types = { "ntriples": "application/n-triples", "turtle": "text/turtle", @@ -1009,66 +994,13 @@ def import_rdf( "blank_node_scope": blank_node_scope, "resource_type": resource_type, "edge_idempotency": edge_idempotency, + "publish": publish, }, content=rdf, content_type=content_types[format], idempotency_key=idempotency_key or self.idempotency_key("import-rdf"), ) - def export_rdf( - self, - *, - format: str = "turtle", - max_triples: int | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> Any: - """Export the snapshot-visible RDF projection as Turtle, N-Triples, TriG, or N-Quads.""" - if format not in {"turtle", "ntriples", "trig", "nquads"}: - raise ValueError("format must be 'turtle', 'ntriples', 'trig', or 'nquads'") - return self._request( - "GET", - "/v1/graph/export/rdf", - params={ - "format": "nt" if format == "ntriples" else format, - "max_triples": max_triples, - "as_of_valid_time": as_of_valid_time, - "as_of_commit_seq": as_of_commit_seq, - "entailment": entailment, - "reason": reason, - }, - ) - - def export_rdf_preview( - self, - *, - format: str = "turtle", - max_triples: int = 100, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> models.RdfExportPreviewResponse: - """Return a deterministic bounded RDF slice plus truncation metadata.""" - if format not in {"turtle", "ntriples", "trig", "nquads"}: - raise ValueError("format must be 'turtle', 'ntriples', 'trig', or 'nquads'") - return self._model_request( - models.RdfExportPreviewResponse, - "GET", - "/v1/graph/export/rdf", - params={ - "format": "nt" if format == "ntriples" else format, - "max_triples": max_triples, - "truncate": "true", - "as_of_valid_time": as_of_valid_time, - "as_of_commit_seq": as_of_commit_seq, - "entailment": entailment, - "reason": reason, - }, - ) - def retract(self, body: Body, *, idempotency_key: str | None = None) -> Any: """Retract specific edges and/or every edge touching given entities. @@ -1176,15 +1108,13 @@ def model_split_audit(self, *, kind: str, run: int) -> Any: ) def shadow_eval(self, body: Body) -> Any: - """Champion vs challenger retrieval over one pinned snapshot (``POST - /v1/models/shadow-eval``). Returns promotion evidence (hit-rate@k, - latency, per-query overlap); never promotes.""" + """Compare champion and challenger retrieval over one pinned snapshot.""" return self._request("POST", "/v1/models/shadow-eval", body=body) def synthetic_eval(self, *, limit: int | None = None) -> Any: """Execution-verified QA probes generated from the graph's current edges — labels are the executed projections (``GET - /v1/models/synthetic-eval``). Feeds ``shadow_eval`` directly.""" + /v1/models/synthetic-eval``).""" return self._request( "GET", "/v1/models/synthetic-eval", params={"limit": limit} ) @@ -1233,31 +1163,6 @@ def set_training_config(self, body: Body) -> Any: toggle + trainable kinds (``POST /v1/models/training-config``).""" return self._request("POST", "/v1/models/training-config", body=body) - def ask(self, body: Body) -> Any: - """Ground a natural-language question to the graph's real vocabulary, - retrieve against the pinned snapshot, and answer with citations - (``POST /v1/ask``). Body: - ``{"question", "execute"?, "top_k"?, "as_of_commit_seq"?, - "as_of_valid_time"?}``. The response carries ``mode`` - (``grounding_only`` | ``resident_planner``), ``answer``, ``citations``, - ``grounding``, a per-call ``explain``, and an ``ask_id`` to join to - :meth:`ask_feedback`. The typed response model is - :class:`lbb.models.AskResponse`.""" - return self._request("POST", "/v1/ask", body=body) - - def ask_feedback(self, body: Body, *, idempotency_key: str | None = None) -> Any: - """Verdict on an ask (``POST /v1/ask/feedback``): ``accepted`` | - ``rejected`` | ``corrected`` (+ ``corrected_plan``), joined to the - ask's trace by ``ask_id`` — the planner fine-tune's feedback capture. - ``accepted: false`` means signal capture is off on this deployment.""" - validated = models.AskFeedbackRequest.model_validate(body) - return self._request( - "POST", - "/v1/ask/feedback", - body=validated.model_dump(mode="json", exclude_none=True), - idempotency_key=idempotency_key or self.idempotency_key("ask-feedback"), - ) - def ingest_signals(self, body: Body, *, idempotency_key: str | None = None) -> Any: """Write a typed supervision batch with a durable replay-safe receipt.""" return self._request( @@ -1324,9 +1229,6 @@ def external_planner_trace( def planner_dataset( self, *, limit: int | None = None, split_seq: int | None = None ) -> Any: - """The planner fine-tune's training feed (``GET - /v1/models/planner-dataset``): feedback rows joined from signals ≤ the - split pin + execution-verified synthetic plans.""" return self._request( "GET", "/v1/models/planner-dataset", @@ -1336,10 +1238,6 @@ def planner_dataset( def planner_preference_dataset( self, *, limit: int | None = None, split_seq: int | None = None ) -> Any: - """The DPO pass's training feed (``GET - /v1/models/planner-preference-dataset``): preference pairs from - corrected verdicts, paired rejections, synthetic corrupted-slot - pairs; unpaired rejections are counted.""" return self._request( "GET", "/v1/models/planner-preference-dataset", @@ -1349,9 +1247,6 @@ def planner_preference_dataset( def suggest_dataset( self, *, limit: int | None = None, split_seq: int | None = None ) -> Any: - """The suggest-ranker trainer's probe feed (``GET - /v1/models/suggest-dataset``): ``suggestion_adopted`` signals ≤ the - split pin + execution-verified synthetic vocabulary pairs.""" return self._request( "GET", "/v1/models/suggest-dataset", @@ -1361,9 +1256,6 @@ def suggest_dataset( def extractor_dataset( self, *, limit: int | None = None, split_seq: int | None = None ) -> Any: - """The extractor fine-tune's training feed (``GET - /v1/models/extractor-dataset``): EPISODE transcripts joined to the - facts the observe pipeline committed from them.""" return self._request( "GET", "/v1/models/extractor-dataset", @@ -1388,8 +1280,7 @@ def promote_planner( ) -> Any: """Promote a finished ``planner_lora`` run (``POST /v1/models/promote-planner``): gated on held-out slot exactness, - recorded as a ``kind=planner`` training run whose adapter ``/v1/ask`` - serves.""" + recorded as a ``kind=planner`` training run.""" return self._request( "POST", "/v1/models/promote-planner", @@ -1497,10 +1388,6 @@ def why(self, body: Body) -> Any: """Lineage and evidence for a single edge.""" return self._request("POST", "/v1/query/why", body=body) - def shacl(self, body: Body) -> Any: - """SHACL-style shape/pattern query.""" - return self._request("POST", "/v1/query/shacl", body=body) - # --- SPARQL --- def sparql_select( @@ -1515,7 +1402,7 @@ def sparql_select( Takes a ``SparqlSelectRequest`` (model or dict): conjunctive ``patterns`` plus optional ``filters``, ``group_by``/``aggregates`` (COUNT/SUM/AVG/ MIN/MAX), ``having``, ``order_by``, ``select``/``distinct``, ``ask``, - ``limit``/``offset``, and the ``as_of_*`` snapshot pins. GROUP BY is not + and ``limit``/``offset``. GROUP BY is not limited to entity identity: ``group_keys`` adds typed scalar keys — a property value or a calendar bucket of a datetime property (``{"date_bucket": {"var", "field", "granularity", "as"}}``) — so a @@ -1566,8 +1453,6 @@ def _sparql_text_envelope( *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -1583,10 +1468,6 @@ def _sparql_text_envelope( body["reason"] = reason if entailment is not None: body["entailment"] = entailment - if as_of_valid_time is not None: - body["as_of_valid_time"] = as_of_valid_time - if as_of_commit_seq is not None: - body["as_of_commit_seq"] = as_of_commit_seq if limit is not None: body["limit"] = limit if offset is not None: @@ -1607,21 +1488,28 @@ def ontology_resolve(self, body: Body) -> Any: """Resolve mentions to concepts/entities.""" return self._request("POST", "/v1/ontology/resolve", body=body) - def ontology_conformance(self) -> Any: - """Audit the snapshot against the ontology's implied constraints. + def ontology_conformance(self, *, consistency: str | None = None) -> Any: + """Read the durable ontology-conformance report. - Derives SHACL shapes from the ontology's capped ``cardinality`` - (``-> sh:maxCount``) and validates the current snapshot against them, - returning a ``SchemaAuditReport``. Whole-snapshot and never blocks a - write; unlike the published-shapes schema audit it needs no activated - shape bundle — the shapes come from the ontology itself. + ``eventual`` serves the report referenced by the published read root. + ``strong`` requires its validation watermark and ontology/shapes + provenance to match current head; it never runs validation inline. """ - return self._request("GET", "/v1/ontology/conformance") + params = self._consistency_params(consistency, None) + return self._request( + "GET", "/v1/ontology/conformance", params=params or None + ) - def ontology_conformance_model(self) -> models.SchemaAuditReport: + def ontology_conformance_model( + self, *, consistency: str | None = None + ) -> models.SchemaAuditReport: """Ontology conformance report validated as ``SchemaAuditReport``.""" + params = self._consistency_params(consistency, None) return self._model_request( - models.SchemaAuditReport, "GET", "/v1/ontology/conformance" + models.SchemaAuditReport, + "GET", + "/v1/ontology/conformance", + params=params or None, ) def ontology_view(self, *, counts: bool = False) -> Any: @@ -1643,108 +1531,6 @@ def ontology_view_model(self, *, counts: bool = False) -> models.OntologyView: models.OntologyView, "GET", "/v1/ontology", params=params ) - # --- index lifecycle --- - - def index_build(self, *, background: bool = False) -> Any: - """Build default ANN + BM25 indexes. - - With ``background=True`` the build runs detached on the server and the - call returns immediately — use this for large corpora whose synchronous - build would exceed a fronting gateway's timeout (a 504), then poll - :meth:`metadata` (or :meth:`LbbClient.wait_for_index`) for completion. - """ - return self._request( - "POST", - "/v1/index/build", - params={"background": "true" if background else None}, - ) - - def index_run(self, *, background: bool = False) -> Any: - """Build BM25, ANN/vector, and adjacency index families. - - With ``background=True`` the build runs detached on the server and the - call returns immediately — use this for large corpora whose synchronous - build would exceed a fronting gateway's timeout, then poll - :meth:`metadata` (or :meth:`LbbClient.wait_for_index`) for completion. - """ - return self._request( - "POST", - "/v1/index/run", - params={"background": "true" if background else None}, - ) - - def index_submit( - self, body: Body | None = None, *, idempotency_key: str - ) -> models.SearchIndexJobStatusResponse: - """Submit a durable full-index job with a reconnect-safe id.""" - return self._model_request( - models.SearchIndexJobStatusResponse, - "POST", - "/v1/index/jobs", - body=body or {}, - idempotency_key=idempotency_key, - ) - - def index_job(self, job_id: str) -> models.SearchIndexJobStatusResponse: - """Poll per-family index progress or terminal failure.""" - return self._model_request( - models.SearchIndexJobStatusResponse, - "GET", - "/v1/index/jobs", - params={"job_id": job_id}, - ) - - def cancel_index_job(self, job_id: str) -> models.SearchIndexJobStatusResponse: - """Cancel a durable full-index job.""" - return self._model_request( - models.SearchIndexJobStatusResponse, - "DELETE", - "/v1/index/jobs", - params={"job_id": job_id}, - ) - - def index_delta(self) -> Any: - """Append a BM25 delta segment for the unindexed WAL tail.""" - return self._request("POST", "/v1/index/delta") - - def index_gc( - self, *, keep_runs: int | None = None, dry_run: bool | None = None - ) -> Any: - """Preview or delete superseded persisted index runs.""" - return self._request( - "POST", "/v1/index/gc", params={"keep_runs": keep_runs, "dry_run": dry_run} - ) - - def index_gc_submit( - self, body: Body | None = None, *, idempotency_key: str - ) -> models.IndexGcJobStatusResponse: - """Submit durable index GC with reconnect-safe progress.""" - return self._model_request( - models.IndexGcJobStatusResponse, - "POST", - "/v1/index/gc-jobs", - body=body or {}, - idempotency_key=idempotency_key, - ) - - def index_gc_job(self, job_id: str) -> models.IndexGcJobStatusResponse: - """Poll durable index-GC planning and deletion progress.""" - return self._model_request( - models.IndexGcJobStatusResponse, - "GET", - "/v1/index/gc-jobs", - params={"job_id": job_id}, - ) - - def cancel_index_gc_job(self, job_id: str) -> models.IndexGcJobStatusResponse: - """Cancel durable index garbage collection.""" - return self._model_request( - models.IndexGcJobStatusResponse, - "DELETE", - "/v1/index/gc-jobs", - params={"job_id": job_id}, - ) - def compact( self, *, min_tail_commits: int | None = None, max_segments: int | None = None ) -> Any: @@ -1764,31 +1550,21 @@ def status(self) -> Any: def metadata( self, *, - include_objects: bool | None = None, include_indexes: bool | None = None, - include_temporal_coverage: bool | None = None, ) -> Any: - """Graph footprint, WAL tail, and index coverage. - - Exact recursive object inventory is opt-in because its cost grows with - object count. - """ + """Graph footprint, WAL tail, and published-index coverage.""" return self._request( "GET", "/v1/graph/metadata", params={ - "include_objects": include_objects, "include_indexes": include_indexes, - "include_temporal_coverage": include_temporal_coverage, }, ) def metadata_model( self, *, - include_objects: bool | None = None, include_indexes: bool | None = None, - include_temporal_coverage: bool | None = None, ) -> models.GraphMetadataResponse: """Graph metadata validated as ``GraphMetadataResponse``.""" return self._model_request( @@ -1796,9 +1572,7 @@ def metadata_model( "GET", "/v1/graph/metadata", params={ - "include_objects": include_objects, "include_indexes": include_indexes, - "include_temporal_coverage": include_temporal_coverage, }, ) @@ -1822,54 +1596,18 @@ def summary_model(self) -> models.GraphSummaryResponse: models.GraphSummaryResponse, "GET", "/v1/graph/summary" ) - def graph_edges( - self, - *, - id: str | None = None, - type: str | None = None, - name: str | None = None, - direction: str | None = None, - relation: str | None = None, - q: str | None = None, - limit: int | None = None, - cursor: str | int | None = None, - offset: int | None = None, - as_of: str | None = None, - as_of_commit_seq: int | None = None, - ) -> Any: - """Paged edge listing in the unified list envelope. - - Scope to one node with ``id`` (or ``type`` + ``name``) and a - ``direction`` (``out`` / ``in`` / ``both``) to walk **every** edge of a - high-degree node. Returns ``{object, data, has_more, next_cursor, - snapshot, total_count}`` — the same envelope as ``entities.list`` — so - page by feeding ``next_cursor`` back as ``cursor`` (the legacy ``offset`` - is still accepted). Optional ``relation`` / ``q`` filters and an - ``as_of`` / ``as_of_commit_seq`` snapshot pin. Each edge row carries - ``valid_time``, so a page is enough to reconstruct a per-edge timeline. - """ - return self._request( + def read_snapshot(self) -> Any: + """Pinned published read root and same-epoch query/conformance lag.""" + return self._request("GET", "/v1/graph/read-snapshot") + + def read_snapshot_model(self) -> models.PublishedReadStatusResponse: + """Published read status validated as ``PublishedReadStatusResponse``.""" + return self._model_request( + models.PublishedReadStatusResponse, "GET", - "/v1/graph/edges", - params={ - "id": id, - "type": type, - "name": name, - "direction": direction, - "relation": relation, - "q": q, - "limit": limit, - "cursor": cursor, - "offset": offset, - "as_of": as_of, - "as_of_commit_seq": as_of_commit_seq, - }, + "/v1/graph/read-snapshot", ) - def graph_edges_page(self, **kwargs: Any) -> ListPage[models.GraphEdgeRow]: - """Paged edges with rows validated as ``GraphEdgeRow``.""" - return self._page_request(models.GraphEdgeRow, self.graph_edges(**kwargs)) - def list_graphs(self) -> Any: """List the graphs (and branches) under the scoped tenant.""" return self._request("GET", "/v1/graphs") @@ -1896,20 +1634,12 @@ def _model_request( def _page_request(self, row_model: type[RowT], payload: Any) -> Any: raise NotImplementedError - def _iter_entity_pages(self, **kwargs: Any) -> Any: - raise NotImplementedError - - def _iter_entity_rows(self, **kwargs: Any) -> Any: - raise NotImplementedError - def sparql( self, query: str, *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -2089,65 +1819,6 @@ def retract_model( idempotency_key=idempotency_key or self._client.idempotency_key("retract"), ) - def export_rdf( - self, - *, - format: str = "turtle", - max_triples: int | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> Any: - """Export this graph's snapshot as Turtle, N-Triples, TriG, or N-Quads.""" - if format not in {"turtle", "ntriples", "trig", "nquads"}: - raise ValueError("format must be 'turtle', 'ntriples', 'trig', or 'nquads'") - return self._client._request( - "GET", - "/v1/graph/export/rdf", - params={ - "graph": self._graph, - "branch": self._branch, - "format": "nt" if format == "ntriples" else format, - "max_triples": max_triples, - "as_of_valid_time": as_of_valid_time, - "as_of_commit_seq": as_of_commit_seq, - "entailment": entailment, - "reason": reason, - }, - ) - - def export_rdf_preview( - self, - *, - format: str = "turtle", - max_triples: int = 100, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, - entailment: str | None = None, - reason: bool | None = None, - ) -> models.RdfExportPreviewResponse: - """Return a bounded typed RDF preview for this explicit graph scope.""" - if format not in {"turtle", "ntriples", "trig", "nquads"}: - raise ValueError("format must be 'turtle', 'ntriples', 'trig', or 'nquads'") - return self._client._model_request( - models.RdfExportPreviewResponse, - "GET", - "/v1/graph/export/rdf", - params={ - "graph": self._graph, - "branch": self._branch, - "format": "nt" if format == "ntriples" else format, - "max_triples": max_triples, - "truncate": "true", - "as_of_valid_time": as_of_valid_time, - "as_of_commit_seq": as_of_commit_seq, - "entailment": entailment, - "reason": reason, - }, - ) - - class _FactsNamespace: def __init__(self, client: _BaseLbbClient, graph: str, branch: str | None) -> None: self._client = client @@ -2187,7 +1858,7 @@ def import_ndjson( batch: int | None = None, strict: bool | None = None, observed_at: str | None = None, - index: bool | None = None, + publish: bool | None = None, idempotency_key: str | None = None, ) -> Any: """Bulk-load a dataset as NDJSON. See :meth:`LbbClient.import_ndjson`.""" @@ -2205,7 +1876,7 @@ def import_ndjson( "batch": batch, "strict": strict, "observed_at": observed_at, - "index": index, + "publish": publish, }, content=ndjson, content_type="application/x-ndjson", @@ -2214,9 +1885,8 @@ def import_ndjson( def import_rdf( self, - rdf: str | None = None, + rdf: str, *, - ntriples: str | None = None, format: str = "ntriples", base_iri: str | None = None, graph_uri: str | None = None, @@ -2226,19 +1896,10 @@ def import_rdf( observed_at: str | None = None, resource_type: str | None = None, edge_idempotency: str | None = None, + publish: bool | None = None, idempotency_key: str | None = None, ) -> Any: """Bulk-load N-Triples, Turtle, N-Quads, or TriG. See :meth:`LbbClient.import_rdf`.""" - if rdf is not None and ntriples is not None: - raise TypeError("pass exactly one of rdf= or the deprecated ntriples=") - if rdf is None: - rdf = ntriples - if rdf is None: - raise TypeError("import_rdf() requires RDF text via rdf= or ntriples=") - if ntriples is not None and format != "ntriples": - raise ValueError( - "the deprecated ntriples= keyword requires format='ntriples'" - ) content_types = { "ntriples": "application/n-triples", "turtle": "text/turtle", @@ -2262,6 +1923,7 @@ def import_rdf( "blank_node_scope": blank_node_scope, "resource_type": resource_type, "edge_idempotency": edge_idempotency, + "publish": publish, }, content=rdf, content_type=content_types[format], @@ -2279,7 +1941,6 @@ def __call__( query: str, *, top_k: int | None = None, - source: str | None = None, consistency: str | None = None, min_indexed_seq: int | None = None, ) -> Any: @@ -2287,7 +1948,6 @@ def __call__( return self.hybrid( query, top_k=top_k, - source=source, consistency=consistency, min_indexed_seq=min_indexed_seq, ) @@ -2301,7 +1961,6 @@ def hybrid(self, query_or_body: str | Body, **kwargs: Any) -> Any: params = { "query": query_or_body, "top_k": kwargs.get("top_k"), - "source": kwargs.get("source"), "consistency": consistency, "min_indexed_seq": min_indexed_seq, "targets": ( @@ -2334,22 +1993,11 @@ def hybrid(self, query_or_body: str | Body, **kwargs: Any) -> Any: class _ContextNamespace: - """Typed grounding, completion, decoding, and answer operations.""" + """Typed grounding, completion, and decoding operations.""" def __init__(self, client: _BaseLbbClient) -> None: self._client = client - def ask( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.AskResponse: - return self._client._model_request( - models.AskResponse, - "POST", - "/v1/ask", - body=body, - options=_read_options(options), - ) - def suggest( self, body: Body, *, options: RequestOptions | None = None ) -> models.SearchSuggestResponse: @@ -2394,7 +2042,6 @@ def groundability( options=_read_options(options), ) - class _OntologyNamespace: """Typed ontology discovery and lifecycle operations.""" @@ -2413,12 +2060,18 @@ def view( ) def conformance( - self, *, options: RequestOptions | None = None + self, + *, + consistency: str | None = None, + options: RequestOptions | None = None, ) -> models.SchemaAuditReport: return self._client._model_request( models.SchemaAuditReport, "GET", "/v1/ontology/conformance", + params={ + "consistency": self._client._resolve_consistency(consistency), + }, options=options, ) @@ -2518,7 +2171,7 @@ def draft_reject(self, draft_id: str, reason: str) -> models.OntologyDraft: class _QueryNamespace: - """Typed structured, SPARQL-text, analytical, and reasoning queries.""" + """Typed structured, SPARQL-text, and analytical queries.""" def __init__(self, client: _BaseLbbClient) -> None: self._client = client @@ -2545,8 +2198,6 @@ def sparql( *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -2556,8 +2207,6 @@ def sparql( query, reason=reason, entailment=entailment, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, limit=limit, offset=offset, consistency=consistency, @@ -2586,111 +2235,43 @@ def conflicts( options=_read_options(options), ) - def shacl( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.ShaclQueryResponse: - return self._client._model_request( - models.ShaclQueryResponse, - "POST", - "/v1/query/shacl", - body=body, - options=_read_options(options), - ) - - def infer( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.InferenceRunResponse: - return self._client._model_request( - models.InferenceRunResponse, - "POST", - "/v1/inference/run", - body=body, - options=_read_options(options), - ) - - def premises( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.RetrievalPremiseResponse: - return self._client._model_request( - models.RetrievalPremiseResponse, - "POST", - "/v1/inference/retrieval-premises", - body=body, - options=_read_options(options), - ) - - class _SchemaNamespace: + """Active ontology/SHACL bundle metadata and atomic publication.""" + def __init__(self, client: _BaseLbbClient) -> None: self._client = client - def view(self, *, audit: bool = False) -> Any: - """Active graph schema bundle: ontology plus activated SHACL shapes.""" - return self._client._request( - "GET", - "/v1/schema", - params={"audit": "true" if audit else None}, - ) - - def view_model(self, *, audit: bool = False) -> models.SchemaBundleView: - """Active schema bundle validated as ``SchemaBundleView``.""" - return self._client._model_request( - models.SchemaBundleView, - "GET", - "/v1/schema", - params={"audit": "true" if audit else None}, - ) - - def preview(self, body: Body) -> Any: - """Preview a proposed RDF/SHACL schema bundle and audit current data.""" - return self._client._request("POST", "/v1/schema/preview", body=body) + def view(self) -> Any: + """Read active metadata without running request-time validation.""" + return self._client._request("GET", "/v1/schema") - def preview_model(self, body: Body) -> models.SchemaPreviewResponse: - """Schema preview validated as ``SchemaPreviewResponse``.""" + def view_model(self) -> models.SchemaBundleView: return self._client._model_request( - models.SchemaPreviewResponse, "POST", "/v1/schema/preview", body=body + models.SchemaBundleView, "GET", "/v1/schema" ) - def publish(self, body: Body) -> Any: - """Activate a previewed SHACL schema bundle for this graph branch.""" - return self._client._request("POST", "/v1/schema/publish", body=body) - - def publish_model(self, body: Body) -> models.SchemaPublishResponse: - """Schema publish response validated as ``SchemaPublishResponse``.""" - return self._client._model_request( - models.SchemaPublishResponse, "POST", "/v1/schema/publish", body=body + def publish( + self, body: Body, *, idempotency_key: str | None = None + ) -> Any: + """Atomically publish a bundle; conformance is produced asynchronously.""" + return self._client._request( + "POST", + "/v1/schema/publish", + body=body, + idempotency_key=idempotency_key + or self._client.idempotency_key("schema-publish"), ) - def audit(self) -> Any: - """Audit current data against the active SHACL schema bundle.""" - return self._client._request("POST", "/v1/schema/audit") - - def audit_model(self) -> models.SchemaAuditReport: - """Schema audit validated as ``SchemaAuditReport``.""" + def publish_model( + self, body: Body, *, idempotency_key: str | None = None + ) -> models.SchemaPublishResponse: return self._client._model_request( - models.SchemaAuditReport, "POST", "/v1/schema/audit" - ) - - -class _IndexNamespace: - def __init__(self, client: _BaseLbbClient) -> None: - self._client = client - - def run( - self, - *, - wait: bool = True, - background: bool | None = None, - body: Body | None = None, - ) -> Any: - run_background = ( - background if background is not None else (False if wait else True) - ) - return self._client._request( + models.SchemaPublishResponse, "POST", - "/v1/index/run", - params={"background": "true" if run_background else None}, + "/v1/schema/publish", body=body, + idempotency_key=idempotency_key + or self._client.idempotency_key("schema-publish"), ) @@ -2705,10 +2286,9 @@ def sample( limit: int | None = None, options: RequestOptions | None = None, ) -> models.EntityTypeSampleResponse: - """Return exact type cardinality and a bounded ranged-index sample. - - The server returns ``index_busy`` instead of falling back to an - exhaustive snapshot scan while the adjacency index is unavailable. + """Return exact type cardinality and a bounded sample from the ranged + adjacency family pinned by the published generation. Missing published + state fails closed instead of falling back to an exhaustive scan. """ return self._client._model_request( models.EntityTypeSampleResponse, @@ -2718,69 +2298,6 @@ def sample( options=_read_options(options), ) - def list( - self, - *, - type: str | None = None, # noqa: A002 - mirrors the HTTP query param. - limit: int | None = None, - cursor: str | int | None = None, - offset: int | None = None, - query: str | None = None, - fields: str | Sequence[str] | None = None, - ids: str | Sequence[str] | None = None, - ) -> Any: - """Browse entities as the unified list envelope. - - Pass ``fields`` (names, or ``"*"`` for all) to inline each row's typed - attributes as native JSON (under ``attributes``) — "list entities and - their titles" in one call instead of a list plus N point lookups — or - ``ids`` to bulk-fetch a specific set. Page with ``cursor`` from the - previous ``next_cursor``. - """ - - def _csv(value: str | Sequence[str] | None) -> str | None: - if value is None or isinstance(value, str): - return value - return ",".join(value) - - return self._client._request( - "GET", - "/v1/graph/entities", - params={ - "type": type, - "limit": limit, - "cursor": cursor, - "offset": offset, - "q": query, - "fields": _csv(fields), - "ids": _csv(ids), - }, - ) - - def list_page(self, **kwargs: Any) -> Any: - """Paged entities with rows validated as ``EntityExplorerRow``.""" - return self._client._page_request(models.EntityExplorerRow, self.list(**kwargs)) - - def filter( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.EntityFilterResponse: - """Snapshot-pinned entity filtering with typed projected attributes.""" - return self._client._model_request( - models.EntityFilterResponse, - "POST", - "/v1/graph/entities/filter", - body=body, - options=_read_options(options), - ) - - def pages(self, **kwargs: Any) -> Any: - """Follow list cursors and yield typed :class:`ListPage` envelopes.""" - return self._client._iter_entity_pages(**kwargs) - - def iter(self, **kwargs: Any) -> Any: - """Follow list cursors and yield typed ``EntityExplorerRow`` objects.""" - return self._client._iter_entity_rows(**kwargs) - def filter_by_attributes( self, *, @@ -2790,8 +2307,6 @@ def filter_by_attributes( select: Sequence[str] | None = None, limit: int | None = None, offset: int | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, order_by: Sequence[Mapping[str, Any]] | None = None, reason: bool | None = None, max_solutions: int | None = None, @@ -2814,8 +2329,6 @@ def filter_by_attributes( select=select, limit=limit, offset=offset, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, order_by=order_by, reason=reason, max_solutions=max_solutions, @@ -2842,8 +2355,6 @@ def _filter_by_attributes_body( select: Sequence[str] | None = None, limit: int | None = None, offset: int | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, order_by: Sequence[Mapping[str, Any]] | None = None, reason: bool | None = None, max_solutions: int | None = None, @@ -2861,8 +2372,6 @@ def _filter_by_attributes_body( "select": list(select) if select is not None else None, "limit": limit, "offset": offset, - "as_of_valid_time": as_of_valid_time, - "as_of_commit_seq": as_of_commit_seq, "order_by": list(order_by) if order_by is not None else None, "reason": reason, "max_solutions": max_solutions, diff --git a/lbb/_sync_client.py b/lbb/_sync_client.py index 8007ed0..71f2e2b 100644 --- a/lbb/_sync_client.py +++ b/lbb/_sync_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import time -from collections.abc import Callable, Iterator, Mapping +from collections.abc import Callable, Mapping from typing import Any, cast import httpx @@ -36,13 +36,11 @@ _retry_allowed, _retry_delay_seconds, _retryable, + _SchemaNamespace, ) class _SyncContextNamespace(_ContextNamespace): - def ask(self, body: Body, *, options: RequestOptions | None = None) -> models.AskResponse: - return cast(models.AskResponse, super().ask(body, options=options)) - def suggest( self, body: Body, *, options: RequestOptions | None = None ) -> models.SearchSuggestResponse: @@ -53,7 +51,9 @@ def resolve( ) -> models.ResolveTermResponse: return cast(models.ResolveTermResponse, super().resolve(body, options=options)) - def decode(self, body: Body, *, options: RequestOptions | None = None) -> models.DecodeResponse: + def decode( + self, body: Body, *, options: RequestOptions | None = None + ) -> models.DecodeResponse: return cast(models.DecodeResponse, super().decode(body, options=options)) def groundability( @@ -64,15 +64,22 @@ def groundability( super().groundability(sample=sample, options=options), ) - class _SyncOntologyNamespace(_OntologyNamespace): def view( self, *, counts: bool = False, options: RequestOptions | None = None ) -> models.OntologyView: return cast(models.OntologyView, super().view(counts=counts, options=options)) - def conformance(self, *, options: RequestOptions | None = None) -> models.SchemaAuditReport: - return cast(models.SchemaAuditReport, super().conformance(options=options)) + def conformance( + self, + *, + consistency: str | None = None, + options: RequestOptions | None = None, + ) -> models.SchemaAuditReport: + return cast( + models.SchemaAuditReport, + super().conformance(consistency=consistency, options=options), + ) def search( self, body: Body, *, options: RequestOptions | None = None @@ -121,8 +128,6 @@ def sparql( *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -134,8 +139,6 @@ def sparql( query, reason=reason, entailment=entailment, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, limit=limit, offset=offset, consistency=consistency, @@ -148,40 +151,14 @@ def analytics( ) -> models.AnalyticQueryResponse: return cast(models.AnalyticQueryResponse, super().analytics(body, options=options)) - def shacl( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.ShaclQueryResponse: - return cast(models.ShaclQueryResponse, super().shacl(body, options=options)) - - def infer( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.InferenceRunResponse: - return cast(models.InferenceRunResponse, super().infer(body, options=options)) - - def premises( - self, body: Body, *, options: RequestOptions | None = None - ) -> models.RetrievalPremiseResponse: - return cast(models.RetrievalPremiseResponse, super().premises(body, options=options)) - - -class _SyncEntityNamespace(_EntityNamespace): - def list_page(self, **kwargs: Any) -> ListPage[models.EntityExplorerRow]: - return cast(ListPage[models.EntityExplorerRow], super().list_page(**kwargs)) - - def pages(self, **kwargs: Any) -> Iterator[ListPage[models.EntityExplorerRow]]: - return cast(Iterator[ListPage[models.EntityExplorerRow]], super().pages(**kwargs)) - - def iter(self, **kwargs: Any) -> Iterator[models.EntityExplorerRow]: - return cast(Iterator[models.EntityExplorerRow], super().iter(**kwargs)) - - class LbbClient(_BaseLbbClient): """Synchronous client. Usable as a context manager.""" context: _SyncContextNamespace - entities: _SyncEntityNamespace + entities: _EntityNamespace ontology: _SyncOntologyNamespace query: _SyncQueryNamespace + schema: _SchemaNamespace def __init__( self, @@ -190,7 +167,7 @@ def __init__( api_key: str | None = None, graph: str | None = None, branch: str | None = None, - api_version: str = "2026-07-22", + api_version: str = "2026-07-23", max_retries: int = DEFAULT_MAX_RETRIES, retry_delay: float = 0.1, retry_budget_ms: float = DEFAULT_RETRY_BUDGET_MS, @@ -213,9 +190,10 @@ def __init__( default_consistency=default_consistency, ) self.context = _SyncContextNamespace(self) - self.entities = _SyncEntityNamespace(self) + self.entities = _EntityNamespace(self) self.ontology = _SyncOntologyNamespace(self) self.query = _SyncQueryNamespace(self) + self.schema = _SchemaNamespace(self) self._http = httpx.Client(timeout=timeout, transport=transport, event_hooks=event_hooks) def raw_request( @@ -354,55 +332,6 @@ def _model_request( def _page_request(self, row_model: type[RowT], payload: Any) -> ListPage[RowT]: return ListPage.from_payload(payload, row_model) - def _iter_entity_pages(self, **kwargs: Any) -> Iterator[ListPage[models.EntityExplorerRow]]: - cursor = kwargs.pop("cursor", None) - initial_offset = kwargs.pop("offset", None) - seen: set[str] = set() - while True: - page = self.entities.list_page( - **kwargs, - cursor=cursor, - offset=initial_offset if cursor is None else None, - ) - yield page - if not page.has_more or page.next_cursor is None: - return - if page.next_cursor in seen: - raise RuntimeError(f"entity pagination cursor repeated: {page.next_cursor}") - seen.add(page.next_cursor) - cursor = page.next_cursor - - def _iter_entity_rows(self, **kwargs: Any) -> Iterator[models.EntityExplorerRow]: - for page in self._iter_entity_pages(**kwargs): - yield from page - - def wait_for_index( - self, *, timeout: float = 600.0, poll_interval: float = 2.0 - ) -> dict[str, Any]: - """Block until the persisted index has caught up with the WAL head. - - Pairs with ``index_run(background=True)``: polls :meth:`metadata` until the - persisted index has caught up, or until ``timeout`` seconds elapse (raises - ``TimeoutError``). Returns the final metadata. Uses the server's - authoritative ``index_caught_up`` signal when present, falling back to the - BM25/ANN/tail predicate for older servers. - """ - deadline = time.monotonic() + timeout - while True: - meta = cast(dict[str, Any], self.metadata()) - caught_up = meta.get("index_caught_up") - if caught_up is None: - caught_up = ( - meta.get("bm25_indexed_commit_seq") is not None - and meta.get("ann_indexed_commit_seq") is not None - and meta.get("unindexed_tail_commits", 1) == 0 - ) - if caught_up: - return meta - if time.monotonic() >= deadline: - raise TimeoutError(f"index did not catch up within {timeout}s (last: {meta})") - time.sleep(poll_interval) - def wait_for_index_lineage( self, target_seq: int, @@ -454,8 +383,6 @@ def sparql( *, reason: bool | None = None, entailment: str | None = None, - as_of_valid_time: str | None = None, - as_of_commit_seq: int | None = None, limit: int | None = None, offset: int | None = None, consistency: str | None = None, @@ -467,8 +394,8 @@ def sparql( with ``.rows()``, ``.vars``, and ``.boolean`` already parsed — no manual ``json.loads`` of a results string. Engine extensions map to query options: ``reason`` (fold rule-derived edges), ``entailment`` (``"none"`` - to disable the default ``rdfs:subClassOf`` closure), the ``as_of_*`` - snapshot pins, and ``limit``/``offset``. + to disable the default ``rdfs:subClassOf`` closure), and + ``limit``/``offset``. Note: this uses ``/v1/query/sparql-text``. A standalone stack also serves the native SPARQL 1.1 *Protocol* at ``/sparql`` for off-the-shelf SPARQL @@ -479,8 +406,6 @@ def sparql( query, reason=reason, entailment=entailment, - as_of_valid_time=as_of_valid_time, - as_of_commit_seq=as_of_commit_seq, limit=limit, offset=offset, consistency=consistency, diff --git a/lbb/models.py b/lbb/models.py index 721d99a..bf5d98e 100644 --- a/lbb/models.py +++ b/lbb/models.py @@ -6,7 +6,7 @@ from enum import Enum from typing import Annotated, Any, Literal -from pydantic import BaseModel, Field, RootModel +from pydantic import BaseModel, ConfigDict, Field, RootModel class Op(Enum): @@ -141,39 +141,6 @@ class AnnTargetKind(Enum): path = 'path' -class AskCitationKind(Enum): - entity = 'entity' - assertion = 'assertion' - - -class AskFeedbackResponse(BaseModel): - accepted: Annotated[ - bool, - Field( - description='True when the verdict was captured. False when signal capture is off\non this deployment — the request contract is identical either way, so\nclients never break when the flag flips.' - ), - ] - accepted_count: Annotated[int, Field(ge=0)] - event_id: str - excluded_count: Annotated[int, Field(ge=0)] - exclusions: dict[str, int] | None = None - receipt_id: str - replayed: bool - trainable_count: Annotated[int, Field(ge=0)] - - -class AskFeedbackVerdict(Enum): - """ - A user verdict on one ask (`POST /v1/ask/feedback`) — the planner's - explicit feedback capture. Joined to the ask's `ask_trace` signal by - `ask_id`. - """ - - accepted = 'accepted' - rejected = 'rejected' - corrected = 'corrected' - - class AskFilterOperatorV2(Enum): eq = 'eq' ne = 'ne' @@ -195,51 +162,12 @@ class AskGraphAnchorV2(BaseModel): entity: str -class AskMode(Enum): - grounding_only = 'grounding_only' - resident_planner = 'resident_planner' - - -class AskNarrowing(BaseModel): - """ - How much the database narrowed the world before the model — the core - context-substrate quantity, exposed per request. - """ - - assertions: Annotated[ - int, Field(description='Assertions (edges) retrieved as evidence.', ge=0) - ] - entities: Annotated[int, Field(description='Entities retrieved as evidence.', ge=0)] - vocab_candidates: Annotated[ - int, - Field( - description='Vocabulary terms the question snapped to (classes/relations/properties) —\nthe narrowed candidate set, a subset of real vocabulary by construction.', - ge=0, - ), - ] - - class AskPlanExecutionModeV2(Enum): entity_search = 'entity_search' path_search = 'path_search' hybrid = 'hybrid' -class AskPlanFailureCode(Enum): - planner_disabled = 'planner_disabled' - planner_unavailable = 'planner_unavailable' - no_class_candidates = 'no_class_candidates' - generation_failed = 'generation_failed' - validation_failed = 'validation_failed' - - -class AskPlanFailureStage(Enum): - configuration = 'configuration' - target_type = 'target_type' - relation = 'relation' - anchor = 'anchor' - - class AskRelationDirectionV2(Enum): outgoing = 'outgoing' incoming = 'incoming' @@ -280,38 +208,6 @@ class AskStructuredQuery(BaseModel): ] -class AskTimings(BaseModel): - """ - Per-stage wall-clock latency for one `/v1/ask` call, in milliseconds. - """ - - decode_ms: Annotated[ - float | None, - Field( - description='Shortlist-constrained structured-query decode on the resident model;\nabsent when the constrained leg did not run.' - ), - ] = None - ground_ms: Annotated[ - float, - Field(description='Grounding the question to real vocabulary (WS11 resolve).'), - ] - retrieve_ms: Annotated[ - float, - Field( - description='Hybrid retrieval against the pinned snapshot. Zero when `execute` is false.' - ), - ] - synth_ms: Annotated[ - float | None, - Field( - description='Resident-model synthesis; absent when no planner ran (`grounding_only`).' - ), - ] = None - total_ms: Annotated[ - float, Field(description='End-to-end latency of the whole call.') - ] - - class AskTypedFilterV2(BaseModel): field: str operator: AskFilterOperatorV2 @@ -592,12 +488,6 @@ class EmbeddingIndexClusterView(BaseModel): sample_labels: list[str] -class EmbeddingIndexSource(Enum): - ephemeral = 'ephemeral' - persisted = 'persisted' - persisted_only = 'persisted_only' - - class Kind(Enum): hash = 'hash' @@ -732,10 +622,9 @@ class FacetResult(BaseModel): missing: Annotated[int, Field(ge=0)] -class FullTextIndexSource(Enum): - ephemeral = 'ephemeral' - persisted = 'persisted' - persisted_only = 'persisted_only' +class FullTextIndexInspectRequest(BaseModel): + include_terms: bool + targets: list[AnnTargetKind] class FullTextSearchResult(BaseModel): @@ -920,23 +809,6 @@ class GraphForkResponse(BaseModel): src_graph_id: str -class GraphImportIndexOutcome(BaseModel): - """ - Outcome of the optional one-shot index build a bulk import runs at the end - when `?index=true` is passed — the "bulk load, queryable on return" - primitive. `built` is whether the full build completed, so the imported data - is served from the persisted runs (not just the ephemeral snapshot fallback) - by the time the request returns. `skipped_reason` is present only when - `built` is false: `"index_busy"` (the node's build-admission gate was busy — - the data is committed and queryable, retry the build later) or - `"index_error"` (the build failed; detail is logged server-side, not - surfaced, to avoid leaking internal paths). - """ - - built: bool - skipped_reason: str | None = None - - class GraphImportLineError(BaseModel): """ A per-line parse/commit failure surfaced by the bulk importer. `line` is the @@ -948,51 +820,6 @@ class GraphImportLineError(BaseModel): message: str -class GraphImportResponse(BaseModel): - """ - Aggregate outcome of a bulk NDJSON import. `committed_commit_seq` is the - sequence of the last internal batch commit (absent if nothing committed). - `errors` is bounded; `error_count` is the true total even when the list is - truncated. `index` is present only when the caller passed `?index=true`. - """ - - batches: Annotated[int, Field(ge=0)] - committed_commit_seq: CommitSeq | None = None - error_count: Annotated[int, Field(ge=0)] - errors: list[GraphImportLineError] | None = None - graph_created: bool - idempotency_key: Annotated[ - str, - Field( - description='The caller key, or the server-minted key when the caller omitted one.' - ), - ] - idempotent_replay: Annotated[ - bool, - Field( - description='True when every internal mutation batch was the already-committed\nreceipt for this idempotency key.' - ), - ] - index: GraphImportIndexOutcome | None = None - indexed: bool - lines_read: Annotated[int, Field(ge=0)] - mutation_receipt_id: Annotated[ - str, - Field( - description='Stable identity for the whole multi-batch mutation. Replays return this\nexact receipt and the original terminal commit sequence.' - ), - ] - observations: Annotated[ - int | None, - Field( - description='Exact observation records imported from a full-fidelity export.', - ge=0, - ), - ] = None - properties: Annotated[int, Field(ge=0)] - triplets: Annotated[int, Field(ge=0)] - - class GraphRdfImportError(BaseModel): """ A bounded parse error from RDF bulk import. The RDF parser reports syntax @@ -1009,46 +836,17 @@ class GraphRdfImportPredicate(BaseModel): `uri` is the original RDF predicate IRI. `relation` is the fixed `RDF_TRIPLE` relation used for committed edges, while `lbb_predicate_iri` remains the source predicate IRI that the RDF/SPARQL projection emits. - `property` and `lbb_property_iri` are retained as nullable compatibility - fields for older clients and are not populated by the fixed-schema importer. """ lbb_predicate_iri: str - lbb_property_iri: str | None = None lbb_relation_iri: str literal_triples: Annotated[int, Field(ge=0)] - property: str | None = None relation: str resource_triples: Annotated[int, Field(ge=0)] triples: Annotated[int, Field(ge=0)] uri: str -class GraphRdfImportResponse(BaseModel): - """ - Aggregate outcome of an RDF import. Every RDF statement is committed - through a fixed `RDF_TRIPLE` edge; source predicate and literal term metadata - are stored on the edge so the RDF/SPARQL projection can emit source RDF terms - while avoiding one ontology relation/property per source predicate. - """ - - batches: Annotated[int, Field(ge=0)] - committed_commit_seq: CommitSeq | None = None - duplicate_literal_triples: Annotated[int, Field(ge=0)] - duplicate_resource_triples: Annotated[int, Field(ge=0)] - error_count: Annotated[int, Field(ge=0)] - errors: list[GraphRdfImportError] | None = None - graph_created: bool - imported_triplets: Annotated[int, Field(ge=0)] - indexed: bool - lines_read: Annotated[int, Field(ge=0)] - literal_triples: Annotated[int, Field(ge=0)] - predicate_count: Annotated[int, Field(ge=0)] - predicates: list[GraphRdfImportPredicate] | None = None - resource_triples: Annotated[int, Field(ge=0)] - triples_read: Annotated[int, Field(ge=0)] - - class GraphReloadResponse(BaseModel): """ Outcome of `POST /v1/graph/reload` — the declarative "make the graph match @@ -1249,47 +1047,6 @@ class HybridSourceRank(BaseModel): weighted_rrf: float -class IndexGcJobProgress(BaseModel): - deleted_bytes: Annotated[int, Field(ge=0)] - deleted_objects: Annotated[int, Field(ge=0)] - heartbeat_micros: int | None = None - reclaimable_bytes: Annotated[int, Field(ge=0)] - reclaimable_objects: Annotated[int, Field(ge=0)] - reclaimable_runs: Annotated[int, Field(ge=0)] - scanned_bytes: Annotated[int, Field(ge=0)] - scanned_objects: Annotated[int, Field(ge=0)] - scanned_runs: Annotated[int, Field(ge=0)] - stage: str - worker: str | None = None - - -class IndexGcRequest(BaseModel): - dry_run: Annotated[ - bool | None, - Field(description='Report what would be deleted without deleting anything.'), - ] = None - include_branch_shared: Annotated[ - bool | None, - Field( - description='Delete runs even when other branches exist in the graph. Child\nbranches fall back to parent-branch index runs until they build their\nown, so deleting shared parent runs can force child rebuilds.' - ), - ] = None - keep_runs: Annotated[ - int | None, - Field( - description='Keep this many newest index runs per family (bm25/ann grouping key).\nThe newest run is always kept regardless of this value.', - ge=0, - ), - ] = None - reader_grace_commits: Annotated[ - int | None, - Field( - description='Reader grace: retain any run whose snapshot is within this many commits\nof the current head, even when it exceeds `keep_runs`. A search that\nalready resolved a now-superseded run keeps reading its objects, so\ncollecting a recently-passed run out from under an in-flight reader\nsurfaces as a NotFound/500. The grace window protects those runs until\nthe head has advanced far enough that no in-flight search can still be\nholding them. Set to 0 to disable the grace and collect purely by\n`keep_runs` ordering.', - ge=0, - ), - ] = None - - class IndexLineage(BaseModel): """ Typed convergence view over the persisted serving families. @@ -1309,18 +1066,9 @@ class IndexLineage(BaseModel): observed_at_micros: int -class IndexRunView(BaseModel): - bytes: Annotated[int, Field(ge=0)] - family: str - kept: bool - objects: Annotated[int, Field(ge=0)] - prefix: str - snapshot_commit_seq: Annotated[int, Field(ge=0)] - - class IndexVisibilityFamily(Enum): """ - One of the index families published through the unified visibility manifest. + One of the index families referenced by an atomic published read root. """ base = 'base' @@ -1330,15 +1078,6 @@ class IndexVisibilityFamily(Enum): adjacency = 'adjacency' -class IndexVisibilityFamilyClass(Enum): - """ - How a family participates in the unified visibility watermark. - """ - - lockstep = 'lockstep' - merged_only = 'merged_only' - - class LbbErrorBody(BaseModel): code: Annotated[str, Field(examples=['missing_idempotency_key'])] doc_url: str | None @@ -1378,7 +1117,10 @@ class ManagedEmbeddingBackfillJobRequest(BaseModel): class ManagedEmbeddingBackfillResponse(BaseModel): """ - Outcome of embedding the corpus and rebuilding its Stored ANN index. + Outcome of embedding the corpus and scheduling a complete published + generation. `indexed_commit_seq` remains zero until publication; + `final_index_job_id` identifies the durable generation build when one was + enqueued. ANN is never cut over independently. """ batches: Annotated[int, Field(ge=0)] @@ -1981,8 +1723,8 @@ class PathResult(BaseModel): class PlannerServingDefaults(BaseModel): """ Planner serving default derived from a promoted `planner` run: the LoRA - adapter (a path on the model-serving volume) `/v1/ask` passes to the - resident planner endpoint per generate call. + adapter (a path on the model-serving volume) planner-backed workflows pass + to the resident model per generate call. """ adapter: Annotated[ @@ -2103,38 +1845,40 @@ class PropertyValueInput8(BaseModel): ] -class Kind6(Enum): - asserted = 'asserted' - - -class ProvenanceLeafView1(BaseModel): +class PublishedGenerationEnqueueDisposition(Enum): """ - An asserted edge event this fact transitively rests on (hex id). + Whether an import's deterministic published-generation job was newly + queued or coalesced with equivalent pending work. """ - edge_event_id: str - kind: Kind6 + queued = 'queued' + coalesced = 'coalesced' -class Kind7(Enum): - retrieval = 'retrieval' +class PublishedReadConformanceView(BaseModel): + """ + Published conformance provenance. `validated_at_seq` may trail the common + query watermark while the next durable validation is running. + """ + + artifact_format_version: Annotated[int, Field(ge=0)] + ontology_version: Annotated[int, Field(ge=0)] + shapes_version: Annotated[int | None, Field(ge=0)] = None + validated_at_seq: Annotated[int, Field(ge=0)] -class ProvenanceLeafView2(BaseModel): +class PublishedReadFamilyView(BaseModel): """ - A calibrated retrieval match that *seeded* this fact — never an asserted - leaf. Carries the embedding space it came from, the matched entity, and - the calibrated `P(relevant)` used as the premise confidence. + One family present in an atomic published root. Object keys and ETags stay + internal; this is the bounded operational/API projection. """ - calibrated_score: Annotated[ - float, - Field(description='Calibrated `P(relevant)` used as the premise confidence.'), + family: IndexVisibilityFamily + model_hash: str | None = None + root_format_version: Annotated[ + int, Field(description="That family's persisted root-codec version.", ge=0) ] - kind: Kind7 - matched: Annotated[str, Field(description='Matched entity id (hex).')] - model_id: str - target_kind: AnnTargetKind + target_hash: str | None = None class RangedReadStats(BaseModel): @@ -2209,13 +1953,6 @@ class RangedTraverseStats(BaseModel): meta_bytes_fetched: Annotated[int, Field(ge=0)] payload_slices_fetched: Annotated[int | None, Field(ge=0)] = None shard_cache_hits: Annotated[int, Field(ge=0)] - tail_commits_merged: Annotated[ - int | None, - Field( - description='Commits past the indexed run that were merged from the WAL tail\n(append-safe edges only; anything else falls back to the snapshot\nscan).', - ge=0, - ), - ] = None topology_slices_fetched: Annotated[int | None, Field(ge=0)] = None truncated_by_block_budget: bool truncated_by_block_byte_budget: bool @@ -2422,11 +2159,6 @@ class RowPage(BaseModel): total: Annotated[int, Field(ge=0)] -class RuleSetDefineResponse(BaseModel): - rule_count: Annotated[int, Field(ge=0)] - rules_version: Annotated[int, Field(ge=0)] - - class SchemaAuditResult(BaseModel): component: str focus_node: str @@ -2534,12 +2266,12 @@ class SearchConsistency(Enum): Read consistency for a query surface (search, graph summary, SPARQL). A5 (2026-07-21 product decision): `Eventual` is the **default**. It serves the - last published index/dataset state at its watermark with no in-memory fold of - the un-indexed tail — the lowest-latency mode and the availability floor - during any indexing backlog. The served watermark rides back on - `SnapshotView::served_at_seq`. `Strong` (fold the un-indexed tail up to the - query head) is now explicit opt-in; the precise read-your-writes contract - (`min_indexed_seq`) replaces most former uses of strong. See + pinned published generation at its watermark with no request-time graph + assembly — the lowest-latency mode and the availability floor during any + publication backlog. The served watermark rides back on + `SnapshotView::served_at_seq`. `Strong` requires the immutable published + generation itself to cover the query head and is explicit opt-in; the precise + read-your-writes contract (`min_indexed_seq`) replaces most former uses of strong. See `docs/architecture/segment-native-indexing.md` §6. """ @@ -2607,40 +2339,40 @@ class SearchFeedbackSplitCounts(BaseModel): train: Annotated[int, Field(ge=0)] -class Kind8(Enum): +class Kind6(Enum): entity = 'entity' class SearchFeedbackTarget1(BaseModel): entity: EntitySelector - kind: Kind8 + kind: Kind6 -class Kind9(Enum): +class Kind7(Enum): assertion = 'assertion' class SearchFeedbackTarget2(BaseModel): edge_event_id: str - kind: Kind9 + kind: Kind7 -class Kind10(Enum): +class Kind8(Enum): observation = 'observation' class SearchFeedbackTarget3(BaseModel): - kind: Kind10 + kind: Kind8 observation_id: str -class Kind11(Enum): +class Kind9(Enum): concept = 'concept' class SearchFeedbackTarget4(BaseModel): concept_id: str | None = None - kind: Kind11 + kind: Kind9 name: str | None = None @@ -2799,15 +2531,6 @@ class SearchHitContributions(BaseModel): vector_manifest_key: str | None = None -class SearchIndexFamilyRun(BaseModel): - family: str - indexed_commit_seq_after: Annotated[int, Field(ge=0)] - indexed_commit_seq_before: CommitSeq | None = None - manifest_key: str | None = None - objects_written: Annotated[int, Field(ge=0)] - skipped: bool - - class SearchOrder(Enum): """ Sort direction for a query's `order_by` key. `Desc` is the default for the @@ -2910,12 +2633,10 @@ class SearchSignalWeights(BaseModel): class SearchTemporalCoverage(BaseModel): """ - How a temporally-pinned (or head) search resolved run selection: the - effective `as_of` ceiling, the base snapshot of the selected persisted - run(s), and the highest commit each leg's run+segments actually covered - (the forward WAL overlay covers `(covered_through, ceiling]`). Distinct from - the ontology-inspect `TemporalCoverage` type. Per-leg fields are `None` when - that leg served from an ephemeral rebuild (no persisted run at the ceiling). + Provenance for the immutable family roots selected from one pinned published + generation. `ceiling_commit_seq` is that generation's common query + watermark; per-leg fields are `None` only when the corresponding leg was + disabled. """ bm25_covered_through: CommitSeq | None = None @@ -2923,7 +2644,7 @@ class SearchTemporalCoverage(BaseModel): ceiling_commit_seq: Annotated[ int, Field( - description='Resolved transaction-time ceiling: the `as_of_commit_seq` pin, or the\nhead commit_seq when the query was unpinned.', + description='Common query watermark of the pinned published generation.', ge=0, ), ] @@ -2940,17 +2661,10 @@ class SemanticPathResult(BaseModel): class SemanticSearchExplain(BaseModel): bm25_candidates: Annotated[int, Field(ge=0)] - bm25_degraded_to_ephemeral: Annotated[ - bool | None, - Field( - description='True when a **persisted** BM25 index was requested but none matched the\nquery\'s resolved target set, so the search silently fell back to a full\nephemeral rebuild (much slower). A common cause is building the index for\na narrower target set than the query resolves to (e.g. `[Entity]` vs the\n`{Entity, Neighborhood}` that `Entities` resolves to). Also bumps the\n`lbb_search_degraded_total{family="bm25"}` metric.' - ), - ] = None bm25_documents: Annotated[int, Field(ge=0)] bm25_indexed_commit_seq: CommitSeq | None = None bm25_manifest_key: str | None = None bm25_ms: Annotated[int | None, Field(ge=0)] = None - bm25_overlay_candidates: Annotated[int, Field(ge=0)] bm25_ranged: RangedReadStats | None = None engine_remainder_ms: Annotated[ int | None, @@ -2972,6 +2686,13 @@ class SemanticSearchExplain(BaseModel): ontology_expansions: Annotated[int, Field(ge=0)] ontology_ms: Annotated[int | None, Field(ge=0)] = None paths_considered: Annotated[int, Field(ge=0)] + published_lag_commits: Annotated[ + int, + Field( + description='Commit distance from the graph head to the pinned published generation.', + ge=0, + ), + ] retrieval_profile: RetrievalProfileId | None = None search_mode: str snapshot_load_ms: Annotated[int | None, Field(ge=0)] = None @@ -2992,20 +2713,7 @@ class SemanticSearchExplain(BaseModel): ge=0, ), ] = None - unindexed_tail_commits: Annotated[int, Field(ge=0)] vector_candidates: Annotated[int, Field(ge=0)] - vector_channel_skipped: Annotated[ - bool | None, - Field( - description='True when latest-head hybrid search requested the persisted vector/ANN\nchannel but no matching run existed, so the optional vector channel was\nskipped instead of silently rebuilding an O(corpus) ephemeral ANN on the\nrequest path. Explicit ephemeral and historical pinned searches retain\ntheir existing behavior.' - ), - ] = None - vector_degraded_to_ephemeral: Annotated[ - bool | None, - Field( - description='As `bm25_degraded_to_ephemeral`, for the persisted vector/ANN index.' - ), - ] = None vector_indexed_commit_seq: CommitSeq | None = None vector_manifest_key: str | None = None vector_model_id: Annotated[ @@ -3015,7 +2723,6 @@ class SemanticSearchExplain(BaseModel): ), ] = None vector_ms: Annotated[int | None, Field(ge=0)] = None - vector_overlay_candidates: Annotated[int, Field(ge=0)] vector_ranged: RangedReadStats | None = None vector_spaces_searched: Annotated[int, Field(ge=0)] @@ -3299,11 +3006,9 @@ class SignalKind(Enum): The closed set of signal kinds (v1). Extending this is a deliberate format change, not an open string. - v1.1 (2026-07-07, planner-feedback capture): adds `ask_trace` - (server-emitted per `/v1/ask`: the question, the decoded plan + its - shortlists, verification flags, retrieval outcome) and `ask_feedback` - (client verdict on an ask, joined to its trace by `request_id`) — the raw - material the planner fine-tune trains on. + v1.1 (2026-07-07, planner-feedback capture): adds the legacy + `ask_trace`/`ask_feedback` supervision records. They remain decodable for + durable training data, but no public Ask endpoint emits them. """ suggestion_shown = 'suggestion_shown' @@ -3361,7 +3066,7 @@ class SnapshotView(BaseModel): compacted_seq: Annotated[ int, Field( - description="Highest commit folded into the **compacted graph snapshot base** (the\nmaterialized segment base). Commits in `(compacted_seq, commit_seq]` live in\nthe WAL tail and are replayed on read — so `compacted_seq: 0` is the normal\nstate of a small or freshly-created graph (no base built yet) and does\n**not** mean the data is unreadable: every read replays the full tail.\n\nThis is *not* search-index coverage. Whether BM25/vector search indexes\nare built — what `/v1/index/run` advances — is reported separately as\n`bm25_indexed_commit_seq` / `ann_indexed_commit_seq` on\n`GET /v1/graph/metadata` and on the entity read's metadata.", + description='Highest durable graph-truth commit folded by background compaction.\nThis is maintenance provenance, not the query-serving watermark.\nPublished reads expose their one common `served_at_seq` through the\nresponse and `/v1/graph/read-snapshot`; handlers never fold the WAL tail\nor assemble derived indexes to satisfy a request.', ge=0, ), ] @@ -3375,7 +3080,7 @@ class SnapshotView(BaseModel): stale_reason: Annotated[ str | None, Field( - description='The reason a read is `stale`. `"storage_degraded"` (F2),\n`"eventual_consistency"` (A3: served from the last published index/dataset\nstate), `"adjacency_coverage"` (served from the newest published\nranged-adjacency snapshot), `"tail_budget_exceeded"` (the eventual RDF\nWAL tail exceeded a per-read bound), `"merge_lag"` (the RDF L0 chain was\ncapped at a coherent prefix), or `"assembly_pool_exhausted"` (the shared\neventual-read byte pool was saturated); omitted when not stale.' + description='The reason a read is `stale`. `"storage_degraded"` (F2),\n`"eventual_consistency"` (served from the immutable published\ngeneration) or `"adjacency_coverage"` (served from that generation\'s\nbounded ranged-adjacency snapshot); omitted when not stale.' ), ] = None @@ -3645,23 +3350,13 @@ class SparqlTextRequest(BaseModel): RDF graph, not a results table). """ - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin: project the graph as of this `commit_seq` before running the\nconformant engine, hiding later commits. Errors if it exceeds the head.', - ge=0, - ), - ] = None - as_of_valid_time: Annotated[ - str | None, - Field( - description='RFC3339 valid-time; query the graph as of that instant. `None` = now.' - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) entailment: Annotated[ SparqlEntailment | None, Field( - description='RDFS entailment regime. `Subclass` (default) makes a query for a class\nmatch instances of its subtypes; `None` matches only the declared type.' + description='RDFS entailment regime. `None` (default) reads the asserted published\nprojection. `Subclass` requires a compatible reasoned projection and\nfails closed while one is unavailable.' ), ] = None limit: Annotated[ @@ -3679,7 +3374,7 @@ class SparqlTextRequest(BaseModel): reason: Annotated[ bool | None, Field( - description="Reason over the branch's stored inference rules: project the rule-derived\nfacts into the dataset the conformant engine runs over, so a query reasons\nover asserted **and** derived edges. Off by default; a no-op when the branch\nhas no stored rules. Combine with `entailment: subclass` (the default) for\nfull reasoning — rule-derived facts plus `rdfs:subClassOf` type closure." + description="Reason over the branch's stored inference rules: project the rule-derived\nfacts into the dataset the conformant engine runs over, so a query reasons\nover asserted **and** derived edges. Off by default; a no-op when the branch\nhas no stored rules. Combine with `entailment: subclass` for full\nreasoning—rule-derived facts plus `rdfs:subClassOf` type closure—once\nmaintenance publishes a compatible reasoned projection." ), ] = None @@ -3910,96 +3605,24 @@ class SyntheticEvalResponse(BaseModel): truncated: bool -class TemporalCoverage(BaseModel): - """ - A self-describing summary of a snapshot's two temporal axes, so an agent can - decide up front which temporal queries are meaningful on this graph. +class TimeGranularity(Enum): + instant = 'instant' + day = 'day' + month = 'month' + year = 'year' + unknown = 'unknown' - The product motivation: a graph backfilled in one batch with no per-fact - `valid_time` looks fully populated but cannot be bisected by date — every - `as_of` returns the same snapshot. The two `*_degenerate` flags say so - explicitly rather than letting a caller render N identical daily panels. + +class TrainGateReport(BaseModel): + """ + The deterministic promotion gate's verdict, reported in full so a held + run is as auditable as a promoted one (null results are data). """ - as_of_valid_time_degenerate: Annotated[ - bool, + effect: Annotated[ + float, Field( - description='True when no event carries a `valid_time` bound: an `as_of_valid_time`\nquery returns all-or-nothing, never a daily progression.' - ), - ] - distinct_commit_count: Annotated[ - int, - Field( - description='Distinct `commit_seq` values among the events: how many commits the data\narrived in. `1` means a single bulk backfill, so `as_of_commit_seq` can\nonly distinguish "before" vs "after" that one batch.', - ge=0, - ), - ] - earliest_commit_time_micros: Annotated[ - int | None, - Field( - description='Transaction-time span (when facts were recorded), in epoch micros.' - ), - ] = None - earliest_valid_time_micros: Annotated[ - int | None, - Field( - description='World-time span over events that carry a `valid_time` bound, in micros.' - ), - ] = None - edge_event_count: Annotated[ - int, - Field( - description='Total append-only edge events in the snapshot overlay.', ge=0 - ), - ] - edges_with_valid_time: Annotated[ - int, - Field( - description='Events whose `valid_time` carries a bounded start and/or end.', - ge=0, - ), - ] - head_commit_seq: Annotated[ - int, - Field( - description='Head `commit_seq` — the largest snapshot pin (`as_of_commit_seq`) a read\ncan request right now.', - ge=0, - ), - ] - latest_commit_time_micros: int | None = None - latest_valid_time_micros: int | None = None - single_commit: Annotated[ - bool, - Field( - description='True when every event arrived in a single commit (a one-shot backfill):\nthere is only one snapshot to pin to, and `as_of` by wall-clock date\ncannot bisect the history. For multi-commit graphs, inspect the\n`*_commit_time_micros` span to judge whether daily bisection is possible.' - ), - ] - valid_time_coverage: Annotated[ - float, - Field( - description='`edges_with_valid_time / edge_event_count`, in `[0,1]`. Near zero means\nan `as_of_valid_time` query cannot bisect this graph by world-time.' - ), - ] - - -class TimeGranularity(Enum): - instant = 'instant' - day = 'day' - month = 'month' - year = 'year' - unknown = 'unknown' - - -class TrainGateReport(BaseModel): - """ - The deterministic promotion gate's verdict, reported in full so a held - run is as auditable as a promoted one (null results are data). - """ - - effect: Annotated[ - float, - Field( - description='Challenger − champion primary quality metric on the held-out eval\nslice (nDCG for fusion and retrieval-profile comparisons).' + description='Challenger − champion primary quality metric on the held-out eval\nslice (nDCG for fusion and retrieval-profile comparisons).' ), ] hit_rate_delta: float | None = None @@ -4483,56 +4106,6 @@ class AnalyticTriplePattern(BaseModel): ] -class AskCitation(BaseModel): - id: Annotated[str, Field(description='Entity id or edge-event id, as a string.')] - kind: AskCitationKind - label: Annotated[ - str, - Field( - description='Human-readable label (entity name, or "src —relation→ dst").' - ), - ] - score: float - - -class AskExplain(BaseModel): - """ - Per-request instrumentation of the `/v1/ask` pipeline: what each stage cost, - how much the DB narrowed the world before the model saw it, and the embedding - model that did the grounding. - """ - - embedding: Annotated[ - str, - Field( - description='The embedding model that grounded + retrieved — its id, or `lexical` for\nthe hash/lexical fallback when the graph has no managed embedding model.' - ), - ] - narrowing: Annotated[ - AskNarrowing, - Field( - description='How much the DB narrowed: the vocabulary the question snapped to and the\nsize of the retrieved evidence set the answer rests on.' - ), - ] - timings: Annotated[ - AskTimings, - Field( - description='Wall-clock latency of each stage of the one call, in milliseconds.' - ), - ] - - -class AskPlanFailure(BaseModel): - code: AskPlanFailureCode - retryable: Annotated[ - bool, - Field( - description='True when retrying after the planner recovers can produce a plan.' - ), - ] - stage: AskPlanFailureStage - - class AskStructuredPlanV2(BaseModel): execution_mode: AskPlanExecutionModeV2 filters: list[AskTypedFilterV2] | None = None @@ -4588,29 +4161,6 @@ class CurrentStateRequest(BaseModel): relations: list[str] | None = None -class DerivedEdgeView(BaseModel): - """ - One derived edge (a fact that follows from the rules but is not asserted). - """ - - confidence: Annotated[ - float, - Field( - description="Confidence inherited from the supporting facts: the **max** over\nderivations of the **min** over each derivation's premises (so a fact is\nas strong as its weakest premise, and the best derivation wins)." - ), - ] - depends_on: Annotated[ - list[ProvenanceLeafView1 | ProvenanceLeafView2] | None, - Field( - description='The provenance trail this fact transitively rests on — typed leaves so an\nasserted edge (`Asserted`) and a calibrated retrieval match (`Retrieval`)\nstay distinguishable and a retrieval match can never masquerade as an\nasserted fact (FAL-PROV-NOT-LAUNDERED). Pure rule derivation resolves to\n`Asserted` leaves only.' - ), - ] = None - object: EntityView - predicate: str - rule: Annotated[str, Field(description='The rule that first derived this edge.')] - subject: EntityView - - class EdgeEventRow(BaseModel): commit_seq: Annotated[int, Field(ge=0)] confidence: float @@ -4666,8 +4216,14 @@ class EmbeddingSearchExplain(BaseModel): manifest_key: str | None = None metric: str model_id: str - overlay_candidates: Annotated[int, Field(ge=0)] probe_count: Annotated[int, Field(ge=0)] + published_lag_commits: Annotated[ + int, + Field( + description='Commit distance from the graph head to the pinned published generation.', + ge=0, + ), + ] ranged: RangedReadStats | None = None reranked_candidates: Annotated[ int | None, @@ -4676,10 +4232,8 @@ class EmbeddingSearchExplain(BaseModel): ge=0, ), ] = None - source: EmbeddingIndexSource spaces_searched: Annotated[int, Field(ge=0)] temporal_coverage: SearchTemporalCoverage | None = None - unindexed_tail_commits: Annotated[int, Field(ge=0)] class EmbeddingSearchResponse(BaseModel): @@ -4763,7 +4317,7 @@ class EntityNeighborhoodRequest(BaseModel): as_of_commit_seq: Annotated[ int | None, Field( - description='Snapshot pin: reproduce the neighborhood as of this `commit_seq`, hiding\nany event committed later. Errors if it exceeds the current head, and\nforces the snapshot scan (the ranged adjacency fast path declines a\npinned read). Omit for the latest snapshot.', + description="Snapshot pin: reproduce the neighborhood as of this `commit_seq`, hiding\nany event committed later. Public serving reduces the entity's bounded\nincident domains from the Base family in the one pinned published\ngeneration; it never discovers or assembles another snapshot. Omit for\nthe latest snapshot.", ge=0, ), ] = None @@ -4844,35 +4398,11 @@ class ExtractorExample(BaseModel): transcript: str -class FullTextIndexBuildRequest(BaseModel): - include_terms: bool - targets: list[AnnTargetKind] - tokenizer: FullTextTokenizerConfig | None = None - - -class FullTextIndexBuildResponse(BaseModel): - average_document_len: float - document_count: Annotated[int, Field(ge=0)] - manifest_etag: str - manifest_key: str - object_etag: str - object_key: str - snapshot: SnapshotView - term_count: Annotated[int, Field(ge=0)] - - -class FullTextIndexInspectRequest(BaseModel): - include_terms: bool - source: FullTextIndexSource | None = None - targets: list[AnnTargetKind] - - class FullTextIndexInspectResponse(BaseModel): average_document_len: float document_count: Annotated[int, Field(ge=0)] manifest_key: str | None = None snapshot: SnapshotView - source: FullTextIndexSource term_count: Annotated[int, Field(ge=0)] terms: list[FullTextTermView] tokenizer: FullTextTokenizerConfig @@ -4886,12 +4416,16 @@ class FullTextSearchExplain(BaseModel): filtered_candidates: Annotated[int, Field(ge=0)] indexed_commit_seq: CommitSeq | None = None manifest_key: str | None = None - overlay_candidates: Annotated[int, Field(ge=0)] + published_lag_commits: Annotated[ + int, + Field( + description='Commit distance from the graph head to the pinned published generation.', + ge=0, + ), + ] ranged: RangedReadStats | None = None - source: FullTextIndexSource temporal_coverage: SearchTemporalCoverage | None = None term_count: Annotated[int, Field(ge=0)] - unindexed_tail_commits: Annotated[int, Field(ge=0)] class FullTextSearchResponse(BaseModel): @@ -4969,6 +4503,65 @@ class GraphEdgeRow(BaseModel): valid_time: ValidTime +class GraphImportPublishedGenerationOutcome(BaseModel): + """ + Durable publication accepted after `POST /v1/graph/import?publish=true`. + The import request never constructs index families or waits for publication; + clients can poll the returned job while continuing to observe the previously + published generation. + """ + + disposition: PublishedGenerationEnqueueDisposition + due_seq: Annotated[int, Field(ge=0)] + job_id: str + status: str + + +class GraphImportResponse(BaseModel): + """ + Aggregate outcome of a bulk NDJSON import. `committed_commit_seq` is the + sequence of the last internal batch commit (absent if nothing committed). + `errors` is bounded; `error_count` is the true total even when the list is + truncated. `published_generation` is present only when the caller passed + `?publish=true` and at least one batch committed. + """ + + batches: Annotated[int, Field(ge=0)] + committed_commit_seq: CommitSeq | None = None + error_count: Annotated[int, Field(ge=0)] + errors: list[GraphImportLineError] | None = None + graph_created: bool + idempotency_key: Annotated[ + str, + Field( + description='The caller key, or the server-minted key when the caller omitted one.' + ), + ] + idempotent_replay: Annotated[ + bool, + Field( + description='True when every internal mutation batch was the already-committed\nreceipt for this idempotency key.' + ), + ] + lines_read: Annotated[int, Field(ge=0)] + mutation_receipt_id: Annotated[ + str, + Field( + description='Stable identity for the whole multi-batch mutation. Replays return this\nexact receipt and the original terminal commit sequence.' + ), + ] + observations: Annotated[ + int | None, + Field( + description='Exact observation records imported from a full-fidelity export.', + ge=0, + ), + ] = None + properties: Annotated[int, Field(ge=0)] + published_generation: GraphImportPublishedGenerationOutcome | None = None + triplets: Annotated[int, Field(ge=0)] + + class GraphKey(BaseModel): branch_id: str graph_id: str @@ -4989,7 +4582,6 @@ class GraphListResponse(BaseModel): class GraphMetadataRequest(BaseModel): dim: Annotated[int | None, Field(ge=0)] = None include_indexes: bool | None = None - include_objects: bool | None = None max_clusters: Annotated[int | None, Field(ge=0)] = None provider: ( EmbeddingProviderConfig1 @@ -5000,6 +4592,31 @@ class GraphMetadataRequest(BaseModel): targets: list[AnnTargetKind] +class GraphRdfImportResponse(BaseModel): + """ + Aggregate outcome of an RDF import. Every RDF statement is committed + through a fixed `RDF_TRIPLE` edge; source predicate and literal term metadata + are stored on the edge so the RDF/SPARQL projection can emit source RDF terms + while avoiding one ontology relation/property per source predicate. + """ + + batches: Annotated[int, Field(ge=0)] + committed_commit_seq: CommitSeq | None = None + duplicate_literal_triples: Annotated[int, Field(ge=0)] + duplicate_resource_triples: Annotated[int, Field(ge=0)] + error_count: Annotated[int, Field(ge=0)] + errors: list[GraphRdfImportError] | None = None + graph_created: bool + imported_triplets: Annotated[int, Field(ge=0)] + lines_read: Annotated[int, Field(ge=0)] + literal_triples: Annotated[int, Field(ge=0)] + predicate_count: Annotated[int, Field(ge=0)] + predicates: list[GraphRdfImportPredicate] | None = None + published_generation: GraphImportPublishedGenerationOutcome | None = None + resource_triples: Annotated[int, Field(ge=0)] + triples_read: Annotated[int, Field(ge=0)] + + class GraphRecallResponse(BaseModel): approximate: list[str] exact: list[str] @@ -5108,145 +4725,6 @@ class HybridMultiSearchResult(BaseModel): type: str -class IndexBuildOptions(BaseModel): - """ - Optional JSON body for the data-plane index-build routes (`/v1/index/run` - and `/v1/index/build`). Every field is optional: an empty body resolves the - ANN space the way the search path does — a managed embedding config selects - its `stored` space (its dim winning), otherwise the server's hash default — - so a bare reindex always rebuilds the space queries actually look up. - Supplying `provider` overrides that resolution, e.g. to persist a build over - committed BYO vectors with an explicit `stored`/`external_vectors` space. - """ - - build_permutation: Annotated[ - bool | None, - Field( - description='Build the object-storage-native permutation view (PSO). Off by default.' - ), - ] = False - dim: Annotated[ - int | None, - Field( - description="Embedding dimension when no `provider.dim` is given. Defaults to the\nserver's configured dim. Must match the committed vectors' dimension.", - ge=0, - ), - ] = None - include_raw_rerank: Annotated[ - bool | None, - Field( - description='Append a raw-f32 rerank region to the embedding run. Off by default.' - ), - ] = False - max_clusters: Annotated[ - int | None, - Field( - description="ANN clusters per space. Defaults to the server's configured value.", - ge=0, - ), - ] = None - provider: ( - EmbeddingProviderConfig1 - | EmbeddingProviderConfig2 - | EmbeddingProviderConfig3 - | None - ) = None - - -class IndexDeltaResponse(BaseModel): - """ - Outcome of an incremental index-run delta build (`index delta`, or the - commit-path auto-delta trigger). `built` is true when a delta segment was - appended; `folded` is true when the chain was instead rebuilt into a fresh - base (chain too long, or freshness fold). `skipped_reason` explains a no-op - (no base run, nothing un-indexed). - """ - - built: bool - delta_document_count: Annotated[int, Field(ge=0)] - family: str - folded: bool - from_commit_seq: Annotated[int, Field(ge=0)] - indexed_seq: Annotated[int, Field(ge=0)] - segments: Annotated[int, Field(ge=0)] - skipped_reason: str | None = None - snapshot: SnapshotView - to_commit_seq: Annotated[int, Field(ge=0)] - - -class IndexFamilyVisibility(BaseModel): - """ - Bounded, user-facing summary of one family in the unified visibility manifest. - """ - - class_: Annotated[IndexVisibilityFamilyClass, Field(alias='class')] - covered_seq: CommitSeq | None = None - family: IndexVisibilityFamily - l0_from_seq: CommitSeq | None = None - l0_segment_count: Annotated[int, Field(ge=0)] - l0_to_seq: CommitSeq | None = None - model_hash: Annotated[ - str | None, - Field( - description='Distinguishes ANN model spaces without exposing object keys.' - ), - ] = None - target_hash: Annotated[ - str | None, - Field( - description='Distinguishes target-specific BM25/ANN families without exposing object keys.' - ), - ] = None - - -class IndexGcResponse(BaseModel): - deleted_bytes: Annotated[int, Field(ge=0)] - deleted_objects: Annotated[int, Field(ge=0)] - deleted_runs: Annotated[int, Field(ge=0)] - dry_run: bool - kept_runs: Annotated[int, Field(ge=0)] - runs: list[IndexRunView] - scanned_bytes: Annotated[int, Field(ge=0)] - scanned_objects: Annotated[int, Field(ge=0)] - skipped_branch_shared: Annotated[ - bool, - Field( - description="Set when deletion was skipped because other branches may share this\nbranch's index runs and `include_branch_shared` was false." - ), - ] - snapshot: SnapshotView - - -class IndexVisibilityManifest(BaseModel): - """ - The unified, per-graph visibility view consumed by the console and status tools. - """ - - epoch: Annotated[int, Field(ge=0)] - families: list[IndexFamilyVisibility] - visible_seq: Annotated[ - int, - Field( - description='Shared published watermark. Lockstep families define this value.', - ge=0, - ), - ] - - -class InferenceRunResponse(BaseModel): - derived: list[DerivedEdgeView] - rounds: Annotated[ - int, Field(description='Number of fixpoint rounds executed.', ge=0) - ] - snapshot: SnapshotView - truncated: Annotated[ - bool, - Field( - description='True if a bound (rounds / derived edges / per-rule solutions) was hit, so\nthe derived set may be incomplete.' - ), - ] - - class ManagedEmbeddingBackfillJobStatusResponse(BaseModel): attempts: Annotated[int, Field(ge=0)] enqueued_at_micros: int @@ -5783,22 +5261,50 @@ class PropertyInput(BaseModel): ] -class RdfExportPreviewResponse(BaseModel): +class PublishedReadSnapshotView(BaseModel): """ - JSON envelope returned by `GET /v1/graph/export/rdf?truncate=true`. + Bounded introspection view of an immutable published generation. It exposes + snapshot lineage and freshness without leaking object-store keys. """ - data: Annotated[ - str, + conformance: PublishedReadConformanceView | None = None + epoch: Annotated[int, Field(ge=0)] + families: list[PublishedReadFamilyView] + format_version: Annotated[int, Field(ge=0)] + generation: Annotated[int | None, Field(ge=0)] = None + graph: GraphKey + predecessor_generation: Annotated[int | None, Field(ge=0)] = None + projection_version: Annotated[int | None, Field(ge=0)] = None + served_at_seq: Annotated[int, Field(ge=0)] + source_head_generation: Annotated[ + int, Field( - description='RDF serialization (Turtle, N-Triples, TriG, or N-Quads) encoded as a JSON\nstring so the preview metadata stays in one typed response.' + description='Graph-head generation whose metadata/configuration this root reflects.\nThis can trail the current head even when `served_at_seq` is unchanged.', + ge=0, ), ] - format: str - returned_triples: Annotated[int, Field(ge=0)] - snapshot: SnapshotView - total_triples: Annotated[int, Field(ge=0)] - truncated: bool + summary_available: bool + + +class PublishedReadStatusResponse(BaseModel): + """ + One coherent operational view of the graph head and the immutable read root + pinned while resolving it. Lag values are derived from this `head_seq`, not + from a separately-polled status response. + """ + + conformance_lag_commits: Annotated[int | None, Field(ge=0)] = None + generation_lag: Annotated[ + int, + Field( + description='Head-generation distance, including same-sequence ontology, shapes, or\nindex-configuration changes that commit-sequence lag cannot expose.', + ge=0, + ), + ] + head_generation: Annotated[int, Field(ge=0)] + head_seq: Annotated[int, Field(ge=0)] + query_lag_commits: Annotated[int, Field(ge=0)] + snapshot: PublishedReadSnapshotView class RelationSearchResult(BaseModel): @@ -5850,129 +5356,26 @@ class ResolvedTerm(BaseModel): type_signature: VocabularyTypeSignature | None = None -class RetrievalPremiseRequest(BaseModel): - """ - Stage G — turn calibrated retrieval candidates into derived edges. Every - candidate scored `P >= threshold` becomes a derived edge `(anchor, relation, - matched)` with `confidence = P` and a single `Retrieval` provenance leaf - (never `Asserted` — FAL-PROV-NOT-LAUNDERED). Candidates come from any - retrieval channel; the server re-verifies each against the served snapshot. - """ - - anchor: Annotated[ - EntitySelector, Field(description='Subject of every derived edge.') - ] - calibration: PlattCalibration | None = None - candidates: Annotated[ - list[ScoredCandidateInput] | None, - Field( - description='Explicit candidates (client ran retrieval). Exactly one of `candidates` or\n`query` must be supplied.' - ), - ] = None - materialize: Annotated[ - bool | None, - Field( - description='Persist the derived premises as an immutable `derived/v1` object (separate\nfrom the asserted graph) and return its key in `materialized_key`. Default\nfalse — a plain preview that writes nothing.' - ), - ] = None - max_premises: Annotated[ - int, Field(description='Fail-closed ceiling on emitted premises.', ge=0) - ] - model_id: Annotated[ - str, - Field( - description='The embedding model the scores came from (names the `Retrieval` leaf).' - ), - ] - query: Annotated[ - str | None, - Field( - description='Query-driven mode: when set, the server runs BM25 entity retrieval for this\ntext against the served snapshot and uses the matches (with their raw BM25\nscores) as candidates — so a caller can hand a query instead of pre-scoring.' - ), - ] = None - query_top_k: Annotated[ - int | None, - Field( - description='Candidate-pool size for `query` mode (defaults to 50).', ge=0 - ), - ] = None - relation: Annotated[ - str, - Field( - description='Predicate of every derived edge; must resolve in the ontology.' - ), - ] - target_kind: Annotated[ - AnnTargetKind, Field(description='The retrieval target the scores ranked.') - ] - threshold: Annotated[ - float, - Field( - description='Minimum calibrated `P` for a candidate to become a premise (in `[0,1]`).' - ), - ] - - -class RetrievalPremiseResponse(BaseModel): - """ - The derived edges plus the bound / candidate-not-final instrumentation. - """ - - calibration_run: Annotated[ - int | None, - Field( - description='The promoted `calibration` run whose scaler priced these premises;\nabsent when the request carried an inline `calibration`.', - ge=0, - ), - ] = None - considered: Annotated[ - int, - Field( - description='Candidates examined (`max_premises` may stop the scan early).', - ge=0, - ), - ] - derived: list[DerivedEdgeView] - dropped_below_threshold: Annotated[ - int, - Field( - description='Candidates whose calibrated `P` was below `threshold`.', ge=0 - ), - ] - dropped_not_visible: Annotated[ - int, - Field( - description='Candidates dropped because they were not visible in the served snapshot.', - ge=0, - ), - ] - emitted: Annotated[ - int, Field(description='Premises emitted (`<= max_premises`).', ge=0) - ] - materialized_key: Annotated[ - str | None, - Field( - description='Object key of the persisted `derived/v1` run when `materialize` was set;\n`None` for a plain preview.' - ), - ] = None - snapshot: SnapshotView - truncated: Annotated[ - bool, - Field(description='True if the `max_premises` bound stopped emission early.'), - ] - - class SchemaAuditReport(BaseModel): conforms: bool messages: list[str] | None = None + ontology_version: Annotated[ + int | None, + Field(description='Ontology identity the durable report validated.', ge=0), + ] = None result_count: Annotated[int, Field(ge=0)] results: list[SchemaAuditResult] | None = None + shapes_version: Annotated[ + int | None, + Field(description='Shapes identity the durable report validated.', ge=0), + ] = None truncated: Annotated[ bool | None, Field( description='True when `result_count` is exact but `results` contains only the\ncaller-requested leading window. Whole-graph audits can produce one row\nper offending focus node, so HTTP responses are bounded by default.' ), ] = None + validated_at_seq: CommitSeq | None = None class SchemaBundleView(BaseModel): @@ -6001,41 +5404,16 @@ class SchemaBundleView(BaseModel): shapes_version: Annotated[int | None, Field(ge=0)] = None -class SchemaPreviewRequest(BaseModel): - base_ontology_version: Annotated[int | None, Field(ge=0)] = None - base_shapes_version: Annotated[int | None, Field(ge=0)] = None - desired_mode: SchemaEnforceMode | None = None - ontology: SchemaSource | None = None - shapes: SchemaSource | None = None - - -class SchemaPreviewResponse(BaseModel): - audit: SchemaAuditReport - base_ontology_version: Annotated[int, Field(ge=0)] - base_shapes_version: Annotated[int | None, Field(ge=0)] = None - can_publish: bool - desired_mode: SchemaEnforceMode - diff: list[SchemaDiffEntry] - graph: GraphKey - messages: list[str] - preview_digest: str - proposed_ontology_version: Annotated[int, Field(ge=0)] - proposed_shapes_version: Annotated[int | None, Field(ge=0)] = None - publish_mode_allowed: list[SchemaEnforceMode] - verdict: SchemaCompatibilityVerdict - - class SchemaPublishRequest(BaseModel): confirm_restrictive: bool | None = None desired_mode: SchemaEnforceMode | None = None ontology: SchemaSource | None = None - preview_digest: str shapes: SchemaSource | None = None class SchemaPublishResponse(BaseModel): activated: bool - audit: SchemaAuditReport + audit: SchemaAuditReport | None = None enforce_mode: SchemaEnforceMode graph: GraphKey messages: list[str] @@ -6268,55 +5646,6 @@ class SearchFilterExpr15(BaseModel): values: list[bool | int | float | str | None] -class SearchIndexRunRequest(BaseModel): - build_adjacency: Annotated[ - bool | None, - Field( - description='Build the ranged adjacency run for traversal. Off by default.' - ), - ] = None - build_embeddings: bool | None = None - build_full_text: bool | None = None - build_permutation: Annotated[ - bool | None, - Field( - description='Build the object-storage-native permutation view (PSO) for native SHACL\ntarget/path evaluation and analytic graph queries. Off by default.' - ), - ] = None - dim: Annotated[int | None, Field(ge=0)] = None - include_clusters: bool - include_raw_rerank: Annotated[ - bool | None, - Field( - description='Append a raw-f32 region to the embedding run so vector search can opt\ninto exact rerank. Off by default (compact 4-bit-only runs).' - ), - ] = None - include_terms: bool - max_clusters: Annotated[int | None, Field(ge=0)] = None - provider: ( - EmbeddingProviderConfig1 - | EmbeddingProviderConfig2 - | EmbeddingProviderConfig3 - | None - ) = None - targets: list[AnnTargetKind] - tokenizer: FullTextTokenizerConfig | None = None - - -class SearchIndexRunResponse(BaseModel): - adjacency: SearchIndexFamilyRun | None = None - embeddings: SearchIndexFamilyRun | None = None - full_text: SearchIndexFamilyRun | None = None - index_lineage: Annotated[ - IndexLineage, - Field( - description='One coherent observation of every serving index family after this run.\nUnlike the per-family build outcomes, this also includes families the\nrequest did not rebuild and is therefore the convergence contract.' - ), - ] - permutation: SearchIndexFamilyRun | None = None - snapshot: SnapshotView - - class SearchSuggestion(BaseModel): document_frequency: Annotated[ int | None, @@ -6699,14 +6028,9 @@ class AnalyticQueryRequest(BaseModel): object-storage permutation view. """ - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin: evaluate the query as of this `commit_seq`, hiding any event\ncommitted later. Errors if it exceeds the head. Forces the snapshot reduce\npath — the head-fresh permutation view and the count fast paths are\ndeclined, since they cannot reconstruct an earlier snapshot.', - ge=0, - ), - ] = None - as_of_valid_time: str | None = None + model_config = ConfigDict( + extra='forbid', + ) combinators: Annotated[ list[ AnalyticCombinator1 @@ -6735,96 +6059,21 @@ class AnalyticQueryRequest(BaseModel): int | None, Field( description="Fail-closed ceiling on object reads (GETs) the query's scans may issue —\nthe per-request object-storage cost cap. Clamped to the server's\n`MAX_ANALYTIC_OBJECT_READS`; when hit, the scan stops and the response's\n`truncated_by_read_budget` flag is set.", - ge=0, - ), - ] = None - max_solutions: Annotated[ - int | None, - Field( - description="Fail-closed ceiling on the intermediate join solution set. Clamped to the\nserver's `MAX_ANALYTIC_SOLUTIONS`; when the join hits it the result is\npartial and the response's `truncated` flag is set. Distinct from `limit`,\nwhich is a caller-requested cap on the final, complete result.", - ge=0, - ), - ] = None - min_indexed_seq: CommitSeq | None = None - offset: Annotated[ - int | None, Field(description='Skip this many bindings before `limit`.', ge=0) - ] = None - patterns: list[AnalyticTriplePattern] - - -class AskFeedbackRequest(BaseModel): - ask_id: Annotated[str, Field(description='The `ask_id` the ask response carried.')] - corrected_plan: AskStructuredPlanV2 | None = None - note: Annotated[ - str | None, Field(description='Optional free-text note (bounded server-side).') - ] = None - verdict: AskFeedbackVerdict - - -class AskGrounding(BaseModel): - candidates: Annotated[ - list[ResolvedTerm], - Field( - description="Real vocabulary the question snapped to (classes/relations/properties/\nterms) — a subset of the graph's vocabulary by construction." - ), - ] - constrained: Annotated[ - bool, - Field( - description='True when identifier slots were hard-constrained during decode. Always\nfalse in `grounding_only` (no decode); true under the resident planner.' - ), - ] - signature_forced: Annotated[ - bool | None, - Field( - description='True when the grounding forced a single relation via a type signature\n(WS10). Always false in `grounding_only` v1; set by the resident planner.' - ), - ] = None - - -class AskQuery(BaseModel): - plan_failure: AskPlanFailure | None = None - query: Annotated[ - str, Field(description='The retrieval query text that was executed.') - ] - structured: AskStructuredQuery | None = None - structured_v2: AskStructuredPlanV2 | None = None - top_k: Annotated[int, Field(ge=0)] - - -class AskResponse(BaseModel): - answer: Annotated[ - str | None, - Field( - description='A synthesized answer when a model produced one; in `grounding_only` this\nis a templated evidence summary (the retrieved matches), not model prose.' - ), - ] = None - ask_id: Annotated[ - str | None, - Field( - description="Server-stamped id for this ask. Reference it in\n`POST /v1/ask/feedback` to attach a verdict; when signal capture is on\nit is also the `request_id` joining the emitted `ask_trace` signal to\nits `ask_feedback` — the planner fine-tune's training join key." + ge=0, ), ] = None - citations: Annotated[ - list[AskCitation], - Field(description='Evidence: the graph items the answer rests on.'), - ] - confidence: Annotated[ - float, Field(description='Confidence in [0, 1], from the top retrieved score.') - ] - explain: Annotated[ - AskExplain, + max_solutions: Annotated[ + int | None, Field( - description='Instrumentation for the one call: per-stage latency, how much the DB\nnarrowed, and which embedding model grounded the question. Makes the\n"DB narrows, cheap model decodes" pipeline observable per request.' + description="Fail-closed ceiling on the intermediate join solution set. Clamped to the\nserver's `MAX_ANALYTIC_SOLUTIONS`; when the join hits it the result is\npartial and the response's `truncated` flag is set. Distinct from `limit`,\nwhich is a caller-requested cap on the final, complete result.", + ge=0, ), - ] - grounding: Annotated[ - AskGrounding, - Field(description='How the question was mapped onto real vocabulary.'), - ] - mode: Annotated[AskMode, Field(description='Which pipeline produced this answer.')] - query: AskQuery | None = None - snapshot: SnapshotView + ] = None + min_indexed_seq: CommitSeq | None = None + offset: Annotated[ + int | None, Field(description='Skip this many bindings before `limit`.', ge=0) + ] = None + patterns: list[AnalyticTriplePattern] class BranchParentView(BaseModel): @@ -6865,47 +6114,6 @@ class CurrentStateResponse(BaseModel): state: list[StateEntry] -class EmbeddingIndexBuildRequest(BaseModel): - dim: Annotated[int | None, Field(ge=0)] = None - include_clusters: bool - include_raw_rerank: Annotated[ - bool | None, - Field( - description='Append a raw-f32 region per cluster so persisted vector search can opt\ninto exact rerank (`rerank` on the search request). Larger objects at\nrest; default off keeps runs compact and 4-bit-only.' - ), - ] = None - max_clusters: Annotated[int | None, Field(ge=0)] = None - provider: ( - EmbeddingProviderConfig1 - | EmbeddingProviderConfig2 - | EmbeddingProviderConfig3 - | None - ) = None - quantizer: Annotated[ - str | None, - Field( - description='Quantizer codec for the persisted cluster blocks. Absent / `None` uses\nthe default `tq-hadamard` (4-bit). Set `exrabitq` (with `quantizer_bits`,\n2..=8) for the higher-bit Extended RaBitQ codec that can reach\nrerank-grade recall without the raw-f32 region (P30/R9). The scheme is\nself-describing in the persisted index meta, so reads dispatch\nautomatically; this only changes how new runs are built.' - ), - ] = None - quantizer_bits: Annotated[ - int | None, - Field( - description='Bits per dimension for the `exrabitq` scheme (2..=8). Ignored by\n`tq-hadamard` (fixed 4-bit); defaults to 4 when `quantizer` is set\nwithout bits.', - ge=0, - ), - ] = None - targets: list[AnnTargetKind] - - -class EmbeddingIndexBuildSpaceView(BaseModel): - cluster_count: Annotated[int, Field(ge=0)] - clusters: list[EmbeddingIndexClusterView] - entry_count: Annotated[int, Field(ge=0)] - object_etag: str - object_key: str - space: EmbeddingSpaceKey - - class EmbeddingIndexInspectRequest(BaseModel): dim: Annotated[int | None, Field(ge=0)] = None include_clusters: bool @@ -6916,7 +6124,6 @@ class EmbeddingIndexInspectRequest(BaseModel): | EmbeddingProviderConfig3 | None ) = None - source: EmbeddingIndexSource | None = None targets: list[AnnTargetKind] @@ -6947,10 +6154,10 @@ class EntityDetailResponse(BaseModel): class EntityNeighborhoodResponse(BaseModel): """ - Result of an entity point lookup: the entity plus its current out/in - neighborhood. Served from the ranged adjacency run's per-entity slices when - one exists (cost is the entity's degree, not the whole graph), otherwise - from the snapshot overlay. + Result of an entity point lookup: the entity plus its out/in neighborhood. + Public reads use adjacency for the published watermark and the same + generation's Base family for historical pins; both paths cost the entity's + degree rather than the whole graph. """ entity: EntityView @@ -6959,7 +6166,7 @@ class EntityNeighborhoodResponse(BaseModel): served_from_ranged: Annotated[ bool, Field( - description='True when served from the persisted ranged adjacency run (the\npoint-lookup fast path); false when computed from the snapshot overlay.' + description="True when served directly from the persisted adjacency family. False\nwhen an exact historical pin was reduced from the same published\ngeneration's Base family." ), ] snapshot: SnapshotView @@ -7193,14 +6400,19 @@ class GraphMetadataResponse(BaseModel): index_caught_up: Annotated[ bool | None, Field( - description='One-shot "has the persisted index caught up to head?" signal, so a\nbulk-import caller does not hand-assemble the three-field predicate.\n`Some(true)` iff both the BM25 and ANN persisted runs are current to the\nhead commit (no un-indexed tail); `Some(false)` when a build is still\npending or absent; `None` when indexes were not inspected\n(`include_indexes=false`). Note (Strong consistency): committed data is\nqueryable via the per-query overlay *before* this turns true — this marks\nthe persisted fast path being current, not queryability.' + description='One-shot "has the published generation caught up to head?" signal, so a\nbulk-import caller does not hand-assemble the three-field predicate.\n`Some(true)` iff both the BM25 and ANN persisted runs are current to the\nhead commit; `Some(false)` when publication is still\npending or absent; `None` when indexes were not inspected\n(`include_indexes=false`).' ), ] = None index_lineage: IndexLineage | None = None - object_bytes: Annotated[int, Field(ge=0)] - object_count: Annotated[int, Field(ge=0)] ontology_version: Annotated[int, Field(ge=0)] parent: BranchParentView | None = None + published_lag_commits: Annotated[ + int, + Field( + description='Commit distance from the graph head to the pinned published generation.', + ge=0, + ), + ] segment_bytes: Annotated[int | None, Field(ge=0)] = None segment_count: Annotated[ int | None, @@ -7210,20 +6422,6 @@ class GraphMetadataResponse(BaseModel): ), ] = None snapshot: SnapshotView - temporal_coverage: Annotated[ - TemporalCoverage | None, - Field( - description='Temporal coverage of this snapshot — what kinds of as-of query the data\ncan actually answer. Lets a caller tell *before* querying whether\npoint-in-time / daily views are possible, instead of discovering that\nevery as-of returns the same picture.' - ), - ] = None - temporal_coverage_computed: Annotated[ - bool | None, - Field( - description='Whether `temporal_coverage` was computed from the full snapshot. The\nbounded HTTP metadata path is head-only by default; callers that need\nexact event-time coverage opt in explicitly.' - ), - ] = None - unindexed_tail_commits: Annotated[int, Field(ge=0)] - visibility_manifest: IndexVisibilityManifest | None = None wal_tail_bytes: Annotated[int, Field(ge=0)] wal_tail_commits: Annotated[int, Field(ge=0)] @@ -7235,19 +6433,6 @@ class HybridMultiSearchResponse(BaseModel): snapshot: SnapshotView -class IndexGcJobStatusResponse(BaseModel): - attempts: Annotated[int, Field(ge=0)] - enqueued_at_micros: int - graph: GraphKey - job_id: str - progress: IndexGcJobProgress | None = None - request: IndexGcRequest - result: IndexGcResponse | None = None - status: str - terminal_error: str | None = None - updated_at_micros: int - - class InferenceRule(BaseModel): """ A single inference rule (SHACL-AF `sh:TripleRule` shape): a BGP `body` (the @@ -7289,46 +6474,6 @@ class InferenceRule(BaseModel): ] = None -class InferenceRunRequest(BaseModel): - """ - Run a set of inference rules to a bounded fixpoint and return the derived - edges as a **preview**. Derived facts are never written: the write gate - refuses `origin=Derived`, so this surfaces "what follows" without mutating - the graph. Stratified persistence (`derived/v1`) is a separate path. - """ - - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin: run inference over the graph as of this `commit_seq`, hiding\nlater commits. Errors if it exceeds the head.', - ge=0, - ), - ] = None - as_of_valid_time: str | None = None - max_derived: Annotated[ - int | None, - Field( - description='Fail-closed ceiling on total derived edges (clamped server-side).', - ge=0, - ), - ] = None - max_rounds: Annotated[ - int | None, - Field( - description='Fail-closed ceiling on fixpoint rounds (clamped server-side).', - ge=0, - ), - ] = None - max_solutions: Annotated[ - int | None, - Field( - description="Per-rule ceiling on the `body` join's solution set (clamped server-side).", - ge=0, - ), - ] = None - rules: list[InferenceRule] - - class ModelRegistryResponse(BaseModel): """ `GET /v1/models/registry` — the runs of one kind, newest first. @@ -7596,7 +6741,9 @@ class ResolveTermRequest(BaseModel): by construction — the resolver never fabricates a term. """ - as_of_commit_seq: Annotated[int | None, Field(ge=0)] = None + model_config = ConfigDict( + extra='forbid', + ) candidates: Annotated[ list[str] | None, Field( @@ -7609,7 +6756,6 @@ class ResolveTermRequest(BaseModel): description='Which vocabulary sources to consider; empty means all. Ignored when\n`candidates` is supplied (the candidate list is the search space).' ), ] = None - snapshot_token: str | None = None text: Annotated[ str, Field(description='The free text to snap to real vocabulary (1..=256 chars).'), @@ -7633,27 +6779,6 @@ class ResolveTermResponse(BaseModel): snapshot_token: str -class RuleSet(BaseModel): - """ - A versioned, immutable set of inference rules stored with a graph branch - (Track B). Pinned from `GraphHead.rules_ref`; used by `infer` and SHACL - `include_derived` when the request carries no inline rules. - """ - - rules: list[InferenceRule] - version: Annotated[ - int, Field(description='Monotonically increasing; bumped on each define.', ge=0) - ] - - -class RuleSetDefineRequest(BaseModel): - """ - Define (replace) the stored rule set for a graph branch. - """ - - rules: list[InferenceRule] - - class SearchFeedbackExportResponse(BaseModel): counts: SearchFeedbackExportCounts feedback_graph: GraphKey @@ -7667,27 +6792,6 @@ class SearchFeedbackExportResponse(BaseModel): rows: list[SearchFeedbackExportRow] -class SearchIndexJobStatusResponse(BaseModel): - """ - Durable background full-index job status with per-family terminal result. - """ - - attempts: Annotated[int, Field(ge=0)] - enqueued_at_micros: int - graph: GraphKey - job_id: str - result: SearchIndexRunResponse | None = None - stage: str | None = None - status: Annotated[ - str, - Field( - description='`pending` | `running` | `succeeded` | `failed` | `cancelled`.' - ), - ] - terminal_error: str | None = None - updated_at_micros: int - - class SearchSessionCommitResponse(BaseModel): """ Commit result: the ordinary search response plus a `speculation` block @@ -7736,13 +6840,9 @@ class SearchSuggestRequest(BaseModel): completions are strings that provably exist in the graph at this snapshot. """ - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Transaction-time vocabulary pin. Mutually exclusive with\n`snapshot_token`.', - ge=0, - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) context: SuggestContext | None = None field: Annotated[ str | None, @@ -7762,12 +6862,6 @@ class SearchSuggestRequest(BaseModel): ] = None prefix: str ranker: SuggestRankerWeights | None = None - snapshot_token: Annotated[ - str | None, - Field( - description='Opaque graph snapshot identity previously returned by LBB. Mutually\nexclusive with `as_of_commit_seq`.' - ), - ] = None vocabulary_filter: VocabularyFilter | None = None @@ -7901,7 +6995,6 @@ class CommitResponse(BaseModel): edge_event_ids: list[str] entity_ids: list[str] idempotent_replay: bool - indexed: bool no_op: bool | None = None observation_ids: list[str] schema_validation: SchemaAuditReport | None = None @@ -7922,19 +7015,10 @@ class CommitResponse(BaseModel): ] = None -class EmbeddingIndexBuildResponse(BaseModel): - manifest_etag: str - manifest_key: str - provider: EmbeddingProviderSpec - snapshot: SnapshotView - spaces: list[EmbeddingIndexBuildSpaceView] - - class EmbeddingIndexInspectResponse(BaseModel): manifest_key: str | None = None provider: EmbeddingProviderSpec snapshot: SnapshotView - source: EmbeddingIndexSource spaces: list[EmbeddingIndexSpaceView] @@ -7981,84 +7065,10 @@ class ShaclQueryResponse(BaseModel): snapshot: SnapshotView -class AskRequest(BaseModel): - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin (transaction-time ceiling): retrieval and citations\nreproduce the graph as of this commit sequence; the response\n`snapshot.as_of_commit_seq` echoes the pin. Omitted means head.', - ge=0, - ), - ] = None - as_of_valid_time: Annotated[ - str | None, - Field( - description='Valid-time cursor (RFC 3339): retrieval reflects facts true at this\ninstant. Omitted means the latest valid time.' - ), - ] = None - execute: Annotated[ - bool | None, - Field( - description='Run retrieval and return citations (default true). When false, only the\ngrounding is computed — the caller drives its own retrieval/model.' - ), - ] = None - fields: Annotated[ - list[str] | None, - Field( - description='Entity attributes retained as evidence on the internal execution trace.' - ), - ] = None - filters: ( - SearchFilterExpr1 - | SearchFilterExpr2 - | SearchFilterExpr3 - | SearchFilterExpr4 - | SearchFilterExpr5 - | SearchFilterExpr6 - | SearchFilterExpr7 - | SearchFilterExpr8 - | SearchFilterExpr9 - | SearchFilterExpr10 - | SearchFilterExpr11 - | SearchFilterExpr12 - | SearchFilterExpr13 - | SearchFilterExpr14 - | SearchFilterExpr15 - | SearchFilterExpr16 - | SearchFilterExpr17 - | SearchFilterExpr18 - | SearchFilterExpr19 - | SearchFilterExpr20 - | SearchFilterExpr21 - | SearchFilterExpr22 - | None - ) = None - question: Annotated[str, Field(description='The natural-language question.')] - snapshot_token: Annotated[ - str | None, - Field( - description='Opaque alternative to `as_of_commit_seq`. Exactly one pin spelling may\nbe supplied; grounding, validation, execution, trace, and citations all\nuse the resolved commit.' - ), - ] = None - top_k: Annotated[ - int | None, - Field(description='Max citations to return (default 8, clamped to 25).', ge=0), - ] = None - - class EmbeddingSearchRequest(BaseModel): - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. The ANN\nrun is selected as the newest run at or below the pin and the pin bounds\nthe forward overlay; candidate generation is never the correctness layer.\nOmitted means the current head.', - ge=0, - ), - ] = None - as_of_valid_time: Annotated[ - str | None, - Field( - description='Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.' - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) consistency: SearchConsistency | None = None dim: Annotated[int | None, Field(ge=0)] = None explain: bool @@ -8117,7 +7127,6 @@ class EmbeddingSearchRequest(BaseModel): ge=0, ), ] = None - source: EmbeddingIndexSource | None = None targets: list[AnnTargetKind] top_k: Annotated[int, Field(ge=0)] @@ -8166,19 +7175,9 @@ class EntityFilterRequest(BaseModel): class FullTextSearchRequest(BaseModel): - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. The BM25\nrun is selected as the newest run at or below the pin and the pin bounds\nthe forward overlay; candidate generation is never the correctness layer.\nOmitted means the current head.', - ge=0, - ), - ] = None - as_of_valid_time: Annotated[ - str | None, - Field( - description='Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.' - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) consistency: SearchConsistency | None = None explain: bool facets: list[FacetRequest] | None = None @@ -8228,7 +7227,6 @@ class FullTextSearchRequest(BaseModel): ), ] = None query: str - source: FullTextIndexSource | None = None targets: list[AnnTargetKind] tokenizer: FullTextTokenizerConfig | None = None top_k: Annotated[int, Field(ge=0)] @@ -8240,7 +7238,9 @@ class GovernedConflictAggregationRequest(BaseModel): required filter and is evaluated before any grouping or value collection. """ - as_of_commit_seq: Annotated[int | None, Field(ge=0)] = None + model_config = ConfigDict( + extra='forbid', + ) entity_type: str key_fields: list[str] limit: Annotated[int | None, Field(ge=0)] = None @@ -8328,7 +7328,6 @@ class HybridSubquery(BaseModel): class SearchEngineOptions(BaseModel): bm25: bool | None = None - bm25_source: FullTextIndexSource | None = None consistency: SearchConsistency | None = None dim: Annotated[int | None, Field(ge=0)] = None facets: list[FacetRequest] | None = None @@ -8390,7 +7389,6 @@ class SearchEngineOptions(BaseModel): ] = None tokenizer: FullTextTokenizerConfig | None = None vector: bool | None = None - vector_source: EmbeddingIndexSource | None = None weights: SearchSignalWeights | None = None @@ -8480,35 +7478,23 @@ class SearchFilterExpr22(BaseModel): class SearchSessionCommitRequest(BaseModel): """ - `POST /v1/search/session/commit` — execute the search against the session's - pinned snapshot. The warmed cache makes it read warm; the results are exactly - what the same request would return without any prior `prefix` frames. + `POST /v1/search/session/commit` — execute the search against the current + published snapshot. The warmed cache makes it read warm; the results are + exactly what the same request would return without any prior `prefix` + frames. """ - pin: Annotated[ - bool | None, - Field( - description="Enforce the session's snapshot pin: the search runs with\n`as_of_commit_seq` set to the commit the session opened at, so a write\nthat landed mid-session cannot change what this commit returns\n(reproducible runs / retry determinism). An explicit conflicting\n`request.as_of_commit_seq` is an `invalid_input`. Default false — the\ncommit reads the current head, exactly like `POST /v1/graph/search`." - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) request: SemanticGraphSearchRequest session_id: str class SemanticGraphSearchRequest(BaseModel): - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin (transaction-time ceiling): results hide every event\ncommitted after this sequence, reproducing that past snapshot. BM25/ANN\nindexes still generate candidates from the head; the pin is enforced\nwhere results are verified against the snapshot, never by candidate\ngeneration. Omitted means the current head.', - ge=0, - ), - ] = None - as_of_valid_time: Annotated[ - str | None, - Field( - description='Valid-time cursor (RFC 3339): results reflect facts true at this\ninstant. Omitted means the latest valid time.' - ), - ] = None + model_config = ConfigDict( + extra='forbid', + ) explain: bool | None = None fields: Annotated[ list[str] | None, @@ -8536,14 +7522,9 @@ class SemanticGraphSearchRequest(BaseModel): class SemanticTraverseRequest(BaseModel): - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin (transaction-time ceiling): seeds and expansion reproduce\nthe graph as of this commit sequence. Any as-of (valid time or pin)\nroutes traversal through the snapshot scan — the persisted-vector\nranged fast path serves head reads only. Omitted means head.', - ge=0, - ), - ] = None - as_of_valid_time: str | None = None + model_config = ConfigDict( + extra='forbid', + ) direction: ExpansionDirection explain: bool fields: Annotated[ @@ -8916,10 +7897,9 @@ class ShadowEvalRequest(BaseModel): on this evidence — the endpoint never promotes. """ - as_of_commit_seq: Annotated[ - int | None, - Field(description='Pin both arms to one snapshot for reproducibility.', ge=0), - ] = None + model_config = ConfigDict( + extra='forbid', + ) challenger: SearchEngineOptions champion: SearchEngineOptions | None = None queries: list[ShadowQuery] @@ -8977,20 +7957,15 @@ class SparqlSelectRequest(BaseModel): aggregation arrive in later milestones. """ + model_config = ConfigDict( + extra='forbid', + ) aggregates: Annotated[ list[SparqlAggregate] | None, Field( description='Aggregate projections (COUNT/SUM/AVG/MIN/MAX … AS …). Presence switches\nthe query into grouped/aggregated mode.' ), ] = None - as_of_commit_seq: Annotated[ - int | None, - Field( - description='Snapshot pin: evaluate as of this `commit_seq`, hiding later commits.\nErrors if it exceeds the head; forces the snapshot reduce path.', - ge=0, - ), - ] = None - as_of_valid_time: str | None = None ask: Annotated[ bool | None, Field( @@ -9072,7 +8047,7 @@ class SparqlSelectRequest(BaseModel): reason: Annotated[ bool | None, Field( - description="Reason over the graph's stored inference rules: fold the rule-derived\nfacts into the snapshot the query sees, so a pattern matches asserted **and**\nderived edges in one shot. Off by default (asserted-only). Forces the\noverlay reduce path (the prebuilt index holds no derived facts), and is a\nno-op when the branch has no stored rules." + description="Reason over the graph's stored inference rules so a pattern matches\nasserted **and** derived edges in one shot. Off by default\n(asserted-only). Public serving requires a compatible reasoned\nprojection in the pinned published generation and fails closed when it\nis absent; it never forces an overlay reduce." ), ] = None select: Annotated[ @@ -9087,7 +8062,7 @@ class TraverseRequest(BaseModel): as_of_commit_seq: Annotated[ int | None, Field( - description='Snapshot pin: reproduce the graph state as of this `commit_seq`, hiding\nany event committed later. Errors if it exceeds the current head, and\nforces the snapshot scan (the ranged adjacency fast path declines a\npinned read). Omit for the latest snapshot.', + description='Snapshot pin: reproduce the graph state as of this `commit_seq`, hiding\nany event committed later. Public serving reduces the bounded edge\ndomains from the Base family in the one pinned published generation;\nit never discovers or assembles another snapshot. Historical entity\nfilters/field projection fail explicitly because Base does not carry a\npoint-indexed entity-mutation history. Omit for the latest snapshot.', ge=0, ), ] = None @@ -9127,14 +8102,14 @@ class TraverseRequest(BaseModel): max_block_bytes: Annotated[ int | None, Field( - description='Decoded adjacency-block working-set byte budget for the ranged path.\nDefaults to the server/store budget. A request may lower the budget,\nbut not raise it. Ignored on the snapshot path.', + description='Decoded adjacency-block working-set byte budget for the ranged path.\nDefaults to the server/store budget. A request may lower the budget,\nbut not raise it. Ignored on the bounded Base-family reducer path.', ge=0, ), ] = None max_block_reads: Annotated[ int | None, Field( - description='Object-read budget for the ranged adjacency path; defaults to a value\nderived from `max_frontier_entities`. Ignored on the snapshot path.', + description='Object-read budget for the ranged adjacency path; defaults to a value\nderived from `max_frontier_entities`. Ignored on the bounded Base-family\nreducer path.', ge=0, ), ] = None @@ -9146,7 +8121,6 @@ class TraverseRequest(BaseModel): start: EntitySelector -AskRequest.model_rebuild() EmbeddingSearchRequest.model_rebuild() EntityFilterRequest.model_rebuild() FullTextSearchRequest.model_rebuild() diff --git a/tests/test_client.py b/tests/test_client.py index 1e5f06d..02f9fea 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -10,30 +10,23 @@ import httpx from pydantic import ValidationError -from lbb import AsyncLbbClient, LbbClient, LbbError, ListPage, __version__ +from lbb import AsyncLbbClient, LbbClient, LbbError, __version__ from lbb.models import ( AddEntityTypeOp, AdditiveOntologyEvolveRequest, - AskResponse, CreateGraphResponse, - EntityExplorerRow, - EntityFilterResponse, EntityTypeSampleResponse, GovernedConflictAggregationResponse, GraphBranchDeleteResponse, GraphDeleteResponse, - GraphEdgeRow, GraphForkResponse, GraphReloadResponse, GraphSummaryResponse, - IndexGcJobStatusResponse, OntologyDraft, OntologyEvolveRequest, - RdfExportPreviewResponse, SchemaBundleView, SearchFeedbackExportResponse, SearchFeedbackSummaryResponse, - SearchIndexJobStatusResponse, SparqlSelectResponse, TrainModelJobStatusResponse, ) @@ -105,7 +98,6 @@ def edge_list_payload() -> dict[str, Any]: "total_count": 1, } - def schema_view_payload() -> dict[str, Any]: return { "graph": GRAPH, @@ -115,7 +107,6 @@ def schema_view_payload() -> dict[str, Any]: "relations": [], "shape_count": 1, "constraint_shape_count": 1, - "audit_summary": {"conforms": False, "violation_count": 1}, } @@ -189,16 +180,14 @@ def handler(request: httpx.Request) -> httpx.Response: class SyncClientTests(unittest.TestCase): - def test_metadata_keeps_recursive_object_inventory_opt_in(self) -> None: + def test_metadata_exposes_only_bounded_index_detail_option(self) -> None: seen: list[httpx.Request] = [] with LbbClient( "http://h", graph="g", transport=capturing_transport(seen) ) as client: client.metadata() client.metadata( - include_objects=True, include_indexes=False, - include_temporal_coverage=True, ) self.assertEqual(dict(seen[0].url.params), {"graph": "g"}) @@ -206,9 +195,7 @@ def test_metadata_keeps_recursive_object_inventory_opt_in(self) -> None: dict(seen[1].url.params), { "graph": "g", - "include_objects": "true", "include_indexes": "false", - "include_temporal_coverage": "true", }, ) @@ -262,7 +249,7 @@ def test_namespace_facts_create_injects_auth_scope_version_and_idempotency( ) self.assertEqual(dict(request.url.params), {"graph": "main", "branch": "b"}) self.assertEqual(request.headers["authorization"], "Bearer lbb_sk_test") - self.assertEqual(request.headers["lbb-version"], "2026-07-22") + self.assertEqual(request.headers["lbb-version"], "2026-07-23") self.assertEqual(request.headers["idempotency-key"], "ik_py_1") self.assertEqual(json.loads(request.content), {"triplets": []}) @@ -272,7 +259,6 @@ def test_search_namespace_encodes_query_params(self) -> None: client.search.hybrid( "customer identity", top_k=5, - source="persisted", consistency="strong", targets=["concepts", "entities"], ) @@ -280,34 +266,21 @@ def test_search_namespace_encodes_query_params(self) -> None: self.assertEqual(str(seen[0].url).split("?")[0], "http://h/v1/search") self.assertEqual(params["query"], "customer identity") self.assertEqual(params["top_k"], "5") - self.assertEqual(params["source"], "persisted") + self.assertNotIn("source", params) self.assertEqual(params["consistency"], "strong") self.assertEqual(params["targets"], "concepts,entities") def test_search_namespace_is_callable_for_quick_hybrid_search(self) -> None: seen: list[httpx.Request] = [] with LbbClient("http://h", transport=capturing_transport(seen)) as client: - client.search("customer identity", top_k=5, source="persisted") + client.search("customer identity", top_k=5) self.assertEqual(str(seen[0].url).split("?")[0], "http://h/v1/search") self.assertEqual( dict(seen[0].url.params), - {"query": "customer identity", "top_k": "5", "source": "persisted"}, + {"query": "customer identity", "top_k": "5"}, ) - def test_entities_namespace_encodes_list_filters(self) -> None: - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", graph="g", transport=capturing_transport(seen) - ) as client: - client.entities.list(type="SERVICE", limit=10, query="billing") - params = dict(seen[0].url.params) - self.assertEqual(str(seen[0].url).split("?")[0], "http://h/v1/graph/entities") - self.assertEqual(params["graph"], "g") - self.assertEqual(params["type"], "SERVICE") - self.assertEqual(params["limit"], "10") - self.assertEqual(params["q"], "billing") - def test_entities_sample_is_typed_and_uses_bounded_route(self) -> None: seen: list[httpx.Request] = [] payload = { @@ -332,33 +305,6 @@ def test_entities_sample_is_typed_and_uses_bounded_route(self) -> None: ) self.assertEqual(dict(seen[0].url.params)["limit"], "48") - def test_entities_filter_is_typed_and_retry_safe(self) -> None: - seen: list[httpx.Request] = [] - payload = { - "snapshot": SNAPSHOT, - "matched_count": 1, - "entities": entity_list_payload()["data"], - } - body = { - "filter": {"field": "document_id", "op": "eq", "value": "doc-1"}, - "fields": ["title", "acl_principals"], - "limit": 20, - } - with LbbClient( - "http://h", - graph="g", - transport=capturing_transport(seen, {"json": payload}), - ) as client: - result = client.entities.filter(body) - - self.assertIsInstance(result, EntityFilterResponse) - self.assertEqual(result.matched_count, 1) - self.assertEqual(result.snapshot.commit_seq, 7) - self.assertEqual( - str(seen[0].url).split("?")[0], "http://h/v1/graph/entities/filter" - ) - self.assertEqual(json.loads(seen[0].content), body) - def test_ontology_evolve_models_have_stable_discriminated_names(self) -> None: op = AddEntityTypeOp(op="add_entity_type", name="CUSTOMER") request = AdditiveOntologyEvolveRequest(ops=[op]) @@ -409,6 +355,7 @@ def test_a5_read_your_writes_floor_and_default_consistency(self) -> None: {"json": {"commit_seq": 128, "snapshot_token": "t", "op_count": 1}}, {"json": {"snapshot": SNAPSHOT, "vars": [], "solutions": []}}, {"json": summary_payload()}, + {"json": {"conforms": True, "result_count": 0}}, ] with LbbClient( "http://h", @@ -422,6 +369,9 @@ def test_a5_read_your_writes_floor_and_default_consistency(self) -> None: # On the summary (URL) route the floor + default consistency ride the # query string. client.summary(min_indexed_seq=commit_seq) + # Durable conformance uses the same client default, but has no + # read-your-writes floor: strong waits for an exact report. + client.ontology_conformance() self.assertEqual(commit_seq, 128) sparql_body = json.loads(seen[1].content) @@ -432,6 +382,11 @@ def test_a5_read_your_writes_floor_and_default_consistency(self) -> None: summary_params = dict(seen[2].url.params) self.assertEqual(summary_params["min_indexed_seq"], "128") self.assertEqual(summary_params["consistency"], "strong") + conformance_params = dict(seen[3].url.params) + self.assertEqual( + conformance_params, + {"graph": "g", "consistency": "strong"}, + ) def test_a5_per_call_consistency_wins_over_default(self) -> None: seen: list[httpx.Request] = [] @@ -542,80 +497,123 @@ def test_search_feedback_summary_returns_constant_size_model(self) -> None: str(seen[0].url).split("?")[0], "http://h/v1/search/feedback/summary" ) - def test_ask_posts_question_and_returns_grounded_answer(self) -> None: + def test_schema_namespace_returns_typed_models(self) -> None: seen: list[httpx.Request] = [] - answer = { - "mode": "resident_planner", - "answer": "user-db stores it.", - "grounding": {"candidates": [], "constrained": True}, - "citations": [], - "confidence": 0.82, - "explain": { - "timings": {"ground_ms": 1.0, "retrieve_ms": 2.0, "total_ms": 3.0}, - "narrowing": {"vocab_candidates": 3, "entities": 9, "assertions": 14}, - "embedding": "bge", - }, - "snapshot": SNAPSHOT, - "ask_id": "ask_1", - } with LbbClient( - "http://h", graph="g", transport=capturing_transport(seen, {"json": answer}) + "http://h", + graph="g", + transport=capturing_transport( + seen, + [ + {"json": schema_view_payload()}, + { + "json": { + "graph": GRAPH, + "ontology_version": 3, + "shapes_version": 2, + "enforce_mode": "warn", + "activated": True, + "audit": {"conforms": True, "result_count": 0}, + "messages": [], + } + }, + ], + ), ) as client: - result = client.ask( + schema = client.schema.view_model() + published = client.schema.publish_model( { - "question": "which databases store customer identity data?", - "top_k": 8, - } + "desired_mode": "warn", + "shapes": { + "source": "@prefix sh: ." + }, + }, + idempotency_key="schema-1", ) - self.assertEqual(result["ask_id"], "ask_1") - self.assertEqual(result["mode"], "resident_planner") - request = seen[0] - self.assertEqual(request.method, "POST") - self.assertEqual(str(request.url).split("?")[0], "http://h/v1/ask") - self.assertEqual(dict(request.url.params)["graph"], "g") - self.assertNotIn("idempotency-key", request.headers) + + self.assertIsInstance(schema, SchemaBundleView) + self.assertTrue(published.activated) self.assertEqual( - json.loads(request.content), - {"question": "which databases store customer identity data?", "top_k": 8}, + [str(request.url).split("?")[0] for request in seen], + [ + "http://h/v1/schema", + "http://h/v1/schema/publish", + ], ) - # The response validates against the generated typed model. - AskResponse.model_validate(result) + self.assertEqual(seen[1].headers["idempotency-key"], "schema-1") - def test_context_namespace_returns_typed_models_without_raw_request(self) -> None: + def test_preserved_grounding_and_model_dataset_routes(self) -> None: seen: list[httpx.Request] = [] - answer = { - "mode": "resident_planner", - "answer": "user-db stores it.", - "grounding": {"candidates": [], "constrained": True}, - "citations": [], - "confidence": 0.82, - "explain": { - "timings": {"ground_ms": 1.0, "retrieve_ms": 2.0, "total_ms": 3.0}, - "narrowing": {"vocab_candidates": 3, "entities": 9, "assertions": 14}, - "embedding": "bge", - }, - "snapshot": SNAPSHOT, - "ask_id": "ask_1", - } with LbbClient( "http://h", graph="g", - max_retries=1, - retry_delay=0, transport=capturing_transport( seen, [ - {"status": 503, "json": {"error": {"message": "retry"}}}, - {"json": answer}, + { + "json": { + "matches": [], + "method": "lexical", + "snapshot": SNAPSHOT, + "snapshot_token": "snapshot-7", + } + }, + { + "json": { + "candidates": [], + "mode": "forced", + "narrowing_source": "signature", + "signature_forced": True, + } + }, + { + "json": { + "name_semantics": { + "embeddable_pct": 1.0, + "hash_like_pct": 0.0, + "sampled": 1, + }, + "narrowing_recall_sampled": { + "n": 1, + "recall_at_10": 1.0, + }, + "recommendation": "narrow", + "signature_sparsity": { + "forced_pct": 1.0, + "le3_pct": 1.0, + "type_pairs": 1, + }, + "snapshot": SNAPSHOT, + } + }, + *[{"json": {}} for _ in range(5)], ], ), ) as client: - result = client.context.ask({"question": "what stores identity data?"}) + client.context.resolve({"text": "writes"}) + client.context.decode( + {"source": {"name": "auth"}, "target": {"name": "db"}} + ) + client.context.groundability(sample=25) + client.shadow_eval({"queries": [], "challenger": {}}) + client.planner_dataset(limit=10, split_seq=7) + client.planner_preference_dataset(limit=11, split_seq=8) + client.suggest_dataset(limit=12, split_seq=9) + client.extractor_dataset(limit=13, split_seq=10) - self.assertIsInstance(result, AskResponse) - self.assertEqual(result.ask_id, "ask_1") - self.assertEqual(len(seen), 2) - self.assertEqual(str(seen[1].url).split("?")[0], "http://h/v1/ask") + self.assertEqual( + [str(request.url).split("?")[0] for request in seen], + [ + "http://h/v1/search/resolve-term", + "http://h/v1/decode", + "http://h/v1/graph/groundability", + "http://h/v1/models/shadow-eval", + "http://h/v1/models/planner-dataset", + "http://h/v1/models/planner-preference-dataset", + "http://h/v1/models/suggest-dataset", + "http://h/v1/models/extractor-dataset", + ], + ) def test_typed_query_namespace_retries_read_only_post(self) -> None: seen: list[httpx.Request] = [] @@ -638,29 +636,6 @@ def test_typed_query_namespace_retries_read_only_post(self) -> None: self.assertEqual(len(seen), 2) self.assertEqual(str(seen[1].url).split("?")[0], "http://h/v1/query/sparql") - def test_entity_iterator_follows_cursors_and_returns_typed_rows(self) -> None: - seen: list[httpx.Request] = [] - first = entity_list_payload() - first["has_more"] = True - first["next_cursor"] = "cursor-2" - first["total_count"] = 2 - second = entity_list_payload() - second["data"][0]["id"] = "e2" - second["data"][0]["name"] = "billing-service" - second["total_count"] = 2 - with LbbClient( - "http://h", - graph="g", - transport=capturing_transport(seen, [{"json": first}, {"json": second}]), - ) as client: - rows = list(client.entities.iter(limit=1)) - - self.assertEqual( - [row.name for row in rows], ["auth-service", "billing-service"] - ) - self.assertTrue(all(isinstance(row, EntityExplorerRow) for row in rows)) - self.assertEqual(dict(seen[1].url.params)["cursor"], "cursor-2") - def test_raw_response_exposes_retry_metadata_and_request_options(self) -> None: seen: list[httpx.Request] = [] events: list[str] = [] @@ -827,29 +802,6 @@ def test_on_retry_hook_surfaces_absorbed_retries(self) -> None: self.assertEqual(events[0].attempt, 1) self.assertGreaterEqual(events[0].delay_seconds, 0.0) - def test_graph_edges_scopes_and_pages_entity_edges(self) -> None: - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", graph="g", transport=capturing_transport(seen) - ) as client: - client.graph_edges( - type="SERVICE", - name="auth", - direction="out", - limit=150, - offset=150, - as_of_commit_seq=42, - ) - request = seen[0] - self.assertEqual(str(request.url).split("?")[0], "http://h/v1/graph/edges") - params = dict(request.url.params) - self.assertEqual(params["type"], "SERVICE") - self.assertEqual(params["name"], "auth") - self.assertEqual(params["direction"], "out") - self.assertEqual(params["limit"], "150") - self.assertEqual(params["offset"], "150") - self.assertEqual(params["as_of_commit_seq"], "42") - def test_commit_dry_run_sets_dry_run_and_no_idempotency_key(self) -> None: seen: list[httpx.Request] = [] with LbbClient( @@ -862,16 +814,6 @@ def test_commit_dry_run_sets_dry_run_and_no_idempotency_key(self) -> None: self.assertEqual(dict(request.url.params)["dry_run"], "true") self.assertNotIn("idempotency-key", request.headers) - def test_entities_list_projects_fields_and_bulk_ids(self) -> None: - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", graph="g", transport=capturing_transport(seen) - ) as client: - client.entities.list(fields=["title", "status"], ids=["abc", "def"]) - params = dict(seen[0].url.params) - self.assertEqual(params["fields"], "title,status") - self.assertEqual(params["ids"], "abc,def") - def test_entities_filter_by_attributes_builds_structured_sparql(self) -> None: seen: list[httpx.Request] = [] with LbbClient( @@ -1028,48 +970,8 @@ def test_durable_trainer_submit_and_poll_are_typed(self) -> None: self.assertEqual(seen[0].headers["idempotency-key"], "fiqa-fusion-1") self.assertEqual(dict(seen[1].url.params)["job_id"], "train_model:abc") - def test_durable_index_submit_and_poll_are_typed(self) -> None: + def test_graph_deletion_is_typed(self) -> None: seen: list[httpx.Request] = [] - payload = { - "job_id": "index_run:abc", - "status": "pending", - "graph": GRAPH, - "attempts": 0, - "enqueued_at_micros": 10, - "updated_at_micros": 10, - } - with LbbClient( - "http://h", transport=capturing_transport(seen, {"json": payload}) - ) as client: - submitted = client.index_submit({}, idempotency_key="fiqa-index-1") - with LbbClient( - "http://h", transport=capturing_transport(seen, {"json": payload}) - ) as client: - polled = client.index_job(submitted.job_id) - self.assertIsInstance(submitted, SearchIndexJobStatusResponse) - self.assertIsInstance(polled, SearchIndexJobStatusResponse) - self.assertEqual(seen[0].headers["idempotency-key"], "fiqa-index-1") - self.assertEqual(dict(seen[1].url.params)["job_id"], "index_run:abc") - - def test_index_cancel_gc_jobs_and_graph_deletion_are_typed(self) -> None: - seen: list[httpx.Request] = [] - index_payload = { - "job_id": "index_run:abc", - "status": "cancelled", - "graph": GRAPH, - "attempts": 0, - "enqueued_at_micros": 10, - "updated_at_micros": 11, - } - gc_payload = { - "job_id": "index_gc:abc", - "status": "pending", - "graph": GRAPH, - "request": {"dry_run": False}, - "attempts": 0, - "enqueued_at_micros": 10, - "updated_at_micros": 10, - } graph_payload = { "ok": True, "graph_id": "main", @@ -1085,14 +987,7 @@ def test_index_cancel_gc_jobs_and_graph_deletion_are_typed(self) -> None: "deleted_objects": 5, "deleted_bytes": 50, } - responses = [ - index_payload, - gc_payload, - gc_payload, - gc_payload, - graph_payload, - branch_payload, - ] + responses = [graph_payload, branch_payload] with LbbClient( "http://h", graph="main", @@ -1101,22 +996,12 @@ def test_index_cancel_gc_jobs_and_graph_deletion_are_typed(self) -> None: seen, [{"json": payload} for payload in responses] ), ) as client: - cancelled = client.cancel_index_job("index_run:abc") - gc = client.index_gc_submit({"dry_run": False}, idempotency_key="gc-1") - polled = client.index_gc_job(gc.job_id) - stopped = client.cancel_index_gc_job(gc.job_id) deleted = client.delete_graph(confirm="main") branch = client.delete_branch(confirm="review") - self.assertIsInstance(cancelled, SearchIndexJobStatusResponse) - self.assertIsInstance(gc, IndexGcJobStatusResponse) - self.assertIsInstance(polled, IndexGcJobStatusResponse) - self.assertIsInstance(stopped, IndexGcJobStatusResponse) self.assertIsInstance(deleted, GraphDeleteResponse) self.assertIsInstance(branch, GraphBranchDeleteResponse) - self.assertEqual(seen[0].method, "DELETE") - self.assertEqual(seen[1].headers["idempotency-key"], "gc-1") - self.assertEqual(seen[4].url.params["confirm"], "main") - self.assertEqual(seen[5].url.params["confirm"], "review") + self.assertEqual(seen[0].url.params["confirm"], "main") + self.assertEqual(seen[1].url.params["confirm"], "review") def test_governed_conflicts_returns_generated_model(self) -> None: seen: list[httpx.Request] = [] @@ -1146,28 +1031,6 @@ def test_governed_conflicts_returns_generated_model(self) -> None: self.assertIsInstance(result, GovernedConflictAggregationResponse) self.assertEqual(str(seen[0].url).split("?")[0], "http://h/v1/query/conflicts") - def test_schema_namespace_uses_v1_schema_routes(self) -> None: - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", graph="main", transport=capturing_transport(seen) - ) as client: - client.schema.view() - client.schema.view(audit=True) - client.schema.preview({"desired_mode": "warn"}) - client.schema.publish( - {"preview_digest": "sha256:test", "desired_mode": "warn"} - ) - client.schema.audit() - - self.assertEqual(str(seen[0].url).split("?")[0], "http://h/v1/schema") - self.assertEqual(dict(seen[0].url.params), {"graph": "main"}) - self.assertEqual(str(seen[1].url).split("?")[0], "http://h/v1/schema") - self.assertEqual(dict(seen[1].url.params), {"graph": "main", "audit": "true"}) - self.assertEqual(str(seen[2].url).split("?")[0], "http://h/v1/schema/preview") - self.assertEqual(json.loads(seen[2].content), {"desired_mode": "warn"}) - self.assertEqual(str(seen[3].url).split("?")[0], "http://h/v1/schema/publish") - self.assertEqual(str(seen[4].url).split("?")[0], "http://h/v1/schema/audit") - def test_facts_import_serializes_ndjson_with_params(self) -> None: seen: list[httpx.Request] = [] with LbbClient( @@ -1196,6 +1059,7 @@ def test_facts_import_serializes_ndjson_with_params(self) -> None: ], batch=500, strict=True, + publish=True, ) self.assertEqual(result["triplets"], 1) request = seen[0] @@ -1203,6 +1067,7 @@ def test_facts_import_serializes_ndjson_with_params(self) -> None: self.assertEqual(dict(request.url.params)["graph"], "research") self.assertEqual(dict(request.url.params)["batch"], "500") self.assertEqual(dict(request.url.params)["strict"], "true") + self.assertEqual(dict(request.url.params)["publish"], "true") self.assertEqual(request.headers["content-type"], "application/x-ndjson") self.assertRegex(request.headers["idempotency-key"], r"^import:") lines = request.content.decode().split("\n") @@ -1224,6 +1089,7 @@ def test_facts_import_rdf_posts_ntriples_with_params(self) -> None: blank_node_scope="document-42", resource_type="RdfResource", edge_idempotency="append", + publish=True, ) self.assertEqual(result["imported_triplets"], 1) request = seen[0] @@ -1236,26 +1102,11 @@ def test_facts_import_rdf_posts_ntriples_with_params(self) -> None: self.assertEqual(params["blank_node_scope"], "document-42") self.assertEqual(params["resource_type"], "RdfResource") self.assertEqual(params["edge_idempotency"], "append") + self.assertEqual(params["publish"], "true") self.assertEqual(request.headers["content-type"], "application/n-triples") self.assertRegex(request.headers["idempotency-key"], r"^import-rdf:") self.assertEqual(request.content.decode(), body) - def test_import_rdf_keeps_published_ntriples_keyword_compatible(self) -> None: - body = " .\n" - for scoped in (False, True): - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", - transport=capturing_transport(seen, {"json": {"imported_triplets": 1}}), - ) as client: - if scoped: - result = client.graph("research").facts.import_rdf(ntriples=body) - else: - result = client.import_rdf(ntriples=body) - self.assertEqual(result["imported_triplets"], 1) - self.assertEqual(seen[0].content.decode(), body) - self.assertEqual(seen[0].headers["content-type"], "application/n-triples") - def test_facts_import_rdf_supports_turtle_and_base_iri(self) -> None: seen: list[httpx.Request] = [] with LbbClient( @@ -1277,65 +1128,6 @@ def test_facts_import_rdf_supports_turtle_and_base_iri(self) -> None: self.assertEqual(params["graph_uri"], "http://ex/graph") self.assertEqual(request.headers["content-type"], "text/turtle") - def test_graph_export_rdf_returns_text(self) -> None: - seen: list[httpx.Request] = [] - turtle = " .\n" - with LbbClient( - "http://h", - transport=capturing_transport( - seen, - { - "text": turtle, - "headers": {"content-type": "application/n-quads; charset=utf-8"}, - }, - ), - ) as client: - result = client.graph("research", branch="draft").export_rdf( - format="nquads", - max_triples=500, - as_of_commit_seq=7, - ) - self.assertEqual(result, turtle) - request = seen[0] - self.assertEqual(str(request.url).split("?")[0], "http://h/v1/graph/export/rdf") - params = dict(request.url.params) - self.assertEqual(params["graph"], "research") - self.assertEqual(params["branch"], "draft") - self.assertEqual(params["max_triples"], "500") - self.assertEqual(params["as_of_commit_seq"], "7") - self.assertEqual(params["format"], "nquads") - - def test_graph_export_rdf_preview_returns_typed_bounded_slice(self) -> None: - seen: list[httpx.Request] = [] - payload = { - "snapshot": SNAPSHOT, - "format": "ntriples", - "data": " .\n", - "returned_triples": 1, - "total_triples": 109, - "truncated": True, - } - with LbbClient( - "http://h", - transport=capturing_transport(seen, {"json": payload}), - ) as client: - result = client.graph("research", branch="draft").export_rdf_preview( - format="ntriples", - max_triples=1, - as_of_commit_seq=7, - ) - self.assertIsInstance(result, RdfExportPreviewResponse) - self.assertEqual(result.returned_triples, 1) - self.assertEqual(result.total_triples, 109) - self.assertTrue(result.truncated) - params = dict(seen[0].url.params) - self.assertEqual(params["graph"], "research") - self.assertEqual(params["branch"], "draft") - self.assertEqual(params["format"], "nt") - self.assertEqual(params["max_triples"], "1") - self.assertEqual(params["truncate"], "true") - self.assertEqual(params["as_of_commit_seq"], "7") - def test_graph_retract_posts_edges(self) -> None: seen: list[httpx.Request] = [] with LbbClient( @@ -1486,7 +1278,7 @@ def test_raw_request_returns_metadata(self) -> None: seen, { "json": {"ok": True}, - "headers": {"x-request-id": "req_py", "lbb-version": "2026-07-22"}, + "headers": {"x-request-id": "req_py", "lbb-version": "2026-07-23"}, }, ), ) as client: @@ -1494,7 +1286,7 @@ def test_raw_request_returns_metadata(self) -> None: self.assertEqual(response.data, {"ok": True}) self.assertEqual(response.status_code, 200) self.assertEqual(response.request_id, "req_py") - self.assertEqual(response.version, "2026-07-22") + self.assertEqual(response.version, "2026-07-23") def test_raw_response_and_route_model_helpers_validate_generated_models( self, @@ -1508,7 +1300,6 @@ def test_raw_response_and_route_model_helpers_validate_generated_models( [ {"json": summary_payload()}, {"json": summary_payload()}, - {"json": schema_view_payload()}, {"json": sparql_select_payload()}, ], ), @@ -1516,7 +1307,6 @@ def test_raw_response_and_route_model_helpers_validate_generated_models( raw = client.raw_request("GET", "/v1/graph/summary") summary = raw.model(GraphSummaryResponse) summary_again = client.summary_model() - schema = client.schema.view_model() rows = client.entities.filter_by_attributes_model( patterns=[ { @@ -1533,40 +1323,9 @@ def test_raw_response_and_route_model_helpers_validate_generated_models( self.assertIsInstance(summary, GraphSummaryResponse) self.assertEqual(summary.entity_count, 2) self.assertIsInstance(summary_again, GraphSummaryResponse) - self.assertIsInstance(schema, SchemaBundleView) - self.assertFalse(schema.audit_summary.conforms) self.assertIsInstance(rows, SparqlSelectResponse) self.assertEqual(rows.vars, ["svc"]) - self.assertEqual(str(seen[2].url).split("?")[0], "http://h/v1/schema") - self.assertEqual(str(seen[3].url).split("?")[0], "http://h/v1/query/sparql") - - def test_list_page_helpers_validate_entity_and_edge_rows(self) -> None: - seen: list[httpx.Request] = [] - with LbbClient( - "http://h", - graph="main", - transport=capturing_transport( - seen, - [ - {"json": entity_list_payload()}, - {"json": edge_list_payload()}, - ], - ), - ) as client: - entities = client.entities.list_page(fields="*") - edges = client.graph_edges_page( - type="SERVICE", name="auth-service", direction="out" - ) - - self.assertIsInstance(entities, ListPage) - self.assertIsInstance(entities.data[0], EntityExplorerRow) - assert entities.data[0].attributes is not None - self.assertEqual(entities.data[0].attributes["slo"], 0.999) - self.assertIsInstance(edges, ListPage) - self.assertIsInstance(edges.data[0], GraphEdgeRow) - self.assertEqual(edges.data[0].relation.name, "WRITES_TO") - self.assertEqual(dict(seen[0].url.params)["fields"], "*") - self.assertEqual(dict(seen[1].url.params)["direction"], "out") + self.assertEqual(str(seen[2].url).split("?")[0], "http://h/v1/query/sparql") def test_retries_retryable_failures(self) -> None: seen: list[httpx.Request] = [] @@ -1967,11 +1726,9 @@ def test_wait_for_index_lineage_retains_build_and_replica_headers(self) -> None: "head_generation": 1, "wal_tail_commits": 0, "wal_tail_bytes": 0, - "object_count": 0, - "object_bytes": 0, "adjacency_indexed_commit_seq": 7, "index_lineage": lineage, - "unindexed_tail_commits": 0, + "published_lag_commits": 0, } def handler(request: httpx.Request) -> httpx.Response: @@ -2414,53 +2171,17 @@ async def test_async_sparql_parses_rows(self) -> None: ) self.assertEqual(results.rows(), [{"s": "x"}]) - async def test_async_model_and_page_helpers(self) -> None: + async def test_async_summary_model_helper(self) -> None: seen: list[httpx.Request] = [] async with AsyncLbbClient( "http://h", graph="g", - transport=capturing_transport( - seen, - [ - {"json": summary_payload()}, - {"json": entity_list_payload()}, - {"json": edge_list_payload()}, - ], - ), + transport=capturing_transport(seen, {"json": summary_payload()}), ) as client: summary = await client.summary_model() - page = await client.entities.list_page(fields=["slo"]) - edges = await client.graph_edges_page( - type="SERVICE", name="auth-service", direction="out" - ) self.assertIsInstance(summary, GraphSummaryResponse) self.assertEqual(summary.current_edge_count, 3) - self.assertIsInstance(page, ListPage) - self.assertIsInstance(page.data[0], EntityExplorerRow) - self.assertIsInstance(edges.data[0], GraphEdgeRow) - self.assertEqual(dict(seen[1].url.params)["fields"], "slo") - self.assertEqual(dict(seen[2].url.params)["direction"], "out") - - async def test_async_entity_iterator_follows_cursors(self) -> None: - seen: list[httpx.Request] = [] - first = entity_list_payload() - first["has_more"] = True - first["next_cursor"] = "cursor-2" - second = entity_list_payload() - second["data"][0]["id"] = "e2" - second["data"][0]["name"] = "billing-service" - async with AsyncLbbClient( - "http://h", - graph="g", - transport=capturing_transport(seen, [{"json": first}, {"json": second}]), - ) as client: - rows = [row async for row in client.entities.iter(limit=1)] - - self.assertEqual( - [row.name for row in rows], ["auth-service", "billing-service"] - ) - self.assertEqual(dict(seen[1].url.params)["cursor"], "cursor-2") def test_typed_suggestion_helper_validates_before_transport_and_sets_idempotency( self, diff --git a/tests/typecheck_dx.py b/tests/typecheck_dx.py index 78019c6..89d74e6 100644 --- a/tests/typecheck_dx.py +++ b/tests/typecheck_dx.py @@ -2,29 +2,32 @@ from __future__ import annotations -from collections.abc import AsyncIterator, Iterator from typing import TYPE_CHECKING from lbb import AsyncLbbClient, LbbClient -from lbb.models import AskResponse, EntityExplorerRow, OntologyView, SparqlSelectResponse +from lbb.models import EntityTypeSampleResponse, OntologyView, SparqlSelectResponse if TYPE_CHECKING: from typing import assert_type def sync_dx_types(client: LbbClient) -> None: - assert_type(client.context.ask({"question": "what changed?"}), AskResponse) assert_type(client.ontology.view(counts=True), OntologyView) assert_type( client.query.structured({"patterns": [], "select": []}), SparqlSelectResponse, ) - assert_type(client.entities.iter(fields="*"), Iterator[EntityExplorerRow]) + assert_type( + client.entities.sample(type="SERVICE", limit=20), + EntityTypeSampleResponse, + ) async def async_dx_types(client: AsyncLbbClient) -> None: - assert_type(await client.context.ask({"question": "what changed?"}), AskResponse) assert_type(await client.ontology.view(counts=True), OntologyView) assert_type( await client.query.structured({"patterns": [], "select": []}), SparqlSelectResponse, ) - assert_type(client.entities.iter(fields="*"), AsyncIterator[EntityExplorerRow]) + assert_type( + await client.entities.sample(type="SERVICE", limit=20), + EntityTypeSampleResponse, + )