2026-04-26 15:45:56 +09:00
|
|
|
# Workflow Contracts
|
|
|
|
|
|
|
|
|
|
## Purpose
|
|
|
|
|
|
|
|
|
|
LLM workflow outputs that affect product state must be typed and inspectable.
|
|
|
|
|
The Go backend should call internalized workflow interfaces and then persist
|
|
|
|
|
validated results. Product state must not depend on parsing arbitrary prose.
|
|
|
|
|
|
|
|
|
|
These contracts are initial planning contracts. Field names may evolve during
|
|
|
|
|
implementation, but the responsibilities should remain stable.
|
|
|
|
|
|
|
|
|
|
## Shared Types
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"evidence_ref": {
|
|
|
|
|
"kind": "answer|grading|source|session|asset",
|
|
|
|
|
"id": "string",
|
|
|
|
|
"quote": "string",
|
|
|
|
|
"confidence": 0.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"concept_ref": {
|
|
|
|
|
"id": "string",
|
|
|
|
|
"label": "string",
|
|
|
|
|
"track": "backend-developer"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## DiagnosticResult
|
|
|
|
|
|
|
|
|
|
Produced by `diagnose_job_seeker`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"user_id": "string",
|
|
|
|
|
"track": "backend-developer",
|
|
|
|
|
"target_role": "junior-backend-developer",
|
|
|
|
|
"stack": ["go", "postgres"],
|
|
|
|
|
"initial_readiness": "unknown|fragile|improving|interview_ready|strong_signal",
|
|
|
|
|
"concept_findings": [
|
|
|
|
|
{
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"readiness": "unknown|fragile|improving|interview_ready|strong_signal",
|
|
|
|
|
"reason": "string",
|
|
|
|
|
"evidence": ["evidence_ref"]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"recommended_next_concepts": ["concept_ref"]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## GradedAnswer
|
|
|
|
|
|
|
|
|
|
Produced by `grade_interview_answer`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
2026-04-26 16:34:52 +09:00
|
|
|
"user_id": "string",
|
2026-04-26 15:45:56 +09:00
|
|
|
"answer_id": "string",
|
|
|
|
|
"question_id": "string",
|
|
|
|
|
"concepts": ["concept_ref"],
|
|
|
|
|
"scores": {
|
|
|
|
|
"correctness": 0,
|
|
|
|
|
"depth": 0,
|
|
|
|
|
"communication": 0,
|
|
|
|
|
"production_judgment": 0
|
|
|
|
|
},
|
|
|
|
|
"overall": "miss|partial|solid|strong",
|
|
|
|
|
"strengths": ["string"],
|
|
|
|
|
"gaps": ["string"],
|
2026-04-26 16:24:35 +09:00
|
|
|
"evidence": ["evidence_ref"],
|
2026-04-26 15:45:56 +09:00
|
|
|
"misconception_candidates": [
|
|
|
|
|
{
|
|
|
|
|
"label": "string",
|
|
|
|
|
"description": "string",
|
|
|
|
|
"evidence": ["evidence_ref"],
|
|
|
|
|
"confidence": 0.0
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"follow_up": {
|
|
|
|
|
"needed": true,
|
|
|
|
|
"question": "string",
|
|
|
|
|
"purpose": "clarify|repair|stretch|pressure_test"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## MemoryUpdateCandidate
|
|
|
|
|
|
|
|
|
|
Produced by `extract_learning_memory`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"user_id": "string",
|
|
|
|
|
"source_answer_id": "string",
|
|
|
|
|
"updates": [
|
|
|
|
|
{
|
|
|
|
|
"kind": "concept_mastery|misconception|intervention|review_schedule",
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"proposed_state": "unknown|fragile|improving|interview_ready|strong_signal",
|
|
|
|
|
"summary": "string",
|
|
|
|
|
"evidence": ["evidence_ref"],
|
|
|
|
|
"confidence": 0.0,
|
|
|
|
|
"durability": "tentative|confirmed"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## NextChallenge
|
|
|
|
|
|
|
|
|
|
Produced by `select_next_challenge`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"user_id": "string",
|
|
|
|
|
"track": "backend-developer",
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"ladder_level": "define|tradeoffs|debug|design_constraints|interview_pressure",
|
|
|
|
|
"question": "string",
|
|
|
|
|
"rationale": "string",
|
|
|
|
|
"difficulty_action": "lower|hold|raise|recover",
|
|
|
|
|
"evidence": ["evidence_ref"]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## ReadinessUpdate
|
|
|
|
|
|
|
|
|
|
Produced by `update_readiness_map`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"user_id": "string",
|
|
|
|
|
"track": "backend-developer",
|
|
|
|
|
"concept_updates": [
|
|
|
|
|
{
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"previous": "unknown|fragile|improving|interview_ready|strong_signal",
|
|
|
|
|
"next": "unknown|fragile|improving|interview_ready|strong_signal",
|
|
|
|
|
"reason": "string",
|
|
|
|
|
"evidence": ["evidence_ref"]
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"unlocks": [
|
|
|
|
|
{
|
|
|
|
|
"kind": "boss_question|review_card|portfolio_entry",
|
|
|
|
|
"label": "string",
|
|
|
|
|
"reason": "string"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## OntologyGap
|
|
|
|
|
|
|
|
|
|
Produced by `detect_ontology_gaps`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"track": "backend-developer",
|
|
|
|
|
"missing_or_weak": [
|
|
|
|
|
{
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"gap_type": "missing_prerequisite|weak_evidence|outdated|needs_rubric",
|
|
|
|
|
"reason": "string",
|
|
|
|
|
"supporting_sources": ["evidence_ref"],
|
|
|
|
|
"proposed_action": "generate_candidate|request_source|human_review"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## TeachingAssetPrompt
|
|
|
|
|
|
|
|
|
|
Produced by `generate_teaching_asset_prompt`.
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"concept": "concept_ref",
|
|
|
|
|
"asset_type": "diagram|lesson_slice|worksheet|interview_card",
|
|
|
|
|
"prompt": "string",
|
|
|
|
|
"source_evidence": ["evidence_ref"],
|
|
|
|
|
"model_key": "gpt-image-v2",
|
|
|
|
|
"requires_model_id_verification": true,
|
|
|
|
|
"review_state": "candidate"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Validation Rules
|
|
|
|
|
|
|
|
|
|
- Required IDs must be non-empty.
|
|
|
|
|
- Any state-changing output must include evidence.
|
|
|
|
|
- Confidence values must be between 0 and 1.
|
|
|
|
|
- Generated or inferred content starts as `candidate` or `tentative`.
|
|
|
|
|
- `model_key` is a product config key; production code must verify the actual
|
|
|
|
|
provider model identifier before image calls.
|