diff --git a/apps/loopover-ui/public/openapi.json b/apps/loopover-ui/public/openapi.json index c90e4e9b27..a1e6f52e35 100644 --- a/apps/loopover-ui/public/openapi.json +++ b/apps/loopover-ui/public/openapi.json @@ -14056,6 +14056,52 @@ "amsCohort", "humanCohort" ] + }, + "GateConfigEffectiveResponse": { + "type": "object", + "properties": { + "repoFullName": { + "type": "string" + }, + "effective": { + "type": "object", + "properties": { + "confidenceFloor": { + "type": "number", + "nullable": true + }, + "scopeCap": { + "type": "object", + "properties": { + "files": { + "type": "integer", + "nullable": true + }, + "lines": { + "type": "integer", + "nullable": true + } + }, + "required": [ + "files", + "lines" + ] + } + }, + "required": [ + "confidenceFloor", + "scopeCap" + ] + }, + "shadowPending": { + "type": "boolean" + } + }, + "required": [ + "repoFullName", + "effective", + "shadowPending" + ] } }, "parameters": {}, @@ -18114,6 +18160,55 @@ } ] } + }, + "/v1/repos/{owner}/{repo}/gate-config/effective": { + "get": { + "summary": "Current effective self-tuned gate config for a repo (#6247)", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Effective TunableOverride values (confidenceFloor / scopeCap.files / scopeCap.lines) with a shadowPending flag — never the raw override_audit history", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GateConfigEffectiveResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid static protected API token" + }, + "403": { + "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" + } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] + } } }, "servers": [ diff --git a/src/openapi/schemas.ts b/src/openapi/schemas.ts index a0c72a3c15..9d9bc62882 100644 --- a/src/openapi/schemas.ts +++ b/src/openapi/schemas.ts @@ -1749,6 +1749,20 @@ export const LiveGateThresholdsResponseSchema = z }) .openapi("LiveGateThresholdsResponse"); +export const GateConfigEffectiveResponseSchema = z + .object({ + repoFullName: z.string(), + effective: z.object({ + confidenceFloor: z.number().nullable(), + scopeCap: z.object({ + files: z.number().int().nullable(), + lines: z.number().int().nullable(), + }), + }), + shadowPending: z.boolean(), + }) + .openapi("GateConfigEffectiveResponse"); + export const BurdenForecastSchema = z .object({ repoFullName: z.string(), diff --git a/src/openapi/spec.ts b/src/openapi/spec.ts index 867a4a7481..30354b50c7 100644 --- a/src/openapi/spec.ts +++ b/src/openapi/spec.ts @@ -31,6 +31,7 @@ import { InstallationRepairSchema, IssueQualityReportSchema, IssueQualityResponseSchema, + GateConfigEffectiveResponseSchema, LabelAuditSchema, LaneAdviceSchema, LiveGateThresholdsResponseSchema, @@ -150,6 +151,7 @@ export function buildOpenApiSpec() { registry.register("ScorePreview", ScorePreviewSchema); registry.register("IssueQualityReport", IssueQualityReportSchema); registry.register("IssueQualityResponse", IssueQualityResponseSchema); + registry.register("GateConfigEffectiveResponse", GateConfigEffectiveResponseSchema); registry.register("LiveGateThresholdsResponse", LiveGateThresholdsResponseSchema); registry.register("BurdenForecast", BurdenForecastSchema); registry.register("ContributorScoringProfile", ContributorScoringProfileSchema); @@ -423,6 +425,20 @@ export function buildOpenApiSpec() { 404: { description: "Repo is unknown or has no issue-quality coverage yet" }, }, }); + registry.registerPath({ + method: "get", + path: "/v1/repos/{owner}/{repo}/gate-config/effective", + summary: "Current effective self-tuned gate config for a repo (#6247)", + request: { params: z.object({ owner: z.string(), repo: z.string() }) }, + responses: { + 200: { + description: "Effective TunableOverride values (confidenceFloor / scopeCap.files / scopeCap.lines) with a shadowPending flag — never the raw override_audit history", + content: { "application/json": { schema: GateConfigEffectiveResponseSchema } }, + }, + 401: { description: "Missing or invalid static protected API token" }, + 403: { description: "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" }, + }, + }); registry.registerPath({ method: "get", path: "/v1/repos/{owner}/{repo}/live-gate-thresholds", diff --git a/test/unit/openapi.test.ts b/test/unit/openapi.test.ts index dfbba5ba05..54d6c520e8 100644 --- a/test/unit/openapi.test.ts +++ b/test/unit/openapi.test.ts @@ -14,6 +14,7 @@ describe("OpenAPI contract", () => { expect(spec.paths["/v1/repos/{owner}/{repo}/intelligence"]).toBeDefined(); expect(spec.paths["/v1/repos/{owner}/{repo}/issue-quality"]).toBeDefined(); expect(spec.paths["/v1/repos/{owner}/{repo}/outcome-patterns"]).toBeDefined(); + expect(spec.paths["/v1/repos/{owner}/{repo}/gate-config/effective"]).toBeDefined(); expect(spec.paths["/v1/repos/{owner}/{repo}/registration-readiness"]).toBeDefined(); expect(spec.paths["/v1/repos/{owner}/{repo}/gittensor-config-recommendation"]).toBeDefined(); expect(spec.paths["/v1/repos/{owner}/{repo}/pulls/{number}/maintainer-packet"]).toBeDefined();