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
|
|
@ -191,6 +191,79 @@ class SessionTurnPersistenceTest(unittest.IsolatedAsyncioTestCase):
|
|||
self.assertEqual(conn.insert_args[17], list(turn.visible_to))
|
||||
self.assertEqual(turn.turn_id, "00000000-0000-0000-0000-000000009999")
|
||||
|
||||
async def test_create_session_binds_goal_stages_as_jsonb_array(self) -> None:
|
||||
class FakeTransaction:
|
||||
async def __aenter__(self) -> None:
|
||||
return None
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb) -> None:
|
||||
return None
|
||||
|
||||
class FakeConn:
|
||||
def __init__(self) -> None:
|
||||
self.session_insert_args: tuple[object, ...] = ()
|
||||
|
||||
def transaction(self) -> FakeTransaction:
|
||||
return FakeTransaction()
|
||||
|
||||
async def fetchrow(self, query: str, *args: object) -> dict[str, object]:
|
||||
if "UPDATE app.case_profile" in query:
|
||||
return {"last_session_no": 2}
|
||||
if "INSERT INTO app.sessions" in query:
|
||||
self.session_insert_args = args
|
||||
return {
|
||||
"id": "00000000-0000-0000-0000-000000000301",
|
||||
"runtime_case_id": args[0],
|
||||
"case_id": args[1],
|
||||
"learner_id": args[2],
|
||||
"persona_code": args[5],
|
||||
"session_no": args[8],
|
||||
"theory_mode": args[9],
|
||||
"started_at": session_persistence.datetime.fromtimestamp(
|
||||
1_000.0, tz=session_persistence.timezone.utc
|
||||
),
|
||||
"ended_at": None,
|
||||
"prev_rapport_credit": args[10],
|
||||
}
|
||||
raise AssertionError(f"unexpected query: {query}")
|
||||
|
||||
async def execute(self, query: str, *args: object) -> str:
|
||||
self.assert_jsonb_object(query, args)
|
||||
return "INSERT 0 1"
|
||||
|
||||
@staticmethod
|
||||
def assert_jsonb_object(query: str, args: tuple[object, ...]) -> None:
|
||||
if "INSERT INTO app.session_state" in query:
|
||||
assert isinstance(args[8], dict)
|
||||
|
||||
conn = FakeConn()
|
||||
goals = ["라포", "탐색"]
|
||||
with (
|
||||
patch.object(session_persistence, "get_pool", return_value=object()),
|
||||
patch.object(
|
||||
session_persistence,
|
||||
"acquire",
|
||||
return_value=_AsyncConnContext(conn),
|
||||
),
|
||||
):
|
||||
created = await session_persistence.create_session(
|
||||
learner_id=_principal().user_id,
|
||||
card=persona_service.P1,
|
||||
theory_mode="humanistic",
|
||||
state=state_machine.SessionState(),
|
||||
session_no=2,
|
||||
carry_rapport=0.25,
|
||||
persona_id="00000000-0000-0000-0000-000000000201",
|
||||
persona_version=1,
|
||||
case_id="00000000-0000-0000-0000-000000000202",
|
||||
goal_stages=goals,
|
||||
)
|
||||
|
||||
self.assertIsNotNone(created)
|
||||
self.assertIsInstance(conn.session_insert_args[11], list)
|
||||
self.assertEqual(conn.session_insert_args[11], goals)
|
||||
self.assertNotIsInstance(conn.session_insert_args[11], str)
|
||||
|
||||
async def test_generate_turn_engine_failure_does_not_append_learner_turn(
|
||||
self,
|
||||
) -> None:
|
||||
|
|
@ -745,6 +818,8 @@ class SessionTurnPersistenceTest(unittest.IsolatedAsyncioTestCase):
|
|||
)
|
||||
)
|
||||
review_turn = review.turns[0]
|
||||
self.assertEqual(review_turn.id, "t1")
|
||||
self.assertEqual(review_turn.turn_id, learner_turn.turn_id)
|
||||
self.assertIsNotNone(review_turn.note)
|
||||
assert review_turn.note is not None
|
||||
self.assertEqual(review_turn.note.title, "턴 직후 평가 실패")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue