Connect all fourteen physical skills and private setup to five card-role battle modifiers, public posture, Harkonnen skilled capture, death return and optional own-leader revival through controls, legal AI and persisted room actions. Nine skill effects and combined-mode/publication acceptance remain unfinished. Captured replacement entitlement and foreign ghola integration stay guarded. Fresh publisher/designer research supports skilled-capture publicity through its unique known physical card; this is recorded as a component inference. Independent review found and fixed Voice/must-use-leader and invalid saved assignment/offer cases. A pre-existing Discovery privacy assertion confused card ID prefixes; the corrected deterministic physical-pair scenario was independently reviewed. The first broad run was 4410/4411; corrected final verification passes types/lint, all 4411 offline tests, build and 43 HTTP tests. Final durations: check 149741ms, build 6659ms, integration 28274ms. Source fingerprint: aef655ac1ebc0eb2f64294e13d3d27337167312cf8ab17568a166ee9c39f6a85. Private final report: 20260913-leader-skills/checks-final/report.json. Three seeded prototype games completed with no rejected bot candidates. Browser setup/card inspection/refresh passed. Another user-reported power outage stopped the server; backup and necessary restart restored the same private seat. All 292 games at restart and their original application records remain unchanged; 33 isolated HTTP-test rooms bring the current total to 325. No database reset. Efficiency: one shared setup/lifecycle implementation supports five connected role effects; selective existing agents handled catalog/UI/tests/research and independent reviews. One repeated broad check was required by the reproduced ID-prefix assertion failure. Aggregate goal counter rose from 65529766 to 67313673 through this checkpoint (1783907), including inherited context and coordination; this is not a billing or savings estimate. Full goal remains active.
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { DatabaseSync } from 'node:sqlite';
|
|
import { writeFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { parseArgs } from 'node:util';
|
|
import { captureSavedGames } from './saved-game-verification';
|
|
import { startPrototypeRoom } from './prototype-room';
|
|
import { sourceSnapshot } from './verification';
|
|
|
|
async function main() {
|
|
const { values } = parseArgs({
|
|
options: {
|
|
db: { type: 'string' },
|
|
profile: { type: 'string', default: 'ix' },
|
|
room: { type: 'string' },
|
|
version: { type: 'string' },
|
|
out: { type: 'string' },
|
|
help: { type: 'boolean' },
|
|
},
|
|
});
|
|
if (values.help) {
|
|
console.log(
|
|
'Usage: node --import tsx tools/start-prototype.ts --profile ix|discovery|leader-skills --db PATH --room CODE --version NUMBER --out /private/new-directory\nStarts only a fresh ready lobby for the selected development prototype. Backs up all rooms first, preserves sessions and existing games, and rejects stale versions. Normal game-start and publication gates remain closed.',
|
|
);
|
|
return;
|
|
}
|
|
if (
|
|
!['ix', 'discovery', 'leader-skills'].includes(values.profile) ||
|
|
!values.db ||
|
|
!values.room ||
|
|
!values.out ||
|
|
!/^\d+$/.test(values.version ?? '')
|
|
)
|
|
throw new Error(
|
|
'Provide --db, --room, --version and a new private --out directory.',
|
|
);
|
|
const root = fileURLToPath(new URL('../', import.meta.url));
|
|
const version = Number(values.version),
|
|
source = sourceSnapshot(root);
|
|
const snapshot = await captureSavedGames(root, values.db, values.out, true);
|
|
if (
|
|
!snapshot.rooms.some(
|
|
(room) => room.code === values.room && room.version === version,
|
|
)
|
|
)
|
|
throw new Error('The requested lobby version is absent from the backup.');
|
|
const db = new DatabaseSync(values.db);
|
|
try {
|
|
const result = startPrototypeRoom(
|
|
db,
|
|
values.room,
|
|
version,
|
|
values.profile as 'ix' | 'discovery' | 'leader-skills',
|
|
);
|
|
writeFileSync(
|
|
resolve(values.out, 'prototype.json'),
|
|
JSON.stringify(
|
|
{
|
|
format: 1,
|
|
startedAt: new Date().toISOString(),
|
|
profile: values.profile,
|
|
source,
|
|
beforeVersion: version,
|
|
...result,
|
|
},
|
|
null,
|
|
2,
|
|
) + '\n',
|
|
{ flag: 'wx', mode: 0o600 },
|
|
);
|
|
console.log(JSON.stringify(result));
|
|
} finally {
|
|
db.close();
|
|
}
|
|
}
|
|
main().catch((error: unknown) => {
|
|
console.error(
|
|
error instanceof Error ? error.message : 'Prototype start failed.',
|
|
);
|
|
process.exitCode = 1;
|
|
});
|