diff --git a/apps/loopover-ui/public/openapi.json b/apps/loopover-ui/public/openapi.json index 0dc4a98de..0035994b6 100644 --- a/apps/loopover-ui/public/openapi.json +++ b/apps/loopover-ui/public/openapi.json @@ -14189,159 +14189,360 @@ "shadowPending" ] }, - "LiveGateThresholdsResponse": { + "EligibilityPlanResponse": { + "type": "object", + "properties": { + "eligible": { + "type": "boolean" + }, + "linkedIssueStatus": { + "type": "string" + }, + "branchEligibilityStatus": { + "type": "string" + }, + "blockers": { + "type": "array", + "items": { + "type": "string" + } + }, + "cleanupPaths": { + "type": "array", + "items": { + "type": "string" + } + }, + "linkedIssueProjection": { + "type": "string", + "nullable": true + }, + "publicSummary": { + "type": "string" + } + } + }, + "ScoreBreakdownResponse": { "type": "object", "properties": { "repoFullName": { "type": "string" }, - "confidence_floor": { - "type": "number", + "scoreabilityStatus": { + "type": "string" + }, + "effectiveEstimatedScore": { + "type": "number" + }, + "components": { "nullable": true }, - "scope_cap_files": { - "type": "integer", + "gateHighlights": { "nullable": true }, - "scope_cap_lines": { - "type": "integer", + "highestLeverageLever": { "nullable": true } + } + }, + "EvaluateEscalationRequest": { + "type": "object", + "properties": { + "runStatus": { + "type": "string", + "enum": [ + "running", + "converged", + "abandoned", + "error" + ] + }, + "healthStatus": { + "type": "string", + "enum": [ + "healthy", + "degraded", + "critical" + ] + }, + "customerFlagged": { + "type": "boolean" + }, + "killRequested": { + "type": "boolean" + } }, "required": [ - "repoFullName", - "confidence_floor", - "scope_cap_files", - "scope_cap_lines" + "runStatus" ] }, - "ContributorScoringProfile": { + "EvaluateEscalationResponse": { "type": "object", "properties": { - "login": { - "type": "string" - }, - "generatedAt": { - "type": "string" + "shouldEscalate": { + "type": "boolean" }, - "scoringModelSnapshotId": { - "type": "string" + "action": { + "type": "string", + "enum": [ + "none", + "notify", + "human_review", + "stop" + ] }, - "evidence": { - "type": "object", - "additionalProperties": { - "type": "number" - } + "severity": { + "type": "string", + "enum": [ + "none", + "low", + "medium", + "high" + ] }, - "privateSignals": { + "reasons": { "type": "array", "items": { "type": "string" } } + } + }, + "BuildResultsPayloadRequest": { + "type": "object", + "properties": { + "repoFullName": { + "type": "string", + "minLength": 1 + }, + "prNumber": { + "type": "integer", + "nullable": true + }, + "title": { + "type": "string" + }, + "changedFiles": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "additions": { + "type": "integer" + }, + "deletions": { + "type": "integer" + } + }, + "required": [ + "path" + ] + }, + "maxItems": 5000 + }, + "status": { + "type": "string", + "enum": [ + "open", + "merged", + "closed" + ] + } }, "required": [ - "login", - "generatedAt", - "scoringModelSnapshotId", - "evidence", - "privateSignals" + "repoFullName", + "title" ] }, - "ContributorStrategy": { + "BuildResultsPayloadResponse": { "type": "object", "properties": { - "login": { - "type": "string" + "prLink": { + "type": "string", + "nullable": true }, - "generatedAt": { + "summary": { "type": "string" }, - "scoringModelSnapshotId": { - "type": "string" + "diffPreview": { + "nullable": true }, - "summary": { - "type": "string" + "totals": { + "nullable": true + } + } + }, + "BuildProgressSnapshotRequest": { + "type": "object", + "properties": { + "iteration": { + "type": "integer" }, - "bestFitRepos": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } + "maxIterations": { + "type": "integer", + "nullable": true }, - "avoidRepos": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } + "phase": { + "type": "string", + "enum": [ + "queued", + "claiming", + "coding", + "reviewing", + "submitting", + "done" + ] }, - "cleanupFirst": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } + "status": { + "type": "string", + "enum": [ + "running", + "converged", + "abandoned", + "error" + ] }, - "maintainerLaneRepos": { + "recentActivity": { "type": "array", "items": { "type": "object", - "additionalProperties": { - "nullable": true - } - } + "properties": { + "step": { + "type": "string" + }, + "detail": { + "type": "string" + }, + "at": { + "type": "string" + } + }, + "required": [ + "step" + ] + }, + "maxItems": 1000 + } + }, + "required": [ + "iteration", + "phase", + "status" + ] + }, + "BuildProgressSnapshotResponse": { + "type": "object", + "properties": { + "phase": { + "type": "string" }, - "successPatterns": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } + "status": { + "type": "string" }, - "failurePatterns": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } + "iteration": { + "type": "number" }, - "laneWarnings": { + "maxIterations": { + "type": "number", + "nullable": true + }, + "percentComplete": { + "type": "number", + "nullable": true + }, + "recentActivity": { + "nullable": true + }, + "done": { + "type": "boolean" + } + } + }, + "IntakeIdeaRequest": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "targetRepo": { + "type": "string" + }, + "constraints": { "type": "array", "items": { "type": "string" - } + }, + "maxItems": 50 }, - "nextActions": { + "acceptanceHints": { "type": "array", "items": { "type": "string" - } + }, + "maxItems": 50 }, - "rewardRisk": { - "type": "object", - "additionalProperties": { - "nullable": true - } + "priority": { + "type": "string" }, - "reasoning": { + "decomposition": { "type": "array", "items": { - "type": "string" - } + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 50 + } + }, + "required": [ + "key", + "title", + "body" + ] + }, + "maxItems": 50 + } + } + }, + "IntakeIdeaResponse": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "verdict": { + "type": "string", + "enum": [ + "go", + "raise", + "avoid" + ] }, - "actionImpact": { + "taskGraph": { + "nullable": true + }, + "errors": { "type": "array", "items": { "type": "string" @@ -14349,393 +14550,254 @@ } }, "required": [ - "login", - "generatedAt", - "scoringModelSnapshotId", - "summary", - "bestFitRepos", - "avoidRepos", - "cleanupFirst", - "maintainerLaneRepos", - "successPatterns", - "failurePatterns", - "laneWarnings", - "nextActions" + "ok" ] }, - "ContributorRewardRiskStrategy": { + "PlanIdeaClaimsRequest": { "type": "object", "properties": { - "login": { + "id": { "type": "string" }, - "generatedAt": { + "title": { "type": "string" }, - "scoringModelSnapshotId": { + "body": { "type": "string" }, - "summary": { + "targetRepo": { "type": "string" }, - "topActions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RewardRiskAction" - } - }, - "repoAnalyses": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RepoRewardRisk" - } - }, - "reasoning": { + "constraints": { "type": "array", "items": { "type": "string" - } + }, + "maxItems": 50 }, - "actionImpact": { + "acceptanceHints": { "type": "array", "items": { "type": "string" - } + }, + "maxItems": 50 }, - "nextActions": { - "type": "array", - "items": { - "type": "string" - } + "priority": { + "type": "string" }, - "eligibilityGap": { + "decomposition": { "type": "array", "items": { "type": "object", "properties": { - "repoFullName": { + "key": { "type": "string" }, - "prsToUnlock": { - "type": "number" - }, - "estimatedScoreAtThreshold": { - "type": "number" + "title": { + "type": "string" }, - "recommendation": { + "body": { "type": "string" + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 50 } }, "required": [ - "repoFullName", - "prsToUnlock", - "estimatedScoreAtThreshold", - "recommendation" + "key", + "title", + "body" ] - } + }, + "maxItems": 50 } - }, - "required": [ - "login", - "generatedAt", - "scoringModelSnapshotId", - "summary", - "topActions", - "repoAnalyses", - "reasoning", - "actionImpact", - "nextActions", - "eligibilityGap" - ] + } }, - "MaintainerNoiseReport": { + "PlanIdeaClaimsResponse": { "type": "object", "properties": { - "repoFullName": { - "type": "string" - }, - "generatedAt": { - "type": "string" - }, - "score": { - "type": "number" + "ok": { + "type": "boolean" }, - "level": { + "verdict": { "type": "string", "enum": [ - "low", - "medium", - "high", - "critical" + "go", + "raise", + "avoid" ] }, - "noiseSources": { + "claimPlan": { + "nullable": true + }, + "errors": { "type": "array", "items": { "type": "string" } + } + }, + "required": [ + "ok" + ] + }, + "LiveGateThresholdsResponse": { + "type": "object", + "properties": { + "repoFullName": { + "type": "string" }, - "maintainerActions": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "review_now", - "needs_author", - "likely_duplicate", - "close_or_redirect", - "watch", - "maintainer_lane" - ] - } + "confidence_floor": { + "type": "number", + "nullable": true }, - "queueHealth": { - "$ref": "#/components/schemas/QueueHealth" + "scope_cap_files": { + "type": "integer", + "nullable": true }, - "summary": { - "type": "string" + "scope_cap_lines": { + "type": "integer", + "nullable": true } }, "required": [ "repoFullName", - "generatedAt", - "score", - "level", - "noiseSources", - "maintainerActions", - "queueHealth", - "summary" + "confidence_floor", + "scope_cap_files", + "scope_cap_lines" ] }, - "AmsMinerCohortComparison": { + "ContributorScoringProfile": { "type": "object", "properties": { - "present": { - "type": "boolean" - }, - "windowDays": { - "type": "number" - }, - "totalSubmitterCount": { - "type": "number" + "login": { + "type": "string" }, - "checkedSubmitterCount": { - "type": "number" + "generatedAt": { + "type": "string" }, - "amsCohort": { - "type": "object", - "properties": { - "submitterCount": { - "type": "number" - }, - "prVolume": { - "type": "number" - }, - "acceptanceRate": { - "type": "number", - "nullable": true - }, - "avgReviewCycleCount": { - "type": "number", - "nullable": true - }, - "avgTimeToMergeMs": { - "type": "number", - "nullable": true - } - }, - "required": [ - "submitterCount", - "prVolume", - "acceptanceRate", - "avgReviewCycleCount", - "avgTimeToMergeMs" - ] + "scoringModelSnapshotId": { + "type": "string" }, - "humanCohort": { + "evidence": { "type": "object", - "properties": { - "submitterCount": { - "type": "number" - }, - "prVolume": { - "type": "number" - }, - "acceptanceRate": { - "type": "number", - "nullable": true - }, - "avgReviewCycleCount": { - "type": "number", - "nullable": true - }, - "avgTimeToMergeMs": { - "type": "number", - "nullable": true - } - }, - "required": [ - "submitterCount", - "prVolume", - "acceptanceRate", - "avgReviewCycleCount", - "avgTimeToMergeMs" - ] + "additionalProperties": { + "type": "number" + } + }, + "privateSignals": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "present", - "windowDays", - "totalSubmitterCount", - "checkedSubmitterCount", - "amsCohort", - "humanCohort" + "login", + "generatedAt", + "scoringModelSnapshotId", + "evidence", + "privateSignals" ] }, - "PullRequestReviewability": { + "ContributorStrategy": { "type": "object", "properties": { - "repoFullName": { + "login": { "type": "string" }, - "pullNumber": { - "type": "number" - }, "generatedAt": { "type": "string" }, - "score": { - "type": "number" + "scoringModelSnapshotId": { + "type": "string" }, - "action": { - "type": "string", - "enum": [ - "review_now", - "needs_author", - "likely_duplicate", - "close_or_redirect", - "watch", - "maintainer_lane" - ] + "summary": { + "type": "string" }, - "noiseSources": { + "bestFitRepos": { "type": "array", "items": { - "type": "string" + "type": "object", + "additionalProperties": { + "nullable": true + } } }, - "whyThisHelps": { + "avoidRepos": { "type": "array", "items": { - "type": "string" + "type": "object", + "additionalProperties": { + "nullable": true + } } }, - "maintainerNextSteps": { + "cleanupFirst": { "type": "array", "items": { - "type": "string" + "type": "object", + "additionalProperties": { + "nullable": true + } } }, - "privateSummary": { - "type": "string" - } - }, - "required": [ - "repoFullName", - "pullNumber", - "generatedAt", - "score", - "action", - "noiseSources", - "whyThisHelps", - "maintainerNextSteps", - "privateSummary" - ] - }, - "PullRequestAiReviewFindings": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "ready", - "not_found", - "ai_review_off" - ] - }, - "repoFullName": { - "type": "string" + "maintainerLaneRepos": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } }, - "pullNumber": { - "type": "number" + "successPatterns": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } }, - "login": { - "type": "string" + "failurePatterns": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } }, - "headSha": { - "type": "string", - "nullable": true + "laneWarnings": { + "type": "array", + "items": { + "type": "string" + } }, - "findings": { + "nextActions": { "type": "array", "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "path": { - "type": "string" - }, - "severity": { - "type": "string", - "enum": [ - "blocker", - "nit" - ] - }, - "line": { - "type": "number" - }, - "body": { - "type": "string" - } - }, - "required": [ - "category", - "path", - "severity", - "line", - "body" - ] + "type": "string" } }, - "categoryCounts": { + "rewardRisk": { "type": "object", "additionalProperties": { - "type": "number" + "nullable": true } - } - }, - "required": [ - "status", - "repoFullName", - "pullNumber", - "login", - "findings", - "categoryCounts" - ] - }, - "FindingTaxonomyDocument": { - "type": "object", - "properties": { - "categories": { + }, + "reasoning": { "type": "array", "items": { "type": "string" } }, - "severities": { + "actionImpact": { "type": "array", "items": { "type": "string" @@ -14743,64 +14805,66 @@ } }, "required": [ - "categories", - "severities" + "login", + "generatedAt", + "scoringModelSnapshotId", + "summary", + "bestFitRepos", + "avoidRepos", + "cleanupFirst", + "maintainerLaneRepos", + "successPatterns", + "failurePatterns", + "laneWarnings", + "nextActions" ] }, - "EnrichmentAnalyzersTaxonomyDocument": { + "ContributorRewardRiskStrategy": { "type": "object", "properties": { - "defaultProfile": { + "login": { "type": "string" }, - "analyzers": { + "generatedAt": { + "type": "string" + }, + "scoringModelSnapshotId": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "topActions": { "type": "array", "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "category": { - "type": "string" - }, - "costClass": { - "type": "string" - }, - "profiles": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "name", - "category", - "costClass", - "profiles" - ] + "$ref": "#/components/schemas/RewardRiskAction" + } + }, + "repoAnalyses": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RepoRewardRisk" + } + }, + "reasoning": { + "type": "array", + "items": { + "type": "string" } - } - }, - "required": [ - "defaultProfile", - "analyzers" - ] - }, - "ContributorPrOutcomes": { - "type": "object", - "properties": { - "login": { - "type": "string" }, - "count": { - "type": "number" + "actionImpact": { + "type": "array", + "items": { + "type": "string" + } }, - "summary": { - "type": "string" + "nextActions": { + "type": "array", + "items": { + "type": "string" + } }, - "outcomes": { + "eligibilityGap": { "type": "array", "items": { "type": "object", @@ -14808,185 +14872,205 @@ "repoFullName": { "type": "string" }, - "pullNumber": { - "type": "number", - "nullable": true - }, - "outcome": { - "type": "string", - "enum": [ - "merged" - ] - }, - "attribution": { - "type": "string" + "prsToUnlock": { + "type": "number" }, - "deeplink": { - "type": "string" + "estimatedScoreAtThreshold": { + "type": "number" }, - "recordedAt": { + "recommendation": { "type": "string" } }, "required": [ "repoFullName", - "pullNumber", - "outcome", - "attribution", - "deeplink", - "recordedAt" + "prsToUnlock", + "estimatedScoreAtThreshold", + "recommendation" ] } } }, "required": [ "login", - "count", + "generatedAt", + "scoringModelSnapshotId", "summary", - "outcomes" - ] - }, - "NotificationFeed": { - "type": "object", - "properties": { - "login": { - "type": "string" - }, - "unreadCount": { - "type": "number" - }, - "notifications": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NotificationFeedItem" - } - } - }, - "required": [ - "login", - "unreadCount", - "notifications" + "topActions", + "repoAnalyses", + "reasoning", + "actionImpact", + "nextActions", + "eligibilityGap" ] }, - "NotificationFeedItem": { + "MaintainerNoiseReport": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "eventType": { - "type": "string" - }, "repoFullName": { "type": "string" }, - "pullNumber": { - "type": "number", - "nullable": true - }, - "title": { - "type": "string" - }, - "body": { + "generatedAt": { "type": "string" }, - "deeplink": { - "type": "string" + "score": { + "type": "number" }, - "status": { + "level": { "type": "string", "enum": [ - "delivered", - "read" + "low", + "medium", + "high", + "critical" ] }, - "createdAt": { + "noiseSources": { + "type": "array", + "items": { + "type": "string" + } + }, + "maintainerActions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "review_now", + "needs_author", + "likely_duplicate", + "close_or_redirect", + "watch", + "maintainer_lane" + ] + } + }, + "queueHealth": { + "$ref": "#/components/schemas/QueueHealth" + }, + "summary": { "type": "string" } }, "required": [ - "id", - "eventType", "repoFullName", - "pullNumber", - "title", - "body", - "deeplink", - "status", - "createdAt" + "generatedAt", + "score", + "level", + "noiseSources", + "maintainerActions", + "queueHealth", + "summary" ] }, - "NotificationsMarked": { + "AmsMinerCohortComparison": { "type": "object", "properties": { - "login": { - "type": "string" + "present": { + "type": "boolean" }, - "marked": { + "windowDays": { "type": "number" - } - }, - "required": [ - "login", - "marked" - ] - }, - "EvaluateEscalationRequest": { - "type": "object", - "properties": { - "runStatus": { - "type": "string", - "enum": [ - "running", - "converged", - "abandoned", - "error" - ] }, - "healthStatus": { - "type": "string", - "enum": [ - "healthy", - "degraded", - "critical" - ] + "totalSubmitterCount": { + "type": "number" }, - "customerFlagged": { - "type": "boolean" + "checkedSubmitterCount": { + "type": "number" }, - "killRequested": { - "type": "boolean" + "amsCohort": { + "type": "object", + "properties": { + "submitterCount": { + "type": "number" + }, + "prVolume": { + "type": "number" + }, + "acceptanceRate": { + "type": "number", + "nullable": true + }, + "avgReviewCycleCount": { + "type": "number", + "nullable": true + }, + "avgTimeToMergeMs": { + "type": "number", + "nullable": true + } + }, + "required": [ + "submitterCount", + "prVolume", + "acceptanceRate", + "avgReviewCycleCount", + "avgTimeToMergeMs" + ] + }, + "humanCohort": { + "type": "object", + "properties": { + "submitterCount": { + "type": "number" + }, + "prVolume": { + "type": "number" + }, + "acceptanceRate": { + "type": "number", + "nullable": true + }, + "avgReviewCycleCount": { + "type": "number", + "nullable": true + }, + "avgTimeToMergeMs": { + "type": "number", + "nullable": true + } + }, + "required": [ + "submitterCount", + "prVolume", + "acceptanceRate", + "avgReviewCycleCount", + "avgTimeToMergeMs" + ] } }, "required": [ - "runStatus" + "present", + "windowDays", + "totalSubmitterCount", + "checkedSubmitterCount", + "amsCohort", + "humanCohort" ] }, - "EvaluateEscalationResponse": { + "GatePrecisionResponse": { "type": "object", "properties": { - "shouldEscalate": { - "type": "boolean" + "repoFullName": { + "type": "string" }, - "action": { - "type": "string", - "enum": [ - "none", - "notify", - "human_review", - "stop" - ] + "generatedAt": { + "type": "string" }, - "severity": { - "type": "string", - "enum": [ - "none", - "low", - "medium", - "high" - ] + "windowDays": { + "type": "number", + "nullable": true }, - "reasons": { + "perGateType": { + "type": "array", + "items": { + "nullable": true + } + }, + "overall": { + "nullable": true + }, + "signals": { "type": "array", "items": { "type": "string" @@ -14994,398 +15078,416 @@ } } }, - "BuildResultsPayloadRequest": { + "OutcomeCalibrationResponse": { "type": "object", "properties": { "repoFullName": { - "type": "string", - "minLength": 1 + "type": "string" }, - "prNumber": { - "type": "integer", + "generatedAt": { + "type": "string" + }, + "windowDays": { + "type": "number", "nullable": true }, - "title": { - "type": "string" + "slop": { + "nullable": true }, - "changedFiles": { + "recommendations": { + "nullable": true + }, + "signals": { "type": "array", "items": { - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "additions": { - "type": "integer" - }, - "deletions": { - "type": "integer" - } - }, - "required": [ - "path" - ] - }, - "maxItems": 5000 + "type": "string" + } }, "status": { - "type": "string", - "enum": [ - "open", - "merged", - "closed" - ] + "type": "string" } - }, - "required": [ - "repoFullName", - "title" - ] + } }, - "BuildResultsPayloadResponse": { + "ActivationPreviewResponse": { "type": "object", "properties": { - "prLink": { - "type": "string", - "nullable": true + "repoFullName": { + "type": "string" }, - "summary": { + "generatedAt": { "type": "string" }, - "diffPreview": { - "nullable": true + "currentReviewCheckMode": { + "type": "string" }, - "totals": { + "aiReviewConfigured": { + "type": "boolean" + }, + "evaluatedCount": { + "type": "number" + }, + "withFindingsCount": { + "type": "number" + }, + "findingCodeCounts": { + "type": "array", + "items": { + "nullable": true + } + }, + "samples": { + "type": "array", + "items": { + "nullable": true + } + }, + "recommendedAction": { + "type": "string", "nullable": true + }, + "summary": { + "type": "string" } } }, - "BuildProgressSnapshotRequest": { + "PullRequestReviewability": { "type": "object", "properties": { - "iteration": { - "type": "integer" + "repoFullName": { + "type": "string" }, - "maxIterations": { - "type": "integer", - "nullable": true + "pullNumber": { + "type": "number" }, - "phase": { - "type": "string", - "enum": [ - "queued", - "claiming", - "coding", - "reviewing", - "submitting", - "done" - ] + "generatedAt": { + "type": "string" }, - "status": { + "score": { + "type": "number" + }, + "action": { "type": "string", "enum": [ - "running", - "converged", - "abandoned", - "error" + "review_now", + "needs_author", + "likely_duplicate", + "close_or_redirect", + "watch", + "maintainer_lane" ] }, - "recentActivity": { + "noiseSources": { "type": "array", "items": { - "type": "object", - "properties": { - "step": { - "type": "string" - }, - "detail": { - "type": "string" - }, - "at": { - "type": "string" - } - }, - "required": [ - "step" - ] - }, - "maxItems": 1000 + "type": "string" + } + }, + "whyThisHelps": { + "type": "array", + "items": { + "type": "string" + } + }, + "maintainerNextSteps": { + "type": "array", + "items": { + "type": "string" + } + }, + "privateSummary": { + "type": "string" } }, "required": [ - "iteration", - "phase", - "status" + "repoFullName", + "pullNumber", + "generatedAt", + "score", + "action", + "noiseSources", + "whyThisHelps", + "maintainerNextSteps", + "privateSummary" ] }, - "BuildProgressSnapshotResponse": { + "PullRequestAiReviewFindings": { "type": "object", "properties": { - "phase": { - "type": "string" - }, "status": { + "type": "string", + "enum": [ + "ready", + "not_found", + "ai_review_off" + ] + }, + "repoFullName": { "type": "string" }, - "iteration": { + "pullNumber": { "type": "number" }, - "maxIterations": { - "type": "number", - "nullable": true + "login": { + "type": "string" }, - "percentComplete": { - "type": "number", + "headSha": { + "type": "string", "nullable": true }, - "recentActivity": { - "nullable": true + "findings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string" + }, + "path": { + "type": "string" + }, + "severity": { + "type": "string", + "enum": [ + "blocker", + "nit" + ] + }, + "line": { + "type": "number" + }, + "body": { + "type": "string" + } + }, + "required": [ + "category", + "path", + "severity", + "line", + "body" + ] + } }, - "done": { - "type": "boolean" + "categoryCounts": { + "type": "object", + "additionalProperties": { + "type": "number" + } } - } + }, + "required": [ + "status", + "repoFullName", + "pullNumber", + "login", + "findings", + "categoryCounts" + ] }, - "IntakeIdeaRequest": { + "FindingTaxonomyDocument": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "body": { - "type": "string" - }, - "targetRepo": { - "type": "string" - }, - "constraints": { + "categories": { "type": "array", "items": { "type": "string" - }, - "maxItems": 50 + } }, - "acceptanceHints": { + "severities": { "type": "array", "items": { "type": "string" - }, - "maxItems": 50 - }, - "priority": { + } + } + }, + "required": [ + "categories", + "severities" + ] + }, + "EnrichmentAnalyzersTaxonomyDocument": { + "type": "object", + "properties": { + "defaultProfile": { "type": "string" }, - "decomposition": { + "analyzers": { "type": "array", "items": { "type": "object", "properties": { - "key": { + "name": { "type": "string" }, - "title": { + "category": { "type": "string" }, - "body": { + "costClass": { "type": "string" }, - "dependsOn": { + "profiles": { "type": "array", "items": { "type": "string" - }, - "maxItems": 50 + } } }, "required": [ - "key", - "title", - "body" + "name", + "category", + "costClass", + "profiles" ] - }, - "maxItems": 50 - } - } - }, - "IntakeIdeaResponse": { - "type": "object", - "properties": { - "ok": { - "type": "boolean" - }, - "verdict": { - "type": "string", - "enum": [ - "go", - "raise", - "avoid" - ] - }, - "taskGraph": { - "nullable": true - }, - "errors": { - "type": "array", - "items": { - "type": "string" } } }, "required": [ - "ok" + "defaultProfile", + "analyzers" ] }, - "PlanIdeaClaimsRequest": { + "ContributorPrOutcomes": { "type": "object", "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "body": { - "type": "string" - }, - "targetRepo": { + "login": { "type": "string" }, - "constraints": { - "type": "array", - "items": { - "type": "string" - }, - "maxItems": 50 - }, - "acceptanceHints": { - "type": "array", - "items": { - "type": "string" - }, - "maxItems": 50 + "count": { + "type": "number" }, - "priority": { + "summary": { "type": "string" }, - "decomposition": { + "outcomes": { "type": "array", "items": { "type": "object", "properties": { - "key": { + "repoFullName": { "type": "string" }, - "title": { + "pullNumber": { + "type": "number", + "nullable": true + }, + "outcome": { + "type": "string", + "enum": [ + "merged" + ] + }, + "attribution": { "type": "string" }, - "body": { + "deeplink": { "type": "string" }, - "dependsOn": { - "type": "array", - "items": { - "type": "string" - }, - "maxItems": 50 + "recordedAt": { + "type": "string" } }, "required": [ - "key", - "title", - "body" + "repoFullName", + "pullNumber", + "outcome", + "attribution", + "deeplink", + "recordedAt" ] - }, - "maxItems": 50 + } } - } + }, + "required": [ + "login", + "count", + "summary", + "outcomes" + ] }, - "PlanIdeaClaimsResponse": { + "NotificationFeed": { "type": "object", "properties": { - "ok": { - "type": "boolean" - }, - "verdict": { - "type": "string", - "enum": [ - "go", - "raise", - "avoid" - ] + "login": { + "type": "string" }, - "claimPlan": { - "nullable": true + "unreadCount": { + "type": "number" }, - "errors": { + "notifications": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/NotificationFeedItem" } } }, "required": [ - "ok" + "login", + "unreadCount", + "notifications" ] }, - "EligibilityPlanResponse": { + "NotificationFeedItem": { "type": "object", "properties": { - "eligible": { - "type": "boolean" + "id": { + "type": "string" }, - "linkedIssueStatus": { + "eventType": { "type": "string" }, - "branchEligibilityStatus": { + "repoFullName": { "type": "string" }, - "blockers": { - "type": "array", - "items": { - "type": "string" - } + "pullNumber": { + "type": "number", + "nullable": true }, - "cleanupPaths": { - "type": "array", - "items": { - "type": "string" - } + "title": { + "type": "string" }, - "linkedIssueProjection": { + "body": { + "type": "string" + }, + "deeplink": { + "type": "string" + }, + "status": { "type": "string", - "nullable": true + "enum": [ + "delivered", + "read" + ] }, - "publicSummary": { + "createdAt": { "type": "string" } - } + }, + "required": [ + "id", + "eventType", + "repoFullName", + "pullNumber", + "title", + "body", + "deeplink", + "status", + "createdAt" + ] }, - "ScoreBreakdownResponse": { + "NotificationsMarked": { "type": "object", "properties": { - "repoFullName": { - "type": "string" - }, - "scoreabilityStatus": { + "login": { "type": "string" }, - "effectiveEstimatedScore": { + "marked": { "type": "number" - }, - "components": { - "nullable": true - }, - "gateHighlights": { - "nullable": true - }, - "highestLeverageLever": { - "nullable": true } - } + }, + "required": [ + "login", + "marked" + ] }, "ListPendingActionsResponse": { "type": "object", @@ -15576,187 +15678,518 @@ "createdAt": { "type": "string" } - }, - "required": [ - "id", - "actionClass", - "pullNumber", - "status", - "autonomyLevel", - "reason", - "decidedBy", - "decidedAt", - "createdAt" - ] + }, + "required": [ + "id", + "actionClass", + "pullNumber", + "status", + "autonomyLevel", + "reason", + "decidedBy", + "decidedAt", + "createdAt" + ] + } + } + } + }, + "parameters": {}, + "securitySchemes": { + "LoopOverBearer": { + "type": "http", + "scheme": "bearer", + "description": "Static API/MCP token or GitHub device-flow LoopOver session token where supported. GitHub personal access tokens are not accepted." + }, + "LoopOverSessionCookie": { + "type": "apiKey", + "in": "cookie", + "name": "loopover_session", + "description": "HttpOnly browser session cookie set by GitHub web OAuth." + } + } + }, + "paths": { + "/health": { + "get": { + "summary": "Service liveness probe", + "responses": { + "200": { + "description": "Service health", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Health" + } + } + } + } + } + } + }, + "/v1/mcp/compatibility": { + "get": { + "summary": "Public-safe API and MCP client compatibility metadata", + "responses": { + "200": { + "description": "Public-safe API and MCP compatibility metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/McpCompatibility" + } + } + } + } + } + } + }, + "/v1/public/stats": { + "get": { + "summary": "Public homepage aggregate stats", + "responses": { + "200": { + "description": "Public-safe homepage stats: lifetime PRs handled/merged/closed, gate + slop blocks, and reversal-grounded accuracy. Aggregate counts only.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicStats" + } + } + } + }, + "404": { + "description": "Public stats are disabled (LOOPOVER_PUBLIC_STATS off)" + }, + "503": { + "description": "Public stats are temporarily unavailable" + } + } + } + }, + "/v1/public/github/repos/{owner}/{repo}/stats": { + "get": { + "summary": "Public GitHub stars and forks for an allowlisted repository", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Public GitHub repository stars/forks for the website chrome; PUBLIC_REPO_STATS_ALLOWLIST must explicitly include the owner/repo.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicRepoStats" + } + } + } + }, + "400": { + "description": "Invalid or non-allowlisted GitHub repository" + }, + "503": { + "description": "GitHub repository stats are unavailable" + } + } + } + }, + "/v1/public/repos/{owner}/{repo}/quality": { + "get": { + "summary": "Public repository quality summary for an opted-in repository", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Public per-repo review-quality metrics: gate false-positive rates, merge-vs-close ratio, and weekly trend. Aggregate counts only; opt-in via publicQualityMetrics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicQualityMetrics" + } + } + } + }, + "404": { + "description": "Repo is unknown/private/uninstalled or has not opted in" + }, + "503": { + "description": "Public quality metrics are temporarily unavailable" + } + } + } + }, + "/v1/registry/snapshot": { + "get": { + "summary": "Latest Gittensor registry snapshot", + "responses": { + "200": { + "description": "Latest Gittensor registry snapshot", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegistrySnapshot" + } + } + } + } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] + } + }, + "/v1/registry/changes": { + "get": { + "summary": "Diff between the two latest registry snapshots", + "responses": { + "200": { + "description": "Diff between latest registry snapshots", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegistryChangeReport" + } + } + } + } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] + } + }, + "/v1/scoring/model": { + "get": { + "summary": "Latest scoring model snapshot", + "responses": { + "200": { + "description": "Latest private scoring model snapshot", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScoringModelSnapshot" + } + } + } } - } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] } }, - "parameters": {}, - "securitySchemes": { - "LoopOverBearer": { - "type": "http", - "scheme": "bearer", - "description": "Static API/MCP token or GitHub device-flow LoopOver session token where supported. GitHub personal access tokens are not accepted." - }, - "LoopOverSessionCookie": { - "type": "apiKey", - "in": "cookie", - "name": "loopover_session", - "description": "HttpOnly browser session cookie set by GitHub web OAuth." + "/v1/finding-taxonomy": { + "get": { + "summary": "Canonical AI-review finding taxonomy", + "responses": { + "200": { + "description": "Finding categories and the severity ladder", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FindingTaxonomyDocument" + } + } + } + } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] } - } - }, - "paths": { - "/health": { + }, + "/v1/enrichment-analyzers": { "get": { - "summary": "Service liveness probe", + "summary": "REES enrichment analyzer taxonomy", "responses": { "200": { - "description": "Service health", + "description": "Default profile and the registered enrichment analyzers", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Health" + "$ref": "#/components/schemas/EnrichmentAnalyzersTaxonomyDocument" } } } } - } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] } }, - "/v1/mcp/compatibility": { + "/v1/upstream/status": { "get": { - "summary": "Public-safe API and MCP client compatibility metadata", + "summary": "Upstream Gittensor source and ruleset drift status", "responses": { "200": { - "description": "Public-safe API and MCP compatibility metadata", + "description": "Upstream Gittensor source/ruleset drift status", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/McpCompatibility" + "$ref": "#/components/schemas/UpstreamStatus" } } } } - } + }, + "security": [ + { + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] } }, - "/v1/public/stats": { + "/v1/upstream/ruleset": { "get": { - "summary": "Public homepage aggregate stats", + "summary": "Latest normalized upstream Gittensor ruleset snapshot", "responses": { "200": { - "description": "Public-safe homepage stats: lifetime PRs handled/merged/closed, gate + slop blocks, and reversal-grounded accuracy. Aggregate counts only.", + "description": "Latest normalized upstream Gittensor ruleset snapshot", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PublicStats" + "$ref": "#/components/schemas/UpstreamRulesetSnapshot" } } } }, "404": { - "description": "Public stats are disabled (LOOPOVER_PUBLIC_STATS off)" + "description": "No upstream ruleset snapshot has been built yet" + } + }, + "security": [ + { + "LoopOverBearer": [] }, - "503": { - "description": "Public stats are temporarily unavailable" + { + "LoopOverSessionCookie": [] } - } + ] } }, - "/v1/public/github/repos/{owner}/{repo}/stats": { + "/v1/upstream/drift": { "get": { - "summary": "Public GitHub stars and forks for an allowlisted repository", - "parameters": [ + "summary": "Open and historical upstream drift reports", + "responses": { + "200": { + "description": "Open and historical upstream drift reports", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "generatedAt": { + "type": "string" + }, + "upstreamDrift": { + "$ref": "#/components/schemas/UpstreamStatus" + }, + "reports": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UpstreamDriftReport" + } + } + }, + "required": [ + "generatedAt", + "upstreamDrift", + "reports" + ] + } + } + } + } + }, + "security": [ { - "schema": { - "type": "string" - }, - "required": true, - "name": "owner", - "in": "path" + "LoopOverBearer": [] }, { - "schema": { - "type": "string" - }, - "required": true, - "name": "repo", - "in": "path" + "LoopOverSessionCookie": [] } - ], + ] + } + }, + "/v1/scoring/preview": { + "post": { + "summary": "Generate a scoring preview artifact for a candidate contribution", "responses": { "200": { - "description": "Public GitHub repository stars/forks for the website chrome; PUBLIC_REPO_STATS_ALLOWLIST must explicitly include the owner/repo.", + "description": "Private scoring preview artifact", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PublicRepoStats" + "$ref": "#/components/schemas/ScorePreview" } } } }, "400": { - "description": "Invalid or non-allowlisted GitHub repository" + "description": "Invalid scoring preview input" + } + }, + "security": [ + { + "LoopOverBearer": [] }, - "503": { - "description": "GitHub repository stats are unavailable" + { + "LoopOverSessionCookie": [] } - } + ] } }, - "/v1/public/repos/{owner}/{repo}/quality": { - "get": { - "summary": "Public repository quality summary for an opted-in repository", - "parameters": [ + "/v1/scoring/eligibility-plan": { + "post": { + "summary": "Derive a contributor eligibility plan from a scoring preview — REST mirror of loopover_get_eligibility_plan (#9301)", + "responses": { + "200": { + "description": "Structured eligibility plan over a server-built score preview — mirrors the loopover_get_eligibility_plan MCP tool. Advisory only; it explains eligibility, it does not open issues or PRs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EligibilityPlanResponse" + } + } + } + }, + "400": { + "description": "Invalid scoring preview input" + } + }, + "security": [ { - "schema": { - "type": "string" - }, - "required": true, - "name": "owner", - "in": "path" + "LoopOverBearer": [] + }, + { + "LoopOverSessionCookie": [] + } + ] + } + }, + "/v1/scoring/explain-breakdown": { + "post": { + "summary": "Explain a score breakdown from a scoring preview — REST mirror of loopover_explain_score_breakdown (#9301)", + "responses": { + "200": { + "description": "Score multiplier breakdown and gate highlights over a server-built score preview — mirrors the loopover_explain_score_breakdown MCP tool. Requires contributorLogin in the request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScoreBreakdownResponse" + } + } + } + }, + "400": { + "description": "Invalid scoring preview input or missing contributorLogin" + } + }, + "security": [ + { + "LoopOverBearer": [] }, { - "schema": { - "type": "string" - }, - "required": true, - "name": "repo", - "in": "path" + "LoopOverSessionCookie": [] } - ], + ] + } + }, + "/v1/sync/status": { + "get": { + "summary": "Repository and installation sync status", "responses": { "200": { - "description": "Public per-repo review-quality metrics: gate false-positive rates, merge-vs-close ratio, and weekly trend. Aggregate counts only; opt-in via publicQualityMetrics.", + "description": "Repository and installation sync status", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PublicQualityMetrics" + "$ref": "#/components/schemas/SyncStatus" } } } + } + }, + "security": [ + { + "LoopOverBearer": [] }, - "404": { - "description": "Repo is unknown/private/uninstalled or has not opted in" - }, - "503": { - "description": "Public quality metrics are temporarily unavailable" + { + "LoopOverSessionCookie": [] } - } + ] } }, - "/v1/registry/snapshot": { + "/v1/readiness": { "get": { - "summary": "Latest Gittensor registry snapshot", + "summary": "Operational readiness summary for the hosted API", "responses": { "200": { - "description": "Latest Gittensor registry snapshot", + "description": "Operational readiness summary for hosted API, signal fidelity, and public-review preparation", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegistrySnapshot" + "$ref": "#/components/schemas/Readiness" } } } @@ -15772,16 +16205,37 @@ ] } }, - "/v1/registry/changes": { + "/v1/installations": { "get": { - "summary": "Diff between the two latest registry snapshots", + "summary": "List GitHub App installations and their health", "responses": { "200": { - "description": "Diff between latest registry snapshots", + "description": "GitHub App installations and health", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegistryChangeReport" + "type": "object", + "properties": { + "installations": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } + }, + "health": { + "type": "array", + "items": { + "$ref": "#/components/schemas/InstallationHealth" + } + } + }, + "required": [ + "installations", + "health" + ] } } } @@ -15797,19 +16251,32 @@ ] } }, - "/v1/scoring/model": { + "/v1/installations/{id}/health": { "get": { - "summary": "Latest scoring model snapshot", + "summary": "GitHub App installation health detail", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], "responses": { "200": { - "description": "Latest private scoring model snapshot", + "description": "GitHub App installation health", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScoringModelSnapshot" + "$ref": "#/components/schemas/InstallationHealth" } } } + }, + "404": { + "description": "Installation health not found" } }, "security": [ @@ -15822,19 +16289,32 @@ ] } }, - "/v1/finding-taxonomy": { + "/v1/installations/{id}/repair": { "get": { - "summary": "Canonical AI-review finding taxonomy", + "summary": "GitHub App installation repair diagnostics", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], "responses": { "200": { - "description": "Finding categories and the severity ladder", + "description": "GitHub App installation repair diagnostics", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/FindingTaxonomyDocument" + "$ref": "#/components/schemas/InstallationRepair" } } } + }, + "404": { + "description": "Installation health not found" } }, "security": [ @@ -15847,19 +16327,32 @@ ] } }, - "/v1/enrichment-analyzers": { - "get": { - "summary": "REES enrichment analyzer taxonomy", + "/v1/installations/{id}/repair/refresh": { + "post": { + "summary": "Recompute GitHub App installation repair diagnostics", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], "responses": { "200": { - "description": "Default profile and the registered enrichment analyzers", + "description": "Refreshed GitHub App installation repair diagnostics", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EnrichmentAnalyzersTaxonomyDocument" + "$ref": "#/components/schemas/InstallationRepair" } } } + }, + "404": { + "description": "Installation not found" } }, "security": [ @@ -15872,19 +16365,134 @@ ] } }, - "/v1/upstream/status": { + "/v1/app/notification-model": { "get": { - "summary": "Upstream Gittensor source and ruleset drift status", + "summary": "Opt-in notification model and PWA-readiness metadata", "responses": { "200": { - "description": "Upstream Gittensor source/ruleset drift status", + "description": "Opt-in notification model and PWA-readiness metadata for control-panel routes", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpstreamStatus" + "type": "object", + "properties": { + "generatedAt": { + "type": "string" + }, + "notificationModel": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "opt_in" + ] + }, + "defaultState": { + "type": "string", + "enum": [ + "disabled" + ] + }, + "channels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "transport": { + "type": "string", + "enum": [ + "in_app", + "web_push" + ] + }, + "defaultEnabled": { + "type": "boolean" + }, + "requiresPermission": { + "type": "boolean" + }, + "purpose": { + "type": "string" + } + }, + "required": [ + "id", + "transport", + "defaultEnabled", + "purpose" + ] + } + }, + "privacyGuards": { + "type": "array", + "items": { + "type": "string" + } + }, + "fallbackWhenUnavailable": { + "type": "string", + "enum": [ + "in_app_digest_only" + ] + } + }, + "required": [ + "mode", + "defaultState", + "channels", + "privacyGuards", + "fallbackWhenUnavailable" + ] + }, + "pwa": { + "type": "object", + "properties": { + "nativeDependency": { + "type": "boolean" + }, + "manifestPath": { + "type": "string" + }, + "serviceWorkerPath": { + "type": "string" + } + }, + "required": [ + "nativeDependency", + "manifestPath", + "serviceWorkerPath" + ] + }, + "mobileReadyRoutes": { + "type": "array", + "items": { + "type": "string" + } + }, + "nativeMobileFuture": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "generatedAt", + "notificationModel", + "pwa", + "mobileReadyRoutes", + "nativeMobileFuture" + ] } } } + }, + "403": { + "description": "Role does not allow control-panel notification model access" } }, "security": [ @@ -15897,22 +16505,22 @@ ] } }, - "/v1/upstream/ruleset": { + "/v1/repos": { "get": { - "summary": "Latest normalized upstream Gittensor ruleset snapshot", + "summary": "List known repositories", "responses": { "200": { - "description": "Latest normalized upstream Gittensor ruleset snapshot", + "description": "Known repositories", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpstreamRulesetSnapshot" + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } } } } - }, - "404": { - "description": "No upstream ruleset snapshot has been built yet" } }, "security": [ @@ -15925,38 +16533,40 @@ ] } }, - "/v1/upstream/drift": { + "/v1/repos/{owner}/{repo}": { "get": { - "summary": "Open and historical upstream drift reports", + "summary": "Repository detail", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], "responses": { "200": { - "description": "Open and historical upstream drift reports", + "description": "Repository detail", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "generatedAt": { - "type": "string" - }, - "upstreamDrift": { - "$ref": "#/components/schemas/UpstreamStatus" - }, - "reports": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UpstreamDriftReport" - } - } - }, - "required": [ - "generatedAt", - "upstreamDrift", - "reports" - ] + "$ref": "#/components/schemas/Repository" } } } + }, + "404": { + "description": "Repository not found" } }, "security": [ @@ -15969,22 +16579,37 @@ ] } }, - "/v1/scoring/preview": { - "post": { - "summary": "Generate a scoring preview artifact for a candidate contribution", + "/v1/repos/{owner}/{repo}/intelligence": { + "get": { + "summary": "Canonical repository intelligence bundle", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], "responses": { "200": { - "description": "Private scoring preview artifact", + "description": "Canonical repository intelligence bundle", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScorePreview" + "$ref": "#/components/schemas/RepoIntelligence" } } } - }, - "400": { - "description": "Invalid scoring preview input" } }, "security": [ @@ -15997,19 +16622,40 @@ ] } }, - "/v1/sync/status": { + "/v1/repos/{owner}/{repo}/issue-quality": { "get": { - "summary": "Repository and installation sync status", + "summary": "Repository issue quality report", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], "responses": { "200": { - "description": "Repository and installation sync status", + "description": "Cached or computed issue quality report for the repo", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SyncStatus" + "$ref": "#/components/schemas/IssueQualityResponse" } } } + }, + "404": { + "description": "Repo is unknown or has no issue-quality coverage yet" } }, "security": [ @@ -16022,19 +16668,43 @@ ] } }, - "/v1/readiness": { + "/v1/repos/{owner}/{repo}/gate-config/effective": { "get": { - "summary": "Operational readiness summary for the hosted API", + "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": "Operational readiness summary for hosted API, signal fidelity, and public-review preparation", + "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/Readiness" + "$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": [ @@ -16047,40 +16717,31 @@ ] } }, - "/v1/installations": { - "get": { - "summary": "List GitHub App installations and their health", + "/v1/loop/evaluate-escalation": { + "post": { + "summary": "Evaluate whether a loop outcome should escalate — REST mirror of loopover_evaluate_escalation (#9309)", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvaluateEscalationRequest" + } + } + } + }, "responses": { "200": { - "description": "GitHub App installations and health", + "description": "Escalation decision over caller-supplied loop outcome + health signals — mirrors the loopover_evaluate_escalation MCP tool. Pure, source-free evaluator; it decides, the caller wires the action", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "installations": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "nullable": true - } - } - }, - "health": { - "type": "array", - "items": { - "$ref": "#/components/schemas/InstallationHealth" - } - } - }, - "required": [ - "installations", - "health" - ] + "$ref": "#/components/schemas/EvaluateEscalationResponse" } } } + }, + "400": { + "description": "Invalid evaluate-escalation request body" } }, "security": [ @@ -16093,32 +16754,31 @@ ] } }, - "/v1/installations/{id}/health": { - "get": { - "summary": "GitHub App installation health detail", - "parameters": [ - { - "schema": { - "type": "string" - }, - "required": true, - "name": "id", - "in": "path" + "/v1/loop/results-payload": { + "post": { + "summary": "Compose a loop results-delivery payload — REST mirror of loopover_build_results_payload (#9309)", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildResultsPayloadRequest" + } + } } - ], + }, "responses": { "200": { - "description": "GitHub App installation health", + "description": "Formatted results payload over caller-supplied iteration metadata — mirrors the loopover_build_results_payload MCP tool. Pure composer; it formats the result, it does not fetch, open, or deliver anything", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstallationHealth" + "$ref": "#/components/schemas/BuildResultsPayloadResponse" } } } }, - "404": { - "description": "Installation health not found" + "400": { + "description": "Invalid results-payload request body" } }, "security": [ @@ -16131,32 +16791,31 @@ ] } }, - "/v1/installations/{id}/repair": { - "get": { - "summary": "GitHub App installation repair diagnostics", - "parameters": [ - { - "schema": { - "type": "string" - }, - "required": true, - "name": "id", - "in": "path" + "/v1/loop/progress-snapshot": { + "post": { + "summary": "Compose a running-loop progress snapshot — REST mirror of loopover_build_progress_snapshot (#9309)", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildProgressSnapshotRequest" + } + } } - ], + }, "responses": { "200": { - "description": "GitHub App installation repair diagnostics", + "description": "Formatted progress snapshot over caller-supplied loop state — mirrors the loopover_build_progress_snapshot MCP tool. Pure composer; it formats the snapshot, it does not fetch or stream anything", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstallationRepair" + "$ref": "#/components/schemas/BuildProgressSnapshotResponse" } } } }, - "404": { - "description": "Installation health not found" + "400": { + "description": "Invalid progress-snapshot request body" } }, "security": [ @@ -16169,32 +16828,31 @@ ] } }, - "/v1/installations/{id}/repair/refresh": { + "/v1/loop/intake-idea": { "post": { - "summary": "Recompute GitHub App installation repair diagnostics", - "parameters": [ - { - "schema": { - "type": "string" - }, - "required": true, - "name": "id", - "in": "path" + "summary": "Validate an idea submission and assemble its task-graph — REST mirror of loopover_intake_idea (#9309)", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntakeIdeaRequest" + } + } } - ], + }, "responses": { "200": { - "description": "Refreshed GitHub App installation repair diagnostics", + "description": "Idea verdict + assembled task-graph — mirrors the loopover_intake_idea MCP tool. Pure composer over the caller-supplied idea and optional decomposition", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstallationRepair" + "$ref": "#/components/schemas/IntakeIdeaResponse" } } } }, - "404": { - "description": "Installation not found" + "400": { + "description": "Invalid intake-idea request body, or an empty/malformed idea submission (actionable error list returned)" } }, "security": [ @@ -16207,134 +16865,31 @@ ] } }, - "/v1/app/notification-model": { - "get": { - "summary": "Opt-in notification model and PWA-readiness metadata", + "/v1/loop/plan-idea-claims": { + "post": { + "summary": "Disposition an idea's task-graph into a claim plan — REST mirror of loopover_plan_idea_claims (#9309)", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanIdeaClaimsRequest" + } + } + } + }, "responses": { "200": { - "description": "Opt-in notification model and PWA-readiness metadata for control-panel routes", + "description": "Idea verdict + claim plan (which constituent issues can be claimed now vs. deferred) — mirrors the loopover_plan_idea_claims MCP tool. Pure composer over the caller-supplied idea and optional decomposition", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "generatedAt": { - "type": "string" - }, - "notificationModel": { - "type": "object", - "properties": { - "mode": { - "type": "string", - "enum": [ - "opt_in" - ] - }, - "defaultState": { - "type": "string", - "enum": [ - "disabled" - ] - }, - "channels": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "transport": { - "type": "string", - "enum": [ - "in_app", - "web_push" - ] - }, - "defaultEnabled": { - "type": "boolean" - }, - "requiresPermission": { - "type": "boolean" - }, - "purpose": { - "type": "string" - } - }, - "required": [ - "id", - "transport", - "defaultEnabled", - "purpose" - ] - } - }, - "privacyGuards": { - "type": "array", - "items": { - "type": "string" - } - }, - "fallbackWhenUnavailable": { - "type": "string", - "enum": [ - "in_app_digest_only" - ] - } - }, - "required": [ - "mode", - "defaultState", - "channels", - "privacyGuards", - "fallbackWhenUnavailable" - ] - }, - "pwa": { - "type": "object", - "properties": { - "nativeDependency": { - "type": "boolean" - }, - "manifestPath": { - "type": "string" - }, - "serviceWorkerPath": { - "type": "string" - } - }, - "required": [ - "nativeDependency", - "manifestPath", - "serviceWorkerPath" - ] - }, - "mobileReadyRoutes": { - "type": "array", - "items": { - "type": "string" - } - }, - "nativeMobileFuture": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "generatedAt", - "notificationModel", - "pwa", - "mobileReadyRoutes", - "nativeMobileFuture" - ] + "$ref": "#/components/schemas/PlanIdeaClaimsResponse" } } } }, - "403": { - "description": "Role does not allow control-panel notification model access" + "400": { + "description": "Invalid plan-idea-claims request body, or an empty/malformed idea submission (actionable error list returned)" } }, "security": [ @@ -16347,22 +16902,43 @@ ] } }, - "/v1/repos": { + "/v1/repos/{owner}/{repo}/live-gate-thresholds": { "get": { - "summary": "List known repositories", + "summary": "Live self-tuned gate thresholds for AMS probe (#6486)", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "owner", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "repo", + "in": "path" + } + ], "responses": { "200": { - "description": "Known repositories", + "description": "Field-limited live (or soaking-shadow) TunableOverride values — confidence_floor / scope_cap_files / scope_cap_lines only", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Repository" - } + "$ref": "#/components/schemas/LiveGateThresholdsResponse" } } } + }, + "403": { + "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" + }, + "404": { + "description": "No live or shadow gate override is active for this repo" } }, "security": [ @@ -16375,9 +16951,9 @@ ] } }, - "/v1/repos/{owner}/{repo}": { + "/v1/repos/{owner}/{repo}/maintainer-noise": { "get": { - "summary": "Repository detail", + "summary": "Maintainer queue-noise triage report for a repository (#9302)", "parameters": [ { "schema": { @@ -16398,17 +16974,20 @@ ], "responses": { "200": { - "description": "Repository detail", + "description": "Noise score/level, specific noise sources to clear first, and recommended maintainer actions — mirrors the loopover_get_maintainer_noise MCP tool. Maintainer-authenticated; advisory only", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Repository" + "$ref": "#/components/schemas/MaintainerNoiseReport" } } } }, - "404": { - "description": "Repository not found" + "401": { + "description": "Missing or invalid static protected API token" + }, + "403": { + "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" } }, "security": [ @@ -16421,9 +17000,9 @@ ] } }, - "/v1/repos/{owner}/{repo}/intelligence": { + "/v1/repos/{owner}/{repo}/ams-miner-cohort": { "get": { - "summary": "Canonical repository intelligence bundle", + "summary": "AMS-vs-human contributor-mix cohort comparison for a repository (#9302)", "parameters": [ { "schema": { @@ -16444,14 +17023,20 @@ ], "responses": { "200": { - "description": "Canonical repository intelligence bundle", + "description": "Submitter counts, PR volume, acceptance rate, review-cycle, and time-to-merge metrics for AMS-tracked vs human submitters — mirrors the loopover_get_ams_miner_cohort MCP tool. Maintainer-authenticated; advisory only", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RepoIntelligence" + "$ref": "#/components/schemas/AmsMinerCohortComparison" } } } + }, + "401": { + "description": "Missing or invalid static protected API token" + }, + "403": { + "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" } }, "security": [ @@ -16464,9 +17049,9 @@ ] } }, - "/v1/repos/{owner}/{repo}/issue-quality": { + "/v1/repos/{owner}/{repo}/gate-precision": { "get": { - "summary": "Repository issue quality report", + "summary": "Per-gate-type false-positive precision measurement for a repository (#9302)", "parameters": [ { "schema": { @@ -16483,21 +17068,34 @@ "required": true, "name": "repo", "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": false, + "name": "windowDays", + "in": "query" } ], "responses": { "200": { - "description": "Cached or computed issue quality report for the repo", + "description": "Blocked / blocked-then-merged / overridden counts and false-positive rates with low-sample guards — mirrors the loopover_get_gate_precision MCP tool. Maintainer-authenticated; measurement only", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IssueQualityResponse" + "$ref": "#/components/schemas/GatePrecisionResponse" } } } }, - "404": { - "description": "Repo is unknown or has no issue-quality coverage yet" + "401": { + "description": "Missing or invalid static protected API token" + }, + "403": { + "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" } }, "security": [ @@ -16510,9 +17108,9 @@ ] } }, - "/v1/repos/{owner}/{repo}/gate-config/effective": { + "/v1/repos/{owner}/{repo}/outcome-calibration": { "get": { - "summary": "Current effective self-tuned gate config for a repo (#6247)", + "summary": "Slop-band and recommendation outcome calibration for a repository (#9302)", "parameters": [ { "schema": { @@ -16529,15 +17127,25 @@ "required": true, "name": "repo", "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": false, + "name": "windowDays", + "in": "query" } ], "responses": { "200": { - "description": "Effective TunableOverride values (confidenceFloor / scopeCap.files / scopeCap.lines) with a shadowPending flag — never the raw override_audit history", + "description": "Whether higher-slop bands merge less often and how agent recommendations are panning out — mirrors the loopover_get_outcome_calibration MCP tool. Maintainer-authenticated; measurement only", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GateConfigEffectiveResponse" + "$ref": "#/components/schemas/OutcomeCalibrationResponse" } } } @@ -16559,9 +17167,9 @@ ] } }, - "/v1/repos/{owner}/{repo}/live-gate-thresholds": { + "/v1/repos/{owner}/{repo}/activation-preview": { "get": { - "summary": "Live self-tuned gate thresholds for AMS probe (#6486)", + "summary": "Deterministic maintainer activation preview for a repository (#9302)", "parameters": [ { "schema": { @@ -16582,20 +17190,20 @@ ], "responses": { "200": { - "description": "Field-limited live (or soaking-shadow) TunableOverride values — confidence_floor / scope_cap_files / scope_cap_lines only", + "description": "A deterministic \"here's what LoopOver would have surfaced\" run of the advisory engine over recent PRs — mirrors the loopover_get_activation_preview MCP tool. Maintainer-authenticated; advisory only, never runs AI", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LiveGateThresholdsResponse" + "$ref": "#/components/schemas/ActivationPreviewResponse" } } } }, + "401": { + "description": "Missing or invalid static protected API token" + }, "403": { "description": "Static mcp credential is outside MCP_READ_REPO_ALLOWLIST for this repo" - }, - "404": { - "description": "No live or shadow gate override is active for this repo" } }, "security": [ @@ -20243,247 +20851,6 @@ ] } }, - "/v1/loop/evaluate-escalation": { - "post": { - "summary": "Evaluate whether a loop outcome should escalate — REST mirror of loopover_evaluate_escalation (#9309)", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EvaluateEscalationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Escalation decision over caller-supplied loop outcome + health signals — mirrors the loopover_evaluate_escalation MCP tool. Pure, source-free evaluator; it decides, the caller wires the action", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EvaluateEscalationResponse" - } - } - } - }, - "400": { - "description": "Invalid evaluate-escalation request body" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/loop/results-payload": { - "post": { - "summary": "Compose a loop results-delivery payload — REST mirror of loopover_build_results_payload (#9309)", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BuildResultsPayloadRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Formatted results payload over caller-supplied iteration metadata — mirrors the loopover_build_results_payload MCP tool. Pure composer; it formats the result, it does not fetch, open, or deliver anything", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BuildResultsPayloadResponse" - } - } - } - }, - "400": { - "description": "Invalid results-payload request body" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/loop/progress-snapshot": { - "post": { - "summary": "Compose a running-loop progress snapshot — REST mirror of loopover_build_progress_snapshot (#9309)", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BuildProgressSnapshotRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Formatted progress snapshot over caller-supplied loop state — mirrors the loopover_build_progress_snapshot MCP tool. Pure composer; it formats the snapshot, it does not fetch or stream anything", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BuildProgressSnapshotResponse" - } - } - } - }, - "400": { - "description": "Invalid progress-snapshot request body" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/loop/intake-idea": { - "post": { - "summary": "Validate an idea submission and assemble its task-graph — REST mirror of loopover_intake_idea (#9309)", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntakeIdeaRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Idea verdict + assembled task-graph — mirrors the loopover_intake_idea MCP tool. Pure composer over the caller-supplied idea and optional decomposition", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntakeIdeaResponse" - } - } - } - }, - "400": { - "description": "Invalid intake-idea request body, or an empty/malformed idea submission (actionable error list returned)" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/loop/plan-idea-claims": { - "post": { - "summary": "Disposition an idea's task-graph into a claim plan — REST mirror of loopover_plan_idea_claims (#9309)", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PlanIdeaClaimsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Idea verdict + claim plan (which constituent issues can be claimed now vs. deferred) — mirrors the loopover_plan_idea_claims MCP tool. Pure composer over the caller-supplied idea and optional decomposition", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PlanIdeaClaimsResponse" - } - } - } - }, - "400": { - "description": "Invalid plan-idea-claims request body, or an empty/malformed idea submission (actionable error list returned)" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/scoring/eligibility-plan": { - "post": { - "summary": "Derive a contributor eligibility plan from a scoring preview — REST mirror of loopover_get_eligibility_plan (#9301)", - "responses": { - "200": { - "description": "Structured eligibility plan over a server-built score preview — mirrors the loopover_get_eligibility_plan MCP tool. Advisory only; it explains eligibility, it does not open issues or PRs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EligibilityPlanResponse" - } - } - } - }, - "400": { - "description": "Invalid scoring preview input" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, - "/v1/scoring/explain-breakdown": { - "post": { - "summary": "Explain a score breakdown from a scoring preview — REST mirror of loopover_explain_score_breakdown (#9301)", - "responses": { - "200": { - "description": "Score multiplier breakdown and gate highlights over a server-built score preview — mirrors the loopover_explain_score_breakdown MCP tool. Requires contributorLogin in the request body", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScoreBreakdownResponse" - } - } - } - }, - "400": { - "description": "Invalid scoring preview input or missing contributorLogin" - } - }, - "security": [ - { - "LoopOverBearer": [] - }, - { - "LoopOverSessionCookie": [] - } - ] - } - }, "/v1/repos/{owner}/{repo}/agent/pending-actions": { "get": { "summary": "Maintainer-scoped agent approval queue of pending staged actions", diff --git a/src/mcp/server.ts b/src/mcp/server.ts index 73dbe7ff2..fde2cb0cb 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -967,7 +967,7 @@ const repoContextOutputSchema = { dataQuality: z.unknown().optional(), }; -const maintainerNoiseOutputSchema = { +export const maintainerNoiseOutputSchema = { repoFullName: z.string().optional(), generatedAt: z.string().optional(), score: z.number().optional(), @@ -978,7 +978,7 @@ const maintainerNoiseOutputSchema = { summary: z.string().optional(), }; -const amsMinerCohortOutputSchema = { +export const amsMinerCohortOutputSchema = { present: z.boolean().optional(), windowDays: z.number().optional(), totalSubmitterCount: z.number().optional(), @@ -996,7 +996,7 @@ const repoFocusManifestOutputSchema = { // (#7799) Repo-specific "here's what LoopOver would have surfaced" activation preview over recent PRs. // Mirrors buildMaintainerActivationPreview's shape; deterministic, maintainer-authenticated, advisory only. -const activationPreviewOutputSchema = { +export const activationPreviewOutputSchema = { repoFullName: z.string().optional(), generatedAt: z.string().optional(), currentReviewCheckMode: z.string().optional(), @@ -1114,7 +1114,7 @@ const repoSettingsOutputSchema = { slopGateMode: z.string().optional(), }; -const maintainerMeasurementReportOutputSchema = { +export const maintainerMeasurementReportOutputSchema = { repoFullName: z.string().optional(), generatedAt: z.string().optional(), windowDays: z.number().nullable().optional(), @@ -1127,7 +1127,7 @@ const maintainerMeasurementReportOutputSchema = { // #2220 - gate-precision measurement surfaced over MCP. Mirrors the // maintainerMeasurementReportOutputSchema pattern: report fields optional, structured sub-reports as // z.unknown() (buildGatePrecisionReport is the single source of truth for their shape). -const gatePrecisionOutputSchema = { +export const gatePrecisionOutputSchema = { repoFullName: z.string().optional(), generatedAt: z.string().optional(), windowDays: z.number().nullable().optional(), diff --git a/src/openapi/schemas.ts b/src/openapi/schemas.ts index 3816a9437..6032479aa 100644 --- a/src/openapi/schemas.ts +++ b/src/openapi/schemas.ts @@ -3057,6 +3057,59 @@ export const AmsMinerCohortComparisonSchema = z }) .openapi("AmsMinerCohortComparison"); +/** + * Response body for GET /v1/repos/{owner}/{repo}/gate-precision. Field-level parity with + * `gatePrecisionOutputSchema` (the `loopover_get_gate_precision` MCP tool `outputSchema`) in + * src/mcp/server.ts — #9302. + */ +export const GatePrecisionResponseSchema = z + .object({ + repoFullName: z.string().optional(), + generatedAt: z.string().optional(), + windowDays: z.number().nullable().optional(), + perGateType: z.array(z.unknown()).optional(), + overall: z.unknown().optional(), + signals: z.array(z.string()).optional(), + }) + .openapi("GatePrecisionResponse"); + +/** + * Response body for GET /v1/repos/{owner}/{repo}/outcome-calibration. Field-level parity with + * `maintainerMeasurementReportOutputSchema` (the `loopover_get_outcome_calibration` MCP tool + * `outputSchema`) in src/mcp/server.ts — #9302. + */ +export const OutcomeCalibrationResponseSchema = z + .object({ + repoFullName: z.string().optional(), + generatedAt: z.string().optional(), + windowDays: z.number().nullable().optional(), + slop: z.unknown().optional(), + recommendations: z.unknown().optional(), + signals: z.array(z.string()).optional(), + status: z.string().optional(), + }) + .openapi("OutcomeCalibrationResponse"); + +/** + * Response body for GET /v1/repos/{owner}/{repo}/activation-preview. Field-level parity with + * `activationPreviewOutputSchema` (the `loopover_get_activation_preview` MCP tool `outputSchema`) in + * src/mcp/server.ts — #9302. + */ +export const ActivationPreviewResponseSchema = z + .object({ + repoFullName: z.string().optional(), + generatedAt: z.string().optional(), + currentReviewCheckMode: z.string().optional(), + aiReviewConfigured: z.boolean().optional(), + evaluatedCount: z.number().optional(), + withFindingsCount: z.number().optional(), + findingCodeCounts: z.array(z.unknown()).optional(), + samples: z.array(z.unknown()).optional(), + recommendedAction: z.string().nullable().optional(), + summary: z.string().optional(), + }) + .openapi("ActivationPreviewResponse"); + export const PullRequestReviewabilitySchema = z .object({ repoFullName: z.string(), diff --git a/src/openapi/spec.ts b/src/openapi/spec.ts index cf1df39aa..88d25ee1a 100644 --- a/src/openapi/spec.ts +++ b/src/openapi/spec.ts @@ -59,6 +59,9 @@ import { MaintainerLaneReportSchema, MaintainerNoiseReportSchema, AmsMinerCohortComparisonSchema, + GatePrecisionResponseSchema, + OutcomeCalibrationResponseSchema, + ActivationPreviewResponseSchema, McpCompatibilitySchema, PullRequestAiReviewFindingsSchema, PullRequestMaintainerPacketSchema, @@ -205,6 +208,9 @@ export function buildOpenApiSpec() { registry.register("ContributorRewardRiskStrategy", ContributorRewardRiskStrategySchema); registry.register("MaintainerNoiseReport", MaintainerNoiseReportSchema); registry.register("AmsMinerCohortComparison", AmsMinerCohortComparisonSchema); + registry.register("GatePrecisionResponse", GatePrecisionResponseSchema); + registry.register("OutcomeCalibrationResponse", OutcomeCalibrationResponseSchema); + registry.register("ActivationPreviewResponse", ActivationPreviewResponseSchema); registry.register("PullRequestReviewability", PullRequestReviewabilitySchema); registry.register("PullRequestAiReviewFindings", PullRequestAiReviewFindingsSchema); @@ -630,6 +636,87 @@ export function buildOpenApiSpec() { 404: { description: "No live or shadow gate override is active for this repo" }, }, }); + registry.registerPath({ + method: "get", + path: "/v1/repos/{owner}/{repo}/maintainer-noise", + summary: "Maintainer queue-noise triage report for a repository (#9302)", + request: { params: z.object({ owner: z.string(), repo: z.string() }) }, + responses: { + 200: { + description: + "Noise score/level, specific noise sources to clear first, and recommended maintainer actions — mirrors the loopover_get_maintainer_noise MCP tool. Maintainer-authenticated; advisory only", + content: { "application/json": { schema: MaintainerNoiseReportSchema } }, + }, + 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}/ams-miner-cohort", + summary: "AMS-vs-human contributor-mix cohort comparison for a repository (#9302)", + request: { params: z.object({ owner: z.string(), repo: z.string() }) }, + responses: { + 200: { + description: + "Submitter counts, PR volume, acceptance rate, review-cycle, and time-to-merge metrics for AMS-tracked vs human submitters — mirrors the loopover_get_ams_miner_cohort MCP tool. Maintainer-authenticated; advisory only", + content: { "application/json": { schema: AmsMinerCohortComparisonSchema } }, + }, + 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}/gate-precision", + summary: "Per-gate-type false-positive precision measurement for a repository (#9302)", + request: { + params: z.object({ owner: z.string(), repo: z.string() }), + query: z.object({ windowDays: z.coerce.number().int().positive().optional() }), + }, + responses: { + 200: { + description: + "Blocked / blocked-then-merged / overridden counts and false-positive rates with low-sample guards — mirrors the loopover_get_gate_precision MCP tool. Maintainer-authenticated; measurement only", + content: { "application/json": { schema: GatePrecisionResponseSchema } }, + }, + 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}/outcome-calibration", + summary: "Slop-band and recommendation outcome calibration for a repository (#9302)", + request: { + params: z.object({ owner: z.string(), repo: z.string() }), + query: z.object({ windowDays: z.coerce.number().int().positive().optional() }), + }, + responses: { + 200: { + description: + "Whether higher-slop bands merge less often and how agent recommendations are panning out — mirrors the loopover_get_outcome_calibration MCP tool. Maintainer-authenticated; measurement only", + content: { "application/json": { schema: OutcomeCalibrationResponseSchema } }, + }, + 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}/activation-preview", + summary: "Deterministic maintainer activation preview for a repository (#9302)", + request: { params: z.object({ owner: z.string(), repo: z.string() }) }, + responses: { + 200: { + description: + "A deterministic \"here's what LoopOver would have surfaced\" run of the advisory engine over recent PRs — mirrors the loopover_get_activation_preview MCP tool. Maintainer-authenticated; advisory only, never runs AI", + content: { "application/json": { schema: ActivationPreviewResponseSchema } }, + }, + 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}/outcome-patterns", diff --git a/test/unit/openapi.test.ts b/test/unit/openapi.test.ts index c5eb0da30..451fd6bfa 100644 --- a/test/unit/openapi.test.ts +++ b/test/unit/openapi.test.ts @@ -16,6 +16,11 @@ import { proposeActionOutputSchema, proposeActionShape, decidePendingActionOutputSchema, + maintainerNoiseOutputSchema, + amsMinerCohortOutputSchema, + gatePrecisionOutputSchema, + maintainerMeasurementReportOutputSchema, + activationPreviewOutputSchema, } from "../../src/mcp/server"; describe("OpenAPI contract", () => { @@ -34,6 +39,11 @@ describe("OpenAPI contract", () => { 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}/maintainer-noise"]).toBeDefined(); + expect(spec.paths["/v1/repos/{owner}/{repo}/ams-miner-cohort"]).toBeDefined(); + expect(spec.paths["/v1/repos/{owner}/{repo}/gate-precision"]).toBeDefined(); + expect(spec.paths["/v1/repos/{owner}/{repo}/outcome-calibration"]).toBeDefined(); + expect(spec.paths["/v1/repos/{owner}/{repo}/activation-preview"]).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(); @@ -98,7 +108,6 @@ describe("OpenAPI contract", () => { "/v1/repos/{owner}/{repo}/burden-forecast", "/v1/repos/{owner}/{repo}/registry-drift", "/v1/repos/{owner}/{repo}/maintainer-lane", - "/v1/repos/{owner}/{repo}/maintainer-noise", "/v1/repos/{owner}/{repo}/pulls/{number}/review-intelligence", "/v1/repos/{owner}/{repo}/pulls/{number}/scoring-preview", "/v1/internal/jobs/generate-signal-snapshots/run", @@ -118,6 +127,11 @@ describe("OpenAPI contract", () => { expect(spec.components?.schemas?.RepoOutcomePatterns).toBeDefined(); expect(spec.components?.schemas?.RegistrationReadiness).toBeDefined(); expect(spec.components?.schemas?.GittensorConfigRecommendation).toBeDefined(); + expect(spec.components?.schemas?.GatePrecisionResponse).toBeDefined(); + expect(spec.components?.schemas?.OutcomeCalibrationResponse).toBeDefined(); + expect(spec.components?.schemas?.ActivationPreviewResponse).toBeDefined(); + expect(spec.components?.schemas?.MaintainerNoiseReport).toBeDefined(); + expect(spec.components?.schemas?.AmsMinerCohortComparison).toBeDefined(); expect(spec.components?.schemas?.PullRequestMaintainerPacket).toBeDefined(); expect(spec.components?.schemas?.PullRequestReviewability).toBeDefined(); expect(spec.components?.schemas?.PullRequestAiReviewFindings).toBeDefined(); @@ -310,6 +324,53 @@ describe("OpenAPI contract", () => { } }); + // #9302: five maintainer-report GET routes are each backed by an MCP tool whose Zod output shape already + // lives in src/mcp/server.ts. Assert every route is a documented GET path whose response component keys + // stay field-for-field in parity with those tool shapes. + it("documents the repo maintainer-report route family with tool-parity schemas (#9302)", () => { + const spec = buildOpenApiSpec(); + const schemas = spec.components?.schemas ?? {}; + + const propKeys = (name: string) => + Object.keys((schemas[name] as { properties?: Record }).properties ?? {}).sort(); + + const cases = [ + { + path: "/v1/repos/{owner}/{repo}/maintainer-noise", + response: "MaintainerNoiseReport", + outputShape: maintainerNoiseOutputSchema, + }, + { + path: "/v1/repos/{owner}/{repo}/ams-miner-cohort", + response: "AmsMinerCohortComparison", + outputShape: amsMinerCohortOutputSchema, + }, + { + path: "/v1/repos/{owner}/{repo}/gate-precision", + response: "GatePrecisionResponse", + outputShape: gatePrecisionOutputSchema, + }, + { + path: "/v1/repos/{owner}/{repo}/outcome-calibration", + response: "OutcomeCalibrationResponse", + outputShape: maintainerMeasurementReportOutputSchema, + }, + { + path: "/v1/repos/{owner}/{repo}/activation-preview", + response: "ActivationPreviewResponse", + outputShape: activationPreviewOutputSchema, + }, + ]; + + for (const { path, response, outputShape } of cases) { + const op = spec.paths[path]?.get; + expect(op, `${path} should be a documented GET path`).toBeDefined(); + + expect(schemas[response], `${response} component should be registered`).toBeDefined(); + expect(propKeys(response)).toEqual(Object.keys(outputShape).sort()); + } + }); + it("declares an `in: path` parameter for every {templated} path segment (Cloudflare schema-validation warning 30046)", () => { const spec = buildOpenApiSpec(); for (const [path, methods] of Object.entries(spec.paths ?? {})) {