Compare commits

..

4 Commits

Author SHA1 Message Date
43e944e82f Expose grounded Coach strengths
All checks were successful
Tests / Tests (pull_request) Successful in 40s
2026-07-23 11:53:03 -07:00
d6cc81ef9f Add multi-signal coach decision fields 2026-07-23 11:53:03 -07:00
5d775eac70 Expose Session Coach agent summary 2026-07-23 11:53:03 -07:00
b810907f10 Merge pull request 'Add getUploadLinks batch mutation (schema + operation)' (#309) from dean/batch-upload-links-gql into master
Reviewed-on: #309
2026-07-23 07:50:57 +00:00
3 changed files with 166 additions and 0 deletions

View File

@@ -3595,12 +3595,21 @@ export type SerializedShotPathsGql = {
b64EncodedBuffer?: Maybe<Scalars["String"]["output"]>; b64EncodedBuffer?: Maybe<Scalars["String"]["output"]>;
}; };
export type SessionCoachBaselineGql = {
__typename?: "SessionCoachBaselineGQL";
attemptCount: Scalars["Int"]["output"];
madeCount: Scalars["Int"]["output"];
makePercentage: Scalars["Float"]["output"];
sessionCount: Scalars["Int"]["output"];
};
export enum SessionCoachCandidateFamilyEnum { export enum SessionCoachCandidateFamilyEnum {
Aiming = "AIMING", Aiming = "AIMING",
BackCut = "BACK_CUT", BackCut = "BACK_CUT",
CueToObjectDistance = "CUE_TO_OBJECT_DISTANCE", CueToObjectDistance = "CUE_TO_OBJECT_DISTANCE",
CutAngle = "CUT_ANGLE", CutAngle = "CUT_ANGLE",
ObjectToPocketDistance = "OBJECT_TO_POCKET_DISTANCE", ObjectToPocketDistance = "OBJECT_TO_POCKET_DISTANCE",
Overall = "OVERALL",
Spin = "SPIN", Spin = "SPIN",
} }
@@ -3620,8 +3629,11 @@ export type SessionCoachCandidateGql = {
}; };
export enum SessionCoachCandidateKindEnum { export enum SessionCoachCandidateKindEnum {
BaselineComparison = "BASELINE_COMPARISON",
DirectionalMiss = "DIRECTIONAL_MISS", DirectionalMiss = "DIRECTIONAL_MISS",
OutcomePattern = "OUTCOME_PATTERN", OutcomePattern = "OUTCOME_PATTERN",
SessionStreak = "SESSION_STREAK",
StrengthPattern = "STRENGTH_PATTERN",
UsagePattern = "USAGE_PATTERN", UsagePattern = "USAGE_PATTERN",
} }
@@ -3630,16 +3642,26 @@ export type SessionCoachDecisionGql = {
body?: Maybe<Scalars["String"]["output"]>; body?: Maybe<Scalars["String"]["output"]>;
drillId?: Maybe<Scalars["String"]["output"]>; drillId?: Maybe<Scalars["String"]["output"]>;
drillReason?: Maybe<Scalars["String"]["output"]>; drillReason?: Maybe<Scalars["String"]["output"]>;
positiveBody?: Maybe<Scalars["String"]["output"]>;
positiveTitle?: Maybe<Scalars["String"]["output"]>;
practiceAttemptCount?: Maybe<Scalars["Int"]["output"]>; practiceAttemptCount?: Maybe<Scalars["Int"]["output"]>;
practiceTarget?: Maybe<Scalars["String"]["output"]>; practiceTarget?: Maybe<Scalars["String"]["output"]>;
selectedCandidateId?: Maybe<Scalars["ID"]["output"]>; selectedCandidateId?: Maybe<Scalars["ID"]["output"]>;
selectedPositiveCandidateId?: Maybe<Scalars["ID"]["output"]>;
sessionSummary?: Maybe<Scalars["String"]["output"]>;
suggestedAction?: Maybe<Scalars["String"]["output"]>; suggestedAction?: Maybe<Scalars["String"]["output"]>;
supportingCandidateIds: Array<Scalars["ID"]["output"]>;
supportingShotIds: Array<Scalars["Int"]["output"]>;
title?: Maybe<Scalars["String"]["output"]>; title?: Maybe<Scalars["String"]["output"]>;
}; };
export type SessionCoachEvidenceGql = { export type SessionCoachEvidenceGql = {
__typename?: "SessionCoachEvidenceGQL"; __typename?: "SessionCoachEvidenceGQL";
attemptCount: Scalars["Int"]["output"]; attemptCount: Scalars["Int"]["output"];
baselineAttemptCount: Scalars["Int"]["output"];
baselineMadeCount: Scalars["Int"]["output"];
baselineMakePercentage?: Maybe<Scalars["Float"]["output"]>;
baselineSessionCount: Scalars["Int"]["output"];
bucketKey: Scalars["String"]["output"]; bucketKey: Scalars["String"]["output"];
bucketLabel: Scalars["String"]["output"]; bucketLabel: Scalars["String"]["output"];
comparisonAttemptCount: Scalars["Int"]["output"]; comparisonAttemptCount: Scalars["Int"]["output"];
@@ -3661,12 +3683,15 @@ export type SessionCoachGql = {
candidates: Array<SessionCoachCandidateGql>; candidates: Array<SessionCoachCandidateGql>;
generatedAt: Scalars["DateTime"]["output"]; generatedAt: Scalars["DateTime"]["output"];
ineligibilityReason?: Maybe<SessionCoachIneligibilityReasonEnum>; ineligibilityReason?: Maybe<SessionCoachIneligibilityReasonEnum>;
longestMakeStreak: Scalars["Int"]["output"];
madeCount: Scalars["Int"]["output"]; madeCount: Scalars["Int"]["output"];
makePercentage?: Maybe<Scalars["Float"]["output"]>; makePercentage?: Maybe<Scalars["Float"]["output"]>;
missedCount: Scalars["Int"]["output"]; missedCount: Scalars["Int"]["output"];
positiveCandidates: Array<SessionCoachCandidateGql>;
primaryCandidate?: Maybe<SessionCoachCandidateGql>; primaryCandidate?: Maybe<SessionCoachCandidateGql>;
processingId?: Maybe<Scalars["Int"]["output"]>; processingId?: Maybe<Scalars["Int"]["output"]>;
processingStatus?: Maybe<Scalars["String"]["output"]>; processingStatus?: Maybe<Scalars["String"]["output"]>;
recentBaseline?: Maybe<SessionCoachBaselineGql>;
shotCount: Scalars["Int"]["output"]; shotCount: Scalars["Int"]["output"];
state: SessionCoachStateEnum; state: SessionCoachStateEnum;
summary?: Maybe<Scalars["String"]["output"]>; summary?: Maybe<Scalars["String"]["output"]>;
@@ -3692,6 +3717,7 @@ export type SessionCoachGenerationDiagnosticsGql = {
promptVersion: Scalars["String"]["output"]; promptVersion: Scalars["String"]["output"];
providerKey: Scalars["String"]["output"]; providerKey: Scalars["String"]["output"];
startedAt?: Maybe<Scalars["DateTime"]["output"]>; startedAt?: Maybe<Scalars["DateTime"]["output"]>;
synthesisRationale?: Maybe<Scalars["String"]["output"]>;
updatedAt: Scalars["DateTime"]["output"]; updatedAt: Scalars["DateTime"]["output"];
}; };
@@ -7007,6 +7033,46 @@ export type GetSessionCoachQuery = {
unknownOutcomeCount: number; unknownOutcomeCount: number;
analyzedShotCount: number; analyzedShotCount: number;
makePercentage?: number | null; makePercentage?: number | null;
longestMakeStreak: number;
recentBaseline?: {
__typename?: "SessionCoachBaselineGQL";
sessionCount: number;
attemptCount: number;
madeCount: number;
makePercentage: number;
} | null;
positiveCandidates: Array<{
__typename?: "SessionCoachCandidateGQL";
id: string;
rank: number;
family: SessionCoachCandidateFamilyEnum;
kind: SessionCoachCandidateKindEnum;
title: string;
body: string;
action: string;
supportingShotIds: Array<number>;
drillId?: string | null;
limitations: Array<string>;
evidence: {
__typename?: "SessionCoachEvidenceGQL";
bucketKey: string;
bucketLabel: string;
attemptCount: number;
madeCount: number;
missedCount: number;
makePercentage: number;
comparisonAttemptCount: number;
comparisonMadeCount: number;
comparisonMakePercentage?: number | null;
patternShotCount: number;
score: number;
rankReason: string;
baselineSessionCount: number;
baselineAttemptCount: number;
baselineMadeCount: number;
baselineMakePercentage?: number | null;
};
}>;
primaryCandidate?: { primaryCandidate?: {
__typename?: "SessionCoachCandidateGQL"; __typename?: "SessionCoachCandidateGQL";
id: string; id: string;
@@ -7033,6 +7099,10 @@ export type GetSessionCoachQuery = {
patternShotCount: number; patternShotCount: number;
score: number; score: number;
rankReason: string; rankReason: string;
baselineSessionCount: number;
baselineAttemptCount: number;
baselineMadeCount: number;
baselineMakePercentage?: number | null;
}; };
} | null; } | null;
candidates: Array<{ candidates: Array<{
@@ -7061,6 +7131,10 @@ export type GetSessionCoachQuery = {
patternShotCount: number; patternShotCount: number;
score: number; score: number;
rankReason: string; rankReason: string;
baselineSessionCount: number;
baselineAttemptCount: number;
baselineMadeCount: number;
baselineMakePercentage?: number | null;
}; };
}>; }>;
agentGeneration?: { agentGeneration?: {
@@ -7071,7 +7145,13 @@ export type GetSessionCoachQuery = {
completedAt?: any | null; completedAt?: any | null;
decision?: { decision?: {
__typename?: "SessionCoachDecisionGQL"; __typename?: "SessionCoachDecisionGQL";
selectedPositiveCandidateId?: string | null;
positiveTitle?: string | null;
positiveBody?: string | null;
selectedCandidateId?: string | null; selectedCandidateId?: string | null;
supportingCandidateIds: Array<string>;
supportingShotIds: Array<number>;
sessionSummary?: string | null;
title?: string | null; title?: string | null;
body?: string | null; body?: string | null;
suggestedAction?: string | null; suggestedAction?: string | null;
@@ -7099,6 +7179,7 @@ export type GetSessionCoachQuery = {
startedAt?: any | null; startedAt?: any | null;
lastEnqueuedAt?: any | null; lastEnqueuedAt?: any | null;
abstentionReason?: string | null; abstentionReason?: string | null;
synthesisRationale?: string | null;
} | null; } | null;
} | null; } | null;
}; };
@@ -7121,7 +7202,13 @@ export type RequestSessionCoachGenerationMutation = {
completedAt?: any | null; completedAt?: any | null;
decision?: { decision?: {
__typename?: "SessionCoachDecisionGQL"; __typename?: "SessionCoachDecisionGQL";
selectedPositiveCandidateId?: string | null;
positiveTitle?: string | null;
positiveBody?: string | null;
selectedCandidateId?: string | null; selectedCandidateId?: string | null;
supportingCandidateIds: Array<string>;
supportingShotIds: Array<number>;
sessionSummary?: string | null;
title?: string | null; title?: string | null;
body?: string | null; body?: string | null;
suggestedAction?: string | null; suggestedAction?: string | null;
@@ -7149,6 +7236,7 @@ export type RequestSessionCoachGenerationMutation = {
startedAt?: any | null; startedAt?: any | null;
lastEnqueuedAt?: any | null; lastEnqueuedAt?: any | null;
abstentionReason?: string | null; abstentionReason?: string | null;
synthesisRationale?: string | null;
} | null; } | null;
} | null; } | null;
}; };
@@ -7180,6 +7268,10 @@ export type SessionCoachCandidateFieldsFragment = {
patternShotCount: number; patternShotCount: number;
score: number; score: number;
rankReason: string; rankReason: string;
baselineSessionCount: number;
baselineAttemptCount: number;
baselineMadeCount: number;
baselineMakePercentage?: number | null;
}; };
}; };
@@ -7191,7 +7283,13 @@ export type SessionCoachGenerationFieldsFragment = {
completedAt?: any | null; completedAt?: any | null;
decision?: { decision?: {
__typename?: "SessionCoachDecisionGQL"; __typename?: "SessionCoachDecisionGQL";
selectedPositiveCandidateId?: string | null;
positiveTitle?: string | null;
positiveBody?: string | null;
selectedCandidateId?: string | null; selectedCandidateId?: string | null;
supportingCandidateIds: Array<string>;
supportingShotIds: Array<number>;
sessionSummary?: string | null;
title?: string | null; title?: string | null;
body?: string | null; body?: string | null;
suggestedAction?: string | null; suggestedAction?: string | null;
@@ -7219,6 +7317,7 @@ export type SessionCoachGenerationFieldsFragment = {
startedAt?: any | null; startedAt?: any | null;
lastEnqueuedAt?: any | null; lastEnqueuedAt?: any | null;
abstentionReason?: string | null; abstentionReason?: string | null;
synthesisRationale?: string | null;
} | null; } | null;
}; };
@@ -9764,6 +9863,10 @@ export const SessionCoachCandidateFieldsFragmentDoc = gql`
patternShotCount patternShotCount
score score
rankReason rankReason
baselineSessionCount
baselineAttemptCount
baselineMadeCount
baselineMakePercentage
} }
} }
`; `;
@@ -9774,7 +9877,13 @@ export const SessionCoachGenerationFieldsFragmentDoc = gql`
createdAt createdAt
completedAt completedAt
decision { decision {
selectedPositiveCandidateId
positiveTitle
positiveBody
selectedCandidateId selectedCandidateId
supportingCandidateIds
supportingShotIds
sessionSummary
title title
body body
suggestedAction suggestedAction
@@ -9801,6 +9910,7 @@ export const SessionCoachGenerationFieldsFragmentDoc = gql`
startedAt startedAt
lastEnqueuedAt lastEnqueuedAt
abstentionReason abstentionReason
synthesisRationale
} }
} }
`; `;
@@ -15433,6 +15543,16 @@ export const GetSessionCoachDocument = gql`
unknownOutcomeCount unknownOutcomeCount
analyzedShotCount analyzedShotCount
makePercentage makePercentage
longestMakeStreak
recentBaseline {
sessionCount
attemptCount
madeCount
makePercentage
}
positiveCandidates {
...SessionCoachCandidateFields
}
primaryCandidate { primaryCandidate {
...SessionCoachCandidateFields ...SessionCoachCandidateFields
} }

View File

@@ -14,6 +14,16 @@ query GetSessionCoach($videoId: Int!) {
unknownOutcomeCount unknownOutcomeCount
analyzedShotCount analyzedShotCount
makePercentage makePercentage
longestMakeStreak
recentBaseline {
sessionCount
attemptCount
madeCount
makePercentage
}
positiveCandidates {
...SessionCoachCandidateFields
}
primaryCandidate { primaryCandidate {
...SessionCoachCandidateFields ...SessionCoachCandidateFields
} }
@@ -59,6 +69,10 @@ fragment SessionCoachCandidateFields on SessionCoachCandidateGQL {
patternShotCount patternShotCount
score score
rankReason rankReason
baselineSessionCount
baselineAttemptCount
baselineMadeCount
baselineMakePercentage
} }
} }
@@ -68,7 +82,13 @@ fragment SessionCoachGenerationFields on SessionCoachGenerationGQL {
createdAt createdAt
completedAt completedAt
decision { decision {
selectedPositiveCandidateId
positiveTitle
positiveBody
selectedCandidateId selectedCandidateId
supportingCandidateIds
supportingShotIds
sessionSummary
title title
body body
suggestedAction suggestedAction
@@ -95,5 +115,6 @@ fragment SessionCoachGenerationFields on SessionCoachGenerationGQL {
startedAt startedAt
lastEnqueuedAt lastEnqueuedAt
abstentionReason abstentionReason
synthesisRationale
} }
} }

View File

@@ -1312,7 +1312,15 @@ type SerializedShotPathsGQL {
b64EncodedBuffer: String b64EncodedBuffer: String
} }
type SessionCoachBaselineGQL {
sessionCount: Int!
attemptCount: Int!
madeCount: Int!
makePercentage: Float!
}
enum SessionCoachCandidateFamilyEnum { enum SessionCoachCandidateFamilyEnum {
OVERALL
AIMING AIMING
CUT_ANGLE CUT_ANGLE
SPIN SPIN
@@ -1336,13 +1344,22 @@ type SessionCoachCandidateGQL {
} }
enum SessionCoachCandidateKindEnum { enum SessionCoachCandidateKindEnum {
BASELINE_COMPARISON
SESSION_STREAK
STRENGTH_PATTERN
DIRECTIONAL_MISS DIRECTIONAL_MISS
OUTCOME_PATTERN OUTCOME_PATTERN
USAGE_PATTERN USAGE_PATTERN
} }
type SessionCoachDecisionGQL { type SessionCoachDecisionGQL {
selectedPositiveCandidateId: ID
positiveTitle: String
positiveBody: String
selectedCandidateId: ID selectedCandidateId: ID
supportingCandidateIds: [ID!]!
supportingShotIds: [Int!]!
sessionSummary: String
title: String title: String
body: String body: String
suggestedAction: String suggestedAction: String
@@ -1365,6 +1382,10 @@ type SessionCoachEvidenceGQL {
patternShotCount: Int! patternShotCount: Int!
score: Float! score: Float!
rankReason: String! rankReason: String!
baselineSessionCount: Int!
baselineAttemptCount: Int!
baselineMadeCount: Int!
baselineMakePercentage: Float
} }
type SessionCoachGQL { type SessionCoachGQL {
@@ -1382,6 +1403,9 @@ type SessionCoachGQL {
unknownOutcomeCount: Int! unknownOutcomeCount: Int!
analyzedShotCount: Int! analyzedShotCount: Int!
makePercentage: Float makePercentage: Float
longestMakeStreak: Int!
recentBaseline: SessionCoachBaselineGQL
positiveCandidates: [SessionCoachCandidateGQL!]!
primaryCandidate: SessionCoachCandidateGQL primaryCandidate: SessionCoachCandidateGQL
candidates: [SessionCoachCandidateGQL!]! candidates: [SessionCoachCandidateGQL!]!
agentGeneration: SessionCoachGenerationGQL agentGeneration: SessionCoachGenerationGQL
@@ -1405,6 +1429,7 @@ type SessionCoachGenerationDiagnosticsGQL {
startedAt: DateTime startedAt: DateTime
lastEnqueuedAt: DateTime lastEnqueuedAt: DateTime
abstentionReason: String abstentionReason: String
synthesisRationale: String
} }
type SessionCoachGenerationGQL { type SessionCoachGenerationGQL {