merge: cover general missing target boundaries
This commit is contained in:
@@ -30,6 +30,11 @@ turn 6개는 전투태세 1/2/3턴, 내정·전투 특기 초기화 1턴, 은퇴
|
|||||||
`last_turn`과 진행 로그, RNG 무소비를 비교한다. cooldown 3개는 특기
|
`last_turn`과 진행 로그, RNG 무소비를 비교한다. cooldown 3개는 특기
|
||||||
초기화 완료 직후 `current + 60 - preReq`, 1턴 전 차단, 경계 월 허용을
|
초기화 완료 직후 `current + 60 - preReq`, 1턴 전 차단, 경계 월 허용을
|
||||||
ref `next_execute` KV와 core general meta의 공통 projection으로 비교한다.
|
ref `next_execute` KV와 core general meta의 공통 projection으로 비교한다.
|
||||||
|
존재하지 않는 대상 경계 4개는 증여·등용의 장수 ID와 첩보·이동의 도시 ID를
|
||||||
|
고정해 원 명령 미완료, 휴식 fallback, RNG 무소비와 semantic delta를
|
||||||
|
비교한다.
|
||||||
|
필수 인자 객체 자체를 생략한 요청은 ref runner가 제한 시간 안에 종료되지
|
||||||
|
않아 동적 호환 판정에서 제외한다.
|
||||||
나머지 명령별 제약 실패·값 경계와 전체 core PostgreSQL 재조회가 완료
|
나머지 명령별 제약 실패·값 경계와 전체 core PostgreSQL 재조회가 완료
|
||||||
기준을 통과하기 전까지 55개 명령 전체의 동적 호환 상태를 `확인`으로
|
기준을 통과하기 전까지 55개 명령 전체의 동적 호환 상태를 `확인`으로
|
||||||
올리지 않는다.
|
올리지 않는다.
|
||||||
|
|||||||
@@ -210,6 +210,12 @@ Three post-required cooldown cases project the legacy `next_execute` KV and
|
|||||||
core general meta into the same world-level cooldown record. They cover the
|
core general meta into the same world-level cooldown record. They cover the
|
||||||
stored `current + 60 - preReq` value, rejection one turn before availability,
|
stored `current + 60 - preReq` value, rejection one turn before availability,
|
||||||
and successful execution exactly at the boundary.
|
and successful execution exactly at the boundary.
|
||||||
|
Four missing-target cases cover nonexistent general IDs for gift and
|
||||||
|
employment plus nonexistent city IDs for spying and movement. Both engines
|
||||||
|
reject the requested command, execute rest without command RNG, and produce
|
||||||
|
the same semantic state delta.
|
||||||
|
Requests that omit the required argument object remain unverified because the
|
||||||
|
reference runner did not terminate within the bounded comparison run.
|
||||||
This is not yet a claim that every command-specific
|
This is not yet a claim that every command-specific
|
||||||
constraint, clamp and persistence boundary has been dynamically
|
constraint, clamp and persistence boundary has been dynamically
|
||||||
compared.
|
compared.
|
||||||
|
|||||||
@@ -1058,6 +1058,57 @@ integration('general command post-required cooldown boundary matrix', () => {
|
|||||||
}, 120_000);
|
}, 120_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const missingTargetCases: Array<{ name: string; action: string; args: Record<string, unknown> }> = [
|
||||||
|
{
|
||||||
|
name: 'gift to a missing general',
|
||||||
|
action: 'che_증여',
|
||||||
|
args: { isGold: true, amount: 100, destGeneralID: 999 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'spy on a missing city',
|
||||||
|
action: 'che_첩보',
|
||||||
|
args: { destCityID: 999 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'move to a missing city',
|
||||||
|
action: 'che_이동',
|
||||||
|
args: { destCityID: 999 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'employ a missing general',
|
||||||
|
action: 'che_등용',
|
||||||
|
args: { destGeneralID: 999 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
integration('general command missing-target fallback matrix', () => {
|
||||||
|
it.each(missingTargetCases)(
|
||||||
|
'$name rejects the missing target and falls back without command RNG',
|
||||||
|
async ({ action, args }) => {
|
||||||
|
const request = buildRequest(action, args);
|
||||||
|
const reference = runReferenceTurnCommandTraceRequest(
|
||||||
|
workspaceRoot!,
|
||||||
|
request as unknown as Record<string, unknown>
|
||||||
|
);
|
||||||
|
const core = await runCoreTurnCommandTrace(request, reference.before);
|
||||||
|
|
||||||
|
expect(reference.execution.outcome).toMatchObject({ completed: false });
|
||||||
|
expect(core.execution.outcome).toMatchObject({
|
||||||
|
requestedAction: action,
|
||||||
|
actionKey: '휴식',
|
||||||
|
usedFallback: true,
|
||||||
|
});
|
||||||
|
expect(core.rng).toEqual(reference.rng);
|
||||||
|
expect(
|
||||||
|
compareTurnSnapshotDeltas(reference.before, reference.after, core.before, core.after, {
|
||||||
|
ignoredPathPatterns: ignoredLifecyclePaths,
|
||||||
|
})
|
||||||
|
).toEqual([]);
|
||||||
|
},
|
||||||
|
120_000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
type GeneralConstraintCase = {
|
type GeneralConstraintCase = {
|
||||||
name: string;
|
name: string;
|
||||||
action: string;
|
action: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user