회기 무발화 0턴 분리, 자기예측 락 불변식 및 TDD 회귀 검증 완료
Some checks failed
API contract / OpenAPI type drift (push) Failing after 3m27s
Some checks failed
API contract / OpenAPI type drift (push) Failing after 3m27s
This commit is contained in:
parent
a479db7a5a
commit
a0311c5957
100 changed files with 4884 additions and 11210 deletions
35
apps/api/app/session_projection.py
Normal file
35
apps/api/app/session_projection.py
Normal 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))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue