interface SotDocument { name: string; filename: string; exists: boolean; content?: string; sizeBytes?: number; } interface LessonArtifactSummary { lessonId: string; artifactsCount: number; isComplete: boolean; artifacts: string[]; } interface ProjectStatusReport { projectId: string; sotReadiness: SotDocument[]; lessons: LessonArtifactSummary[]; completedCount: number; totalLessons: number; progressPercent: number; rawMarkdownReport: string; } interface SmartResumeContext { projectId: string; currentPhase: number; nextLessonId?: string; nextLessonTitle?: string; recommendedAction: string; rawMarkdownReport: string; } interface QualityAuditReport { projectId: string; pedagogy5EPass: boolean; bloomAlignmentPass: boolean; strictConcurrencyPass: boolean; alignmentMatrixPass: boolean; score: number; details: string[]; rawMarkdownReport: string; } type ArtifactLifecycleState = 'pending' | 'queued' | 'generating' | 'awaiting_review' | 'approved' | 'rejected' | 'completed' | 'cancelled'; interface ReviewRecord { decision: 'APPROVED' | 'REJECTED' | 'NEEDS_REVISION'; reviewedBy: 'human' | '@agent-as-judge' | '@heuristic-linter'; reviewedAt: string; score?: number; feedback?: string; critique?: string; contentHash?: string; } interface ArtifactLifecycleInfo { state: ArtifactLifecycleState; generatedAt?: string; contentHash?: string; review?: ReviewRecord | null; } interface TaskLifecycleState { taskId: string; artifacts: Record; } interface PipelineState { projectId: string; updatedAt: string; tasks: Record>; } interface ICurriculumStorage { /** Check if a project exists */ projectExists(projectId: string): Promise; /** Read SOT document content or return null if not found */ readSotDocument(projectId: string, filename: string): Promise; /** List all SOT documents with existence status */ listSotDocuments(projectId: string): Promise; /** Read an arbitrary artifact file by relative path */ readArtifact(projectId: string, relPath: string): Promise; /** Save an artifact file to persistent storage */ saveArtifact(projectId: string, relPath: string, content: string): Promise; /** List all lessons in the project with their generated artifacts */ listLessons(projectId: string): Promise; /** Get complete structured project status report */ getProjectStatus(projectId: string): Promise; /** Get durable pipeline lifecycle state */ getPipelineState(projectId: string): Promise; /** Save durable pipeline lifecycle state */ savePipelineState(projectId: string, state: PipelineState): Promise; /** Update review or state for a single artifact in pipeline state */ updateArtifactState(projectId: string, taskId: string, artifactType: string, update: Partial): Promise; /** * Delete a single artifact by relative path (best-effort). * * Split-brain root-cause fix (2026-09-14): Force SOT regeneration only * cleared the local disk copy, but the storage backend (Supabase) kept the * OLD plan/expositions. Subsequent readers resolved the backend first and * saw the stale generation while disk held the fresh one — the KX/plan * split-brain. Producers now cascade the purge to the backend through this * method. Implementations may ignore unsupported paths silently (no-throw). */ deleteArtifact?(projectId: string, relPath: string): Promise; } export type { ArtifactLifecycleState as A, ICurriculumStorage as I, LessonArtifactSummary as L, ProjectStatusReport as P, QualityAuditReport as Q, ReviewRecord as R, SmartResumeContext as S, TaskLifecycleState as T, SotDocument as a, ArtifactLifecycleInfo as b, PipelineState as c };