@@ -67,6 +67,7 @@ import { buildRemediationPlan } from "../services/remediation-plan";
6767import { explainScoreBreakdown } from "../services/score-breakdown" ;
6868import { loadOrComputeIssueQualityResponse } from "../services/issue-quality" ;
6969import { loadOrComputeBurdenForecastResponse } from "../services/burden-forecast" ;
70+ import { buildFederatedQueueIndex , FEDERATED_QUEUE_INDEX_MAX_LIMIT } from "../services/queue-federation" ;
7071import { buildMcpClientTelemetry } from "../services/client-telemetry" ;
7172import { loadOrComputeRepoOutcomePatternsResponse } from "../services/repo-outcome-patterns" ;
7273import { buildRepoOutcomeCalibration , outcomeCalibrationSummary } from "../services/outcome-calibration" ;
@@ -158,6 +159,14 @@ const fleetAnalyticsOutputSchema = {
158159 outliers : z . array ( z . unknown ( ) ) . optional ( ) ,
159160} ;
160161
162+ const queueHealthFederationOutputSchema = {
163+ generatedAt : z . string ( ) . optional ( ) ,
164+ repoCount : z . number ( ) . optional ( ) ,
165+ limitApplied : z . number ( ) . optional ( ) ,
166+ source : z . enum ( [ "snapshot" , "computed" ] ) . optional ( ) ,
167+ entries : z . array ( z . unknown ( ) ) . optional ( ) ,
168+ } ;
169+
161170const loginShape = {
162171 login : z . string ( ) . min ( 1 ) ,
163172} ;
@@ -1050,6 +1059,16 @@ export class GittensoryMcp {
10501059 async ( input ) => this . toolResult ( await this . getBurdenForecast ( input ) ) ,
10511060 ) ;
10521061
1062+ server . registerTool (
1063+ "gittensory_queue_health_federation" ,
1064+ {
1065+ description : "Return a ranked cross-repo queue pressure index showing the worst-burden registered repos. Operator-only." ,
1066+ inputSchema : { limit : z . number ( ) . int ( ) . min ( 1 ) . max ( FEDERATED_QUEUE_INDEX_MAX_LIMIT ) . optional ( ) } ,
1067+ outputSchema : queueHealthFederationOutputSchema ,
1068+ } ,
1069+ async ( input ) => this . toolResult ( await this . getQueueHealthFederation ( input . limit ) ) ,
1070+ ) ;
1071+
10531072 server . registerTool (
10541073 "gittensory_get_repo_outcome_patterns" ,
10551074 {
@@ -1813,6 +1832,22 @@ export class GittensoryMcp {
18131832 } ;
18141833 }
18151834
1835+ private async getQueueHealthFederation ( limit ?: number ) : Promise < ToolPayload > {
1836+ if ( this . identity . kind !== "session" ) {
1837+ throw new Error ( "Forbidden: gittensory_queue_health_federation requires operator role." ) ;
1838+ }
1839+ const summary = await loadControlPanelRoleSummary ( this . env , this . identity . actor ) ;
1840+ if ( ! summary . roles . includes ( "operator" ) ) {
1841+ throw new Error ( "Forbidden: gittensory_queue_health_federation requires operator role." ) ;
1842+ }
1843+ const index = await buildFederatedQueueIndex ( this . env , limit ) ;
1844+ const criticalCount = index . entries . filter ( ( entry ) => entry . level === "critical" || entry . level === "high" ) . length ;
1845+ return {
1846+ summary : `Cross-repo queue pressure index: ${ index . repoCount } repo(s) ranked, ${ criticalCount } at critical/high burden.` ,
1847+ data : index as unknown as Record < string , unknown > ,
1848+ } ;
1849+ }
1850+
18161851 private async getIssueQuality ( input : { owner : string ; repo : string } ) : Promise < ToolPayload > {
18171852 const fullName = `${ input . owner } /${ input . repo } ` ;
18181853 if ( ! ( await this . canAccessRepo ( fullName ) ) ) {
0 commit comments