위협 가이드를 관리자 전용 옵션으로(기본 꺼짐) + 최고관리자 추가 + 계정 메뉴에 관리자 메뉴

- 엔진: GameDefinition.adminOnlyOptions — 방은 항상 관리자 값 사용(잠금처럼 강제, 잠금 안내는 안 띄움)
- 오목·체스·장기 threatHints, 바둑 atariWarning: 기본 false, 대기실 설정에서 뺌, 관리자 화면 게임 기본 규칙에서만 켬
- 체스·장기 hints는 off / moves만 남김
- 최고관리자 기본값에 1352267557213573160 추가(.env.example·문서 포함)
- 상단 계정 메뉴: 관리자·최고관리자면 [🛠 관리자 메뉴] → /admin
- 테스트: admin.test(관리자 전용 옵션 강제, 두 번째 최고관리자), admin.e2e(계정 메뉴, 위협 가이드 켜기 저장)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-10-07 15:59:32 +09:00
parent 4cb71d8cbe
commit 373231b553
32 changed files with 207 additions and 45 deletions

View File

@@ -531,8 +531,8 @@ describe('undo, draw, resign', () => {
});
describe('views and determinism', () => {
test('no hidden internals in any view; mover-only illegal points; no atari warning', () => {
let s = make({}, { black: ['B1', 'A2'], white: ['A3', 'C1'] }, 'white');
test('no hidden internals in any view; mover-only hints', () => {
let s = make({ atariWarning: true }, { black: ['B1', 'A2'], white: ['A3', 'C1'] }, 'white');
s = play(s, 'B2'); // black B1/A2... put black stones in atari
for (const viewer of ['A', 'B', null]) {
const json = JSON.stringify(baduk.view(s, viewer));
@@ -541,9 +541,14 @@ describe('views and determinism', () => {
expect(json).not.toContain('rng');
}
const mover = baduk.view(s, 'A');
expect(mover.atariWarnings.length).toBeGreaterThan(0);
expect(mover.illegalPoints.length).toBeGreaterThan(0);
for (const viewer of ['B', null]) expect(baduk.view(s, viewer).illegalPoints).toEqual([]);
for (const viewer of ['A', 'B', null]) expect(JSON.stringify(baduk.view(s, viewer))).not.toMatch(/atari/i);
for (const viewer of ['B', null]) {
const v = baduk.view(s, viewer);
expect(v.illegalPoints).toEqual([]);
expect(v.atariWarnings).toEqual([]);
}
expect(baduk.view(make({}, { black: ['B1'], white: ['A1', 'C1'] }), 'A').atariWarnings).toEqual([]); // off by default
});
test('nigiri is seeded and deterministic', () => {