회기 무발화 0턴 분리, 자기예측 락 불변식 및 TDD 회귀 검증 완료
Some checks failed
API contract / OpenAPI type drift (push) Failing after 3m27s

This commit is contained in:
Yun Chan 2026-09-08 23:28:06 +09:00
parent a479db7a5a
commit a0311c5957
100 changed files with 4884 additions and 11210 deletions

View file

@ -0,0 +1,35 @@
"""브라우저용 세션 projection이 공유하는 순수 도우미."""
from __future__ import annotations
from datetime import datetime, timezone
from typing import cast
from .services import state_machine
from .stage_contract import StageLabel, stage_label as _normalize_stage_label
from .store import InProcSession, TurnRecord
LEARNER_VISIBLE_AI_ROLE = "counselor"
# 전 주기(라포→정리) 기준 라포 만점: 마지막 전이 임계(개입→정리)를 100으로 본다.
_FULL_CYCLE_RAPPORT = max(state_machine.STAGE_ADVANCE_RAPPORT.values())
def stage_label(stage: object) -> StageLabel:
return cast(StageLabel, _normalize_stage_label(stage))
def iso(ts: float | None) -> str | None:
if ts is None:
return None
return datetime.fromtimestamp(ts, tz=timezone.utc).isoformat(timespec="seconds")
def learner_visible_turns(sess: InProcSession) -> list[TurnRecord]:
return sess.turns_visible_to(LEARNER_VISIBLE_AI_ROLE)
def _rapport_percent(credit: float) -> int:
if _FULL_CYCLE_RAPPORT <= 0:
return 0
return max(0, min(100, int(round(float(credit or 0.0) / _FULL_CYCLE_RAPPORT * 100))))