G0~G8 성과·동맹 측정 OS 작업 일괄 고정
8월 7일까지 워킹트리에만 남아 있던 미커밋 작업을 커밋한다. 여러 사본 폴더(worktree·clone)에 흩어져 있던 중간 스냅샷을 정리하기 전에 원본을 git 이력으로 고정하는 것이 목적이다. - contracts/routes/services: measurement, outcome_trajectory, rupture_repair, deliberate_practice, calibration_transfer, supervision_research, multimodal_alliance, continuous_improvement 계열 신규 모듈과 테스트 - infra/db/init: 07~16 마이그레이션(측정 기반~calibration transfer 실행) - apps/web: 세션 리뷰 카드·관리 화면·E2E 스펙 추가 - docs/ops: G0~G8 라이브 통합·배포·롤백 증거 문서와 evidence JSON/PNG - scripts: smoke·ledger·릴리스 에이전트·NAS 프리뷰 운영 스크립트 engine.public 로그 .bak과 apps/web/test-results 산출물은 커밋에서 제외했다.
This commit is contained in:
parent
93dd8f82d7
commit
16e791e044
390 changed files with 243188 additions and 499 deletions
120
apps/web/src/pages/session-review/calibrationTransferApi.ts
Normal file
120
apps/web/src/pages/session-review/calibrationTransferApi.ts
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
import { api, supplementalApi } from "../../lib/api";
|
||||
import type { components } from "../../lib/api.gen";
|
||||
|
||||
type ApiSchema<Name extends keyof components["schemas"]> =
|
||||
components["schemas"][Name];
|
||||
|
||||
/** G5 wire DTO는 생성된 FastAPI OpenAPI 계약을 그대로 사용한다. */
|
||||
export type CalibrationConfidenceInterval = ApiSchema<"ConfidenceInterval">;
|
||||
export type CalibrationPair = ApiSchema<"CalibrationPair">;
|
||||
export type CompetencyCalibrationAssessment =
|
||||
ApiSchema<"CompetencyCalibrationAssessment">;
|
||||
export type MetacognitivePrescription = ApiSchema<"MetacognitivePrescription">;
|
||||
export type PredictionRevisionItem = ApiSchema<"PredictionRevisionItem">;
|
||||
export type PredictionLockItem = ApiSchema<"PredictionLockItem">;
|
||||
export type PerformanceObservationItem = ApiSchema<"PerformanceObservationItem">;
|
||||
export type PredictionHistoryItem = ApiSchema<"PredictionHistoryItem">;
|
||||
export type CalibrationAssessmentItem = ApiSchema<"CalibrationAssessmentItem">;
|
||||
export type TransferAssessment = ApiSchema<"TransferAssessment">;
|
||||
export type TransferTrialItem = ApiSchema<"TransferTrialItem">;
|
||||
export type TransferAssessmentItem = ApiSchema<"TransferAssessmentItem">;
|
||||
export type SyntheticSubgroupResult = ApiSchema<"SyntheticSubgroupResult">;
|
||||
export type SubgroupDriftReport = ApiSchema<"SubgroupDriftReport">;
|
||||
export type DriftReportItem = ApiSchema<"DriftReportItem">;
|
||||
export type TransferSuiteItem = ApiSchema<"TransferSuiteItem">;
|
||||
export type TeacherReviewItem = ApiSchema<"TeacherReviewItem">;
|
||||
export type CalibrationTransferReadModelResponse =
|
||||
ApiSchema<"CalibrationTransferReadModelResponse">;
|
||||
export type PredictionRevisionRequest = ApiSchema<"PredictionRevisionRequest">;
|
||||
export type PredictionRevisionResponse = ApiSchema<"PredictionRevisionResponse">;
|
||||
export type PredictionLockRequest = ApiSchema<"PredictionLockRequest">;
|
||||
export type PredictionLockResponse = ApiSchema<"PredictionLockResponse">;
|
||||
export type TeacherCorrectionResponse = ApiSchema<"TeacherReviewResponse">;
|
||||
export type ActualTransferAssessment = ApiSchema<"ActualTransferAssessment">;
|
||||
export type ActualTransferExecutionRequest =
|
||||
ApiSchema<"ActualTransferExecutionRequest">;
|
||||
export type ActualTransferExecutionResponse =
|
||||
ApiSchema<"ActualTransferExecutionResponse">;
|
||||
|
||||
export type CalibrationBias = CompetencyCalibrationAssessment["bias"];
|
||||
export type CalibrationImprovement =
|
||||
CompetencyCalibrationAssessment["improvement"];
|
||||
export type PerformanceStatus = PerformanceObservationItem["status"];
|
||||
export type RelationshipStyle = TransferTrialItem["relationship_style"];
|
||||
export type DriftStatus = SubgroupDriftReport["status"];
|
||||
|
||||
/** 교수자 UI는 원판정 쓰기를 열지 않고 append-only 교정만 허용한다. */
|
||||
export type TeacherCorrectionRequest = Omit<
|
||||
ApiSchema<"TeacherReviewRequest">,
|
||||
"disposition" | "correction_payload"
|
||||
> & {
|
||||
disposition: "corrected";
|
||||
correction_payload: { teacher_note: string };
|
||||
};
|
||||
|
||||
interface TeacherSessionRef {
|
||||
session_id: string;
|
||||
learner_id: string;
|
||||
}
|
||||
|
||||
interface TeacherDashboardLookup {
|
||||
pending_reviews?: TeacherSessionRef[];
|
||||
recent_sessions?: TeacherSessionRef[];
|
||||
}
|
||||
|
||||
function learnerPath(learnerId?: string): string {
|
||||
return learnerId
|
||||
? `/calibration/learners/${encodeURIComponent(learnerId)}`
|
||||
: "/calibration/learners/me";
|
||||
}
|
||||
|
||||
export class CalibrationLearnerContextError extends Error {
|
||||
constructor() {
|
||||
super("이 회기의 학습자 캘리브레이션 원장을 찾지 못했습니다.");
|
||||
this.name = "CalibrationLearnerContextError";
|
||||
}
|
||||
}
|
||||
|
||||
export const calibrationTransferApi = {
|
||||
getForLearner: (signal?: AbortSignal) =>
|
||||
supplementalApi.get<CalibrationTransferReadModelResponse>(learnerPath(), {
|
||||
signal,
|
||||
}),
|
||||
|
||||
getForTeacherSession: async (sessionId: string, signal?: AbortSignal) => {
|
||||
const dashboard = await supplementalApi.get<TeacherDashboardLookup>(
|
||||
"/teacher/dashboard",
|
||||
{ signal },
|
||||
);
|
||||
const session = [
|
||||
...(dashboard.pending_reviews ?? []),
|
||||
...(dashboard.recent_sessions ?? []),
|
||||
].find((item) => item.session_id === sessionId);
|
||||
if (!session) throw new CalibrationLearnerContextError();
|
||||
return supplementalApi.get<CalibrationTransferReadModelResponse>(
|
||||
learnerPath(session.learner_id),
|
||||
{ signal },
|
||||
);
|
||||
},
|
||||
|
||||
appendPredictionRevision: (body: PredictionRevisionRequest) =>
|
||||
api.post<PredictionRevisionResponse>(
|
||||
"/calibration/predictions/revisions",
|
||||
body,
|
||||
),
|
||||
|
||||
lockPrediction: (historyId: string, body: PredictionLockRequest) =>
|
||||
api.post<PredictionLockResponse>(
|
||||
`/calibration/predictions/${encodeURIComponent(historyId)}/lock`,
|
||||
body,
|
||||
),
|
||||
|
||||
appendTeacherCorrection: (body: TeacherCorrectionRequest) =>
|
||||
api.post<TeacherCorrectionResponse>("/calibration/reviews", body),
|
||||
|
||||
appendActualTransferExecution: (body: ActualTransferExecutionRequest) =>
|
||||
api.post<ActualTransferExecutionResponse>(
|
||||
"/calibration/transfer-executions",
|
||||
body,
|
||||
),
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue