feat: add diagnostic interview loop

This commit is contained in:
user
2026-04-26 16:24:35 +09:00
parent 0e232ff405
commit 4a4240fea2
21 changed files with 926 additions and 23 deletions

View File

@@ -3,6 +3,7 @@ package workflows
import (
"context"
"errors"
"strings"
)
var ErrNotImplemented = errors.New("workflow runner not implemented")
@@ -27,6 +28,7 @@ type GradeAnswerInput struct {
QuestionID string
AnswerID string
AnswerText string
Concepts []ConceptRef
}
type NextChallengeInput struct {
@@ -49,8 +51,49 @@ func (StubRunner) DiagnoseJobSeeker(context.Context, DiagnosticInput) (Diagnosti
return DiagnosticResult{}, ErrNotImplemented
}
func (StubRunner) GradeInterviewAnswer(context.Context, GradeAnswerInput) (GradedAnswer, error) {
return GradedAnswer{}, 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) {
@@ -64,3 +107,13 @@ func (StubRunner) SelectNextChallenge(context.Context, NextChallengeInput) (Next
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
}