package workflows import ( "context" "errors" "strings" ) var ErrNotImplemented = errors.New("workflow runner not implemented") type DiagnosticInput struct { UserID string Track string TargetRole string Stack []string } type Runner interface { DiagnoseJobSeeker(context.Context, DiagnosticInput) (DiagnosticResult, error) GradeInterviewAnswer(context.Context, GradeAnswerInput) (GradedAnswer, error) ExtractLearningMemory(context.Context, GradedAnswer) (MemoryUpdateCandidate, error) SelectNextChallenge(context.Context, NextChallengeInput) (NextChallenge, error) UpdateReadinessMap(context.Context, ReadinessUpdateInput) (ReadinessUpdate, error) } type GradeAnswerInput struct { UserID string QuestionID string AnswerID string AnswerText string Concepts []ConceptRef } type NextChallengeInput struct { UserID string Track string } type ReadinessUpdateInput struct { UserID string Track string } type StubRunner struct{} func NewStubRunner() StubRunner { return StubRunner{} } func (StubRunner) DiagnoseJobSeeker(context.Context, DiagnosticInput) (DiagnosticResult, error) { return DiagnosticResult{}, ErrNotImplemented } func (StubRunner) GradeInterviewAnswer(_ context.Context, input GradeAnswerInput) (GradedAnswer, error) { wordCount := len(strings.Fields(input.AnswerText)) overall := AnswerPartial if wordCount >= 18 { overall = AnswerSolid } if wordCount < 8 { overall = AnswerMiss } grade := GradedAnswer{ AnswerID: input.AnswerID, QuestionID: input.QuestionID, Concepts: append([]ConceptRef(nil), input.Concepts...), Scores: AnswerScores{ Correctness: scoreFromWords(wordCount, 8), Depth: scoreFromWords(wordCount, 14), Communication: scoreFromWords(wordCount, 10), ProductionJudgment: scoreFromWords(wordCount, 20), }, Overall: overall, Strengths: []string{"Answer was captured and evaluated through the typed workflow boundary."}, Gaps: []string{}, Evidence: []EvidenceRef{ { Kind: EvidenceAnswer, ID: input.AnswerID, Quote: input.AnswerText, Confidence: 1, }, }, FollowUp: FollowUpRecommendation{}, } if overall == AnswerMiss || overall == AnswerPartial { grade.Gaps = []string{"Answer needs more concrete reasoning and tradeoff discussion."} grade.FollowUp = FollowUpRecommendation{ Needed: true, Question: "Can you give a concrete production example and explain the tradeoff?", Purpose: FollowUpRepair, } } return grade, nil } func (StubRunner) ExtractLearningMemory(context.Context, GradedAnswer) (MemoryUpdateCandidate, error) { return MemoryUpdateCandidate{}, ErrNotImplemented } func (StubRunner) SelectNextChallenge(context.Context, NextChallengeInput) (NextChallenge, error) { return NextChallenge{}, ErrNotImplemented } func (StubRunner) UpdateReadinessMap(context.Context, ReadinessUpdateInput) (ReadinessUpdate, error) { return ReadinessUpdate{}, ErrNotImplemented } func scoreFromWords(wordCount int, target int) int { if wordCount >= target { return 4 } if wordCount >= target/2 { return 2 } return 1 }