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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions generated/graphql/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4440,6 +4440,35 @@ type GapsArtifactGaps {
gaps: Gaps!
gap_severity: String
gap_priority: Int
schema_parity: GapsArtifactGapsSchemaParity
}

type GapsArtifactGapsSchemaParity {
"""Captured machine-readable specs backing this measurement."""
captured_schema_count: Int!

"""
Paths the subnet's captured spec(s) declare, summed across captured specs.
"""
captured_path_count: Int!

"""
Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero.
"""
declared_non_get_count: Int

"""
Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route).
"""
registered_route_surface_count: Int!

"""Registered surfaces declaring a non-GET method (#11146 phase 3)."""
registered_non_get_count: Int!

"""
True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's \`observed_at\` against the schema index's \`capture_cadence_hours\`.
"""
flagged: Boolean!
}

type EvidenceList {
Expand Down
30 changes: 30 additions & 0 deletions generated/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2745,9 +2745,26 @@ export type GapsArtifactGaps = {
gaps: Gaps;
name: Scalars['String']['output'];
netuid: Scalars['Int']['output'];
schema_parity?: Maybe<GapsArtifactGapsSchemaParity>;
slug: Scalars['String']['output'];
};

export type GapsArtifactGapsSchemaParity = {
__typename?: 'GapsArtifactGapsSchemaParity';
/** Paths the subnet's captured spec(s) declare, summed across captured specs. */
captured_path_count: Scalars['Int']['output'];
/** Captured machine-readable specs backing this measurement. */
captured_schema_count: Scalars['Int']['output'];
/** Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero. */
declared_non_get_count?: Maybe<Scalars['Int']['output']>;
/** True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's `observed_at` against the schema index's `capture_cadence_hours`. */
flagged: Scalars['Boolean']['output'];
/** Registered surfaces declaring a non-GET method (#11146 phase 3). */
registered_non_get_count: Scalars['Int']['output'];
/** Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route). */
registered_route_surface_count: Scalars['Int']['output'];
};

/** Registry-wide interface gap report page. Mirrors GET /api/v1/gaps (and MCP list_gaps). */
export type GapsList = {
__typename?: 'GapsList';
Expand Down Expand Up @@ -8592,6 +8609,7 @@ export type ResolversTypes = ResolversObject<{
Float: ResolverTypeWrapper<Scalars['Float']['output']>;
Gaps: ResolverTypeWrapper<Gaps>;
GapsArtifactGaps: ResolverTypeWrapper<GapsArtifactGaps>;
GapsArtifactGapsSchemaParity: ResolverTypeWrapper<GapsArtifactGapsSchemaParity>;
GapsList: ResolverTypeWrapper<GapsList>;
GlobalHealth: ResolverTypeWrapper<GlobalHealth>;
GlobalIncidentSurface: ResolverTypeWrapper<GlobalIncidentSurface>;
Expand Down Expand Up @@ -9061,6 +9079,7 @@ export type ResolversParentTypes = ResolversObject<{
Float: Scalars['Float']['output'];
Gaps: Gaps;
GapsArtifactGaps: GapsArtifactGaps;
GapsArtifactGapsSchemaParity: GapsArtifactGapsSchemaParity;
GapsList: GapsList;
GlobalHealth: GlobalHealth;
GlobalIncidentSurface: GlobalIncidentSurface;
Expand Down Expand Up @@ -11475,9 +11494,19 @@ export type GapsArtifactGapsResolvers<ContextType = GqlContext, ParentType exten
gaps?: Resolver<ResolversTypes['Gaps'], ParentType, ContextType>;
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
netuid?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
schema_parity?: Resolver<Maybe<ResolversTypes['GapsArtifactGapsSchemaParity']>, ParentType, ContextType>;
slug?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
}>;

export type GapsArtifactGapsSchemaParityResolvers<ContextType = GqlContext, ParentType extends ResolversParentTypes['GapsArtifactGapsSchemaParity'] = ResolversParentTypes['GapsArtifactGapsSchemaParity']> = ResolversObject<{
captured_path_count?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
captured_schema_count?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
declared_non_get_count?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
flagged?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
registered_non_get_count?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
registered_route_surface_count?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
}>;

export type GapsListResolvers<ContextType = GqlContext, ParentType extends ResolversParentTypes['GapsList'] = ResolversParentTypes['GapsList']> = ResolversObject<{
cursor?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
gaps?: Resolver<Array<ResolversTypes['GapsArtifactGaps']>, ParentType, ContextType>;
Expand Down Expand Up @@ -14748,6 +14777,7 @@ export type Resolvers<ContextType = GqlContext> = ResolversObject<{
FailureReasonsDay?: FailureReasonsDayResolvers<ContextType>;
Gaps?: GapsResolvers<ContextType>;
GapsArtifactGaps?: GapsArtifactGapsResolvers<ContextType>;
GapsArtifactGapsSchemaParity?: GapsArtifactGapsSchemaParityResolvers<ContextType>;
GapsList?: GapsListResolvers<ContextType>;
GlobalHealth?: GlobalHealthResolvers<ContextType>;
GlobalIncidentSurface?: GlobalIncidentSurfaceResolvers<ContextType>;
Expand Down
22 changes: 22 additions & 0 deletions packages/contract/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8636,6 +8636,20 @@ export interface components {
gaps: components["schemas"]["Gaps"];
name: string;
netuid: number;
schema_parity?: {
/** @description Paths the subnet's captured spec(s) declare, summed across captured specs. */
captured_path_count: number;
/** @description Captured machine-readable specs backing this measurement. */
captured_schema_count: number;
/** @description Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero. */
declared_non_get_count: number | null;
/** @description True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's `observed_at` against the schema index's `capture_cadence_hours`. */
flagged: boolean;
/** @description Registered surfaces declaring a non-GET method (#11146 phase 3). */
registered_non_get_count: number;
/** @description Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route). */
registered_route_surface_count: number;
};
slug: string;
}[];
generated_at: string;
Expand Down Expand Up @@ -10331,6 +10345,7 @@ export interface components {
url: string;
};
SchemaIndexArtifact: {
capture_cadence_hours?: number;
contract_version?: string;
generated_at: string;
/** @description Public-safe notes; may be a string or a string list depending on the adapter. */
Expand All @@ -10347,6 +10362,11 @@ export interface components {
schema_version: 1;
schemas: {
content_type?: string | null;
/**
* @description What drift_status compares against: this registry's PREVIOUS capture of the same surface, never the subnet's live spec. `unchanged` means 'our snapshot is what it was', NOT 'the upstream API has not changed'. Judge currency from this entry's `snapshot.observed_at` against the artifact's `capture_cadence_hours`.
* @constant
*/
drift_basis?: "previous-capture";
/** @enum {string} */
drift_status: "new" | "changed" | "unchanged" | "not-captured" | "missing-after-previous-capture";
error?: string | null;
Expand All @@ -10370,6 +10390,7 @@ export interface components {
generated_at?: string | null;
hash?: string | null;
netuid?: number | null;
non_get_operation_count?: number;
observed_at?: string | null;
openapi_version?: string | null;
path_count?: number;
Expand Down Expand Up @@ -39252,6 +39273,7 @@ export interface operations {
/**
* @example {
* "data": {
* "capture_cadence_hours": 0.5,
* "contract_version": "2026-06-29.1",
* "generated_at": "2026-06-01T00:00:00.000Z",
* "notes": "Example description.",
Expand Down
70 changes: 70 additions & 0 deletions public/metagraph/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -8240,6 +8240,7 @@
"SchemaIndexArtifactResponse": {
"value": {
"data": {
"capture_cadence_hours": 0.5,
"contract_version": "2026-06-29.1",
"generated_at": "2026-06-01T00:00:00.000Z",
"notes": "Example description.",
Expand Down Expand Up @@ -34250,6 +34251,61 @@
"minimum": 0,
"type": "integer"
},
"schema_parity": {
"additionalProperties": false,
"properties": {
"captured_path_count": {
"description": "Paths the subnet's captured spec(s) declare, summed across captured specs.",
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
"captured_schema_count": {
"description": "Captured machine-readable specs backing this measurement.",
"maximum": 9007199254740991,
"minimum": 1,
"type": "integer"
},
"declared_non_get_count": {
"anyOf": [
{
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero."
},
"flagged": {
"description": "True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's `observed_at` against the schema index's `capture_cadence_hours`.",
"type": "boolean"
},
"registered_non_get_count": {
"description": "Registered surfaces declaring a non-GET method (#11146 phase 3).",
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
"registered_route_surface_count": {
"description": "Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route).",
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
}
},
"required": [
"captured_schema_count",
"captured_path_count",
"declared_non_get_count",
"registered_route_surface_count",
"registered_non_get_count",
"flagged"
],
"type": "object"
},
"slug": {
"type": "string"
}
Expand Down Expand Up @@ -43396,6 +43452,10 @@
"SchemaIndexArtifact": {
"additionalProperties": false,
"properties": {
"capture_cadence_hours": {
"minimum": 0,
"type": "number"
},
"contract_version": {
"type": "string"
},
Expand Down Expand Up @@ -43446,6 +43506,11 @@
}
]
},
"drift_basis": {
"const": "previous-capture",
"description": "What drift_status compares against: this registry's PREVIOUS capture of the same surface, never the subnet's live spec. `unchanged` means 'our snapshot is what it was', NOT 'the upstream API has not changed'. Judge currency from this entry's `snapshot.observed_at` against the artifact's `capture_cadence_hours`.",
"type": "string"
},
"drift_status": {
"enum": [
"new",
Expand Down Expand Up @@ -43634,6 +43699,11 @@
}
]
},
"non_get_operation_count": {
"maximum": 9007199254740991,
"minimum": 0,
"type": "integer"
},
"observed_at": {
"anyOf": [
{
Expand Down
22 changes: 22 additions & 0 deletions public/metagraph/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8636,6 +8636,20 @@ export interface components {
gaps: components["schemas"]["Gaps"];
name: string;
netuid: number;
schema_parity?: {
/** @description Paths the subnet's captured spec(s) declare, summed across captured specs. */
captured_path_count: number;
/** @description Captured machine-readable specs backing this measurement. */
captured_schema_count: number;
/** @description Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero. */
declared_non_get_count: number | null;
/** @description True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's `observed_at` against the schema index's `capture_cadence_hours`. */
flagged: boolean;
/** @description Registered surfaces declaring a non-GET method (#11146 phase 3). */
registered_non_get_count: number;
/** @description Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route). */
registered_route_surface_count: number;
};
slug: string;
}[];
generated_at: string;
Expand Down Expand Up @@ -10331,6 +10345,7 @@ export interface components {
url: string;
};
SchemaIndexArtifact: {
capture_cadence_hours?: number;
contract_version?: string;
generated_at: string;
/** @description Public-safe notes; may be a string or a string list depending on the adapter. */
Expand All @@ -10347,6 +10362,11 @@ export interface components {
schema_version: 1;
schemas: {
content_type?: string | null;
/**
* @description What drift_status compares against: this registry's PREVIOUS capture of the same surface, never the subnet's live spec. `unchanged` means 'our snapshot is what it was', NOT 'the upstream API has not changed'. Judge currency from this entry's `snapshot.observed_at` against the artifact's `capture_cadence_hours`.
* @constant
*/
drift_basis?: "previous-capture";
/** @enum {string} */
drift_status: "new" | "changed" | "unchanged" | "not-captured" | "missing-after-previous-capture";
error?: string | null;
Expand All @@ -10370,6 +10390,7 @@ export interface components {
generated_at?: string | null;
hash?: string | null;
netuid?: number | null;
non_get_operation_count?: number;
observed_at?: string | null;
openapi_version?: string | null;
path_count?: number;
Expand Down Expand Up @@ -39252,6 +39273,7 @@ export interface operations {
/**
* @example {
* "data": {
* "capture_cadence_hours": 0.5,
* "contract_version": "2026-06-29.1",
* "generated_at": "2026-06-01T00:00:00.000Z",
* "notes": "Example description.",
Expand Down
1 change: 1 addition & 0 deletions schemas-src/graphql/published-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ export const PUBLISHED_TYPE_NAMES: Readonly<Record<string, string>> = {
EvidenceLedgerArtifactSummary: "EvidenceLedgerArtifactSummary",
Gaps: "Gaps",
GapsArtifactGaps: "GapsArtifactGaps",
GapsArtifactGapsSchemaParity: "GapsArtifactGapsSchemaParity",
GlobalIncidentsArtifactSummary: "GlobalIncidentsArtifactSummary",
HealthHistoryArtifactSurfaces: "HealthHistoryArtifactSurfaces",
HealthIncidentsArtifactSurfaces: "HealthIncidentsArtifactSurfaces",
Expand Down
34 changes: 34 additions & 0 deletions schemas-src/routes/curation-gaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,39 @@ export type CurationArtifact = z.infer<typeof CurationArtifactSchema>;

export const GAPS_SORT_FIELDS = API_QUERY_COLLECTIONS.gaps.sort_fields;

/** #11146 phase 4: captured spec vs registered catalogue, per subnet. Present
* only when the subnet has captured schema-index entries with stamped counts
* -- absence means "not measured", never "in parity". Not exported: the only
* consumer is GapsEntrySchema below, and an export nothing imports is what
* the unreferenced-exports ratchet counts. */
const SchemaParitySchema = z
.object({
captured_schema_count: z.int().min(1).meta({
description: "Captured machine-readable specs backing this measurement.",
}),
captured_path_count: z.int().min(0).meta({
description:
"Paths the subnet's captured spec(s) declare, summed across captured specs.",
}),
declared_non_get_count: z.int().min(0).nullable().meta({
description:
"Declared POST/PUT/PATCH/DELETE operations. NULL when the captured entries predate the capture-time stamp -- unmeasured, not zero.",
}),
registered_route_surface_count: z.int().min(0).meta({
description:
"Registered concrete route surfaces (subnet-api/sse/data-artifact; the openapi spec surface itself is not a route).",
}),
registered_non_get_count: z.int().min(0).meta({
description:
"Registered surfaces declaring a non-GET method (#11146 phase 3).",
}),
flagged: z.boolean().meta({
description:
"True when the subnet declares more paths than the catalogue registers as routes -- a caller reading only the registry cannot tell which routes are missing. Judge its currency from the entry's `observed_at` against the schema index's `capture_cadence_hours`.",
}),
})
.strict();

export const GapsEntrySchema = z
.object({
netuid: z.int().min(0),
Expand All @@ -61,6 +94,7 @@ export const GapsEntrySchema = z
gaps: GapsSchema,
gap_severity: z.enum(ENDPOINT_INCIDENT_SEVERITY_VALUES).optional(),
gap_priority: z.int().min(0).optional(),
schema_parity: SchemaParitySchema.optional(),
})
.strict();

Expand Down
Loading
Loading