fix: Ref 게임 로직과 시나리오 풀 호환을 보정

월 경계, 전투 기술 상한, 연감과 베팅·설문·경매 정산 순서를 Ref 계약에 맞춘다.\n\n시나리오 일반 풀을 ENGINE mutation과 logical tick 기반으로 직렬화하고 914·915 catalog 및 조건부 100기 pool 실행 경계를 추가한다.\n\n경매 worker는 세대별 durable event만 만들고 ENGINE이 row lock 후 상태 전이와 정산을 단일 transaction으로 소유한다.
This commit is contained in:
2026-08-23 16:26:14 +00:00
parent bf6b7be7b0
commit 85591c68ad
114 changed files with 13327 additions and 901 deletions
+36
View File
@@ -693,6 +693,42 @@ describe('appRouter', () => {
).rejects.toMatchObject({ code: 'FORBIDDEN' });
});
it('queues selection-pool reservation with the authenticated actor and server logical time', async () => {
const transport = new InMemoryTurnDaemonTransport();
const requestId = 'select-pool-reserve-http';
const commandRequestId = `select-pool:user-1:${requestId}:reserve`;
const acceptedGameAt = '2026-07-30T12:00:00.000Z';
const reservation = {
poolName: 'SPoolUnderU30',
hasGeneral: false,
validUntil: '2026-07-30T12:20:00.000Z',
candidates: [],
};
transport.setCommandResult(commandRequestId, {
type: 'selectPoolReserve',
ok: true,
reservation,
});
const state = {
...buildWorldState(),
clockBaseTime: new Date(acceptedGameAt),
clockTick: 0n,
clockMode: 'manual',
clockWallAnchor: new Date(acceptedGameAt),
} as WorldStateRow;
const context = { ...buildContext({ state, transport }), requestId };
await expect(appRouter.createCaller(context).join.getSelectionPool()).resolves.toEqual(reservation);
expect(transport.commands.at(-1)?.command).toEqual({
type: 'selectPoolReserve',
requestId: commandRequestId,
userId: 'user-1',
seedOwnerIdentity: 'user-1',
acceptedGameAt,
acceptedGameTick: 0,
});
});
it('queues turn daemon run commands', async () => {
const transport = new InMemoryTurnDaemonTransport();
const caller = appRouter.createCaller(buildContext({ transport }));