Files
pikasTech-unidesk/scripts/code-queue-queues-shape-contract-test.ts
T
2026-05-23 07:22:07 +00:00

278 lines
16 KiB
TypeScript

import { codexQueuesQueryForTest } from "./src/code-queue";
type JsonRecord = Record<string, unknown>;
function assertCondition(condition: unknown, message: string, detail: JsonRecord = {}): void {
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
}
function asRecord(value: unknown): JsonRecord {
assertCondition(typeof value === "object" && value !== null && !Array.isArray(value), "expected JSON object", { value });
return value as JsonRecord;
}
function asArray(value: unknown): unknown[] {
assertCondition(Array.isArray(value), "expected JSON array", { value });
return value as unknown[];
}
function manyIds(prefix: string, count: number): string[] {
return Array.from({ length: count }, (_, index) => `${prefix}-${String(index + 1).padStart(2, "0")}`);
}
function fixtureResponse(): JsonRecord {
return {
ok: true,
status: 200,
body: {
ok: true,
queue: {
total: 4,
queueCount: 3,
activeQueueIds: ["alpha"],
activeTaskIds: ["task-running"],
queuedTaskIds: ["task-queued"],
counts: { running: 1, queued: 2, succeeded: 1 },
unreadTerminal: 1,
executionDiagnostics: {
state: "split-brain",
splitBrain: true,
heartbeatFreshTaskIds: ["task-running"],
databaseActiveTaskCount: 1,
databaseActiveTaskIds: ["task-running"],
schedulerActiveRunSlotCount: 0,
schedulerActiveTaskIds: [],
},
},
queues: [
{
id: "alpha",
name: "Alpha",
total: 1,
counts: { running: 1, queued: 0 },
unreadTerminal: 0,
activeTaskId: "task-running",
runnableTaskId: null,
updatedAt: "2026-05-20T00:00:00.000Z",
},
{
id: "beta",
name: "Beta",
total: 2,
counts: { running: 0, queued: 2 },
unreadTerminal: 0,
activeTaskId: null,
runnableTaskId: "task-queued",
updatedAt: "2026-05-20T00:01:00.000Z",
},
{
id: "gamma",
name: "Gamma",
total: 1,
counts: { succeeded: 1 },
unreadTerminal: 1,
activeTaskId: null,
runnableTaskId: null,
updatedAt: "2026-05-20T00:02:00.000Z",
},
],
},
};
}
function splitBrainLiveResponse(): JsonRecord {
const liveTaskIds = manyIds("task-running", 8);
return {
ok: true,
status: 200,
body: {
ok: true,
queue: {
total: 8,
queueCount: 2,
activeQueueIds: [],
activeTaskIds: [],
queuedTaskIds: [],
counts: { running: 8 },
unreadTerminal: 0,
executionDiagnostics: {
state: "split-brain",
splitBrain: true,
splitBrainLive: true,
effectiveLiveness: "live",
recommendedAction: "continue-supervision",
databaseActiveTaskCount: 8,
databaseActiveTaskIds: liveTaskIds,
schedulerActiveRunSlotCount: 0,
schedulerActiveTaskIds: [],
activeHeartbeatCount: 8,
activeHeartbeatTaskIds: liveTaskIds,
heartbeatFreshTaskIds: liveTaskIds,
heartbeatExpiredTaskIds: [],
heartbeatMissingTaskIds: [],
staleRecoveryCandidateTaskIds: [],
heartbeatRiskTaskIds: [],
},
},
queues: [
{
id: "alpha",
name: "Alpha",
total: 4,
counts: { running: 4 },
unreadTerminal: 0,
activeTaskId: null,
runnableTaskId: null,
updatedAt: "2026-05-20T00:00:00.000Z",
},
{
id: "beta",
name: "Beta",
total: 4,
counts: { running: 4 },
unreadTerminal: 0,
activeTaskId: null,
runnableTaskId: null,
updatedAt: "2026-05-20T00:01:00.000Z",
},
],
},
};
}
function assertQueuesShape(label: string, result: unknown, expectedView: string): void {
const data = asRecord(result);
const queues = asRecord(data.queues);
assertCondition(queues.view === expectedView, `${label} view mismatch`, queues);
const items = asArray(queues.items);
assertCondition(items.length === 3, `${label} must expose queue rows at data.queues.items[]`, queues);
const first = asRecord(items[0]);
assertCondition(first.id === "alpha", `${label} first item id mismatch`, first);
const firstCounts = asRecord(first.counts);
assertCondition(firstCounts.running === 1, `${label} item counts should be preserved`, first);
const counts = asRecord(queues.counts);
assertCondition(counts.running === 1 && counts.queued === 2, `${label} global counts should be preserved`, counts);
const diagnostics = asRecord(queues.executionDiagnostics);
assertCondition(diagnostics.state === "split-brain", `${label} executionDiagnostics should be preserved`, diagnostics);
assertCondition(diagnostics.splitBrainLive === true, `${label} split-brain live should remain explicitly true`, diagnostics);
assertCondition(diagnostics.effectiveLiveness === "live", `${label} diagnostics should retain derived liveness`, diagnostics);
assertCondition(diagnostics.recommendedAction === "continue-supervision", `${label} split-brain live should continue supervision`, diagnostics);
const liveness = asRecord(diagnostics.liveness);
assertCondition(liveness.effectiveLiveness === "live", `${label} liveness summary should foreground effective live state`, liveness);
assertCondition(liveness.recommendedAction === "continue-supervision", `${label} liveness summary should foreground recommended action`, liveness);
assertCondition(liveness.activeHeartbeatCount === 1, `${label} liveness summary should derive active heartbeat count from fresh heartbeat ids`, liveness);
assertCondition(liveness.schedulerActiveRunSlotCount === 0, `${label} liveness summary should keep master active slot zero visible`, liveness);
assertCondition(asArray(liveness.heartbeatFreshTaskIds).length === 1, `${label} liveness summary should include bounded fresh heartbeat task ids`, liveness);
assertCondition(String(liveness.interpretation ?? "").includes("heartbeat is fresh"), `${label} liveness interpretation should explain slot-zero split-brain`, liveness);
const activity = asRecord(queues.activity);
assertCondition(activity.effectiveActiveTaskCount === 1, `${label} activity should foreground effective active task count`, activity);
assertCondition(activity.databaseRunningTaskCount === 1, `${label} activity should distinguish database running tasks`, activity);
assertCondition(activity.heartbeatFreshActiveTaskCount === 1, `${label} activity should distinguish heartbeat-fresh active runners`, activity);
assertCondition(activity.schedulerLocalActiveQueueCount === 1, `${label} activity should distinguish scheduler-local active queues`, activity);
const commanderConcurrency = asRecord(activity.commanderConcurrency);
assertCondition(commanderConcurrency.activeRunnerCount === 1, `${label} activity should expose commander-facing active runner count`, commanderConcurrency);
assertCondition(commanderConcurrency.activeRunnerCountField === "activity.effectiveActiveTaskCount", `${label} activity should name the active runner count field`, commanderConcurrency);
assertCondition(activity.activeQueueIdsScope === "scheduler-local-active-run-slots", `${label} activity should label activeQueueIds scope`, activity);
assertCondition(Array.isArray(queues.activeTaskIds), `${label} activeTaskIds should be present`, queues);
assertCondition(Array.isArray(queues.queuedTaskIds), `${label} queuedTaskIds should be present`, queues);
}
function assertSplitBrainLiveActivity(label: string, result: unknown): void {
const queues = asRecord(asRecord(result).queues);
const totals = asRecord(queues.totals);
assertCondition(totals.activeQueueCount === 0, `${label} scheduler-local active queue count should be zero`, totals);
assertCondition(totals.schedulerLocalActiveQueueCount === 0, `${label} should preserve zero scheduler-local active queues`, totals);
assertCondition(totals.runnableQueueCount === 0, `${label} runnable queue count should be zero`, totals);
assertCondition(totals.databaseRunningTaskCount === 8, `${label} should foreground DB running task count`, totals);
assertCondition(totals.databaseActiveTaskCount === 8, `${label} should foreground DB active task count`, totals);
assertCondition(totals.heartbeatFreshActiveTaskCount === 8, `${label} should foreground heartbeat-effective active runners`, totals);
assertCondition(totals.commanderActiveRunnerCount === 8, `${label} should mirror commander active count in totals`, totals);
assertCondition(totals.effectiveActiveTaskCount === 8, `${label} should foreground effective active task count`, totals);
assertCondition(asArray(queues.activeQueueIds).length === 0, `${label} activeQueueIds should remain the scheduler-local list`, queues);
assertCondition(queues.activeQueueIdsScope === "scheduler-local-active-run-slots", `${label} activeQueueIds should be scoped`, queues);
assertCondition(String(queues.activeQueueIdsNote ?? "").includes("scheduler-local only"), `${label} activeQueueIds note should explain local-only semantics`, queues);
const activity = asRecord(queues.activity);
assertCondition(activity.effectiveActiveTaskCount === 8, `${label} activity should expose effective active count`, activity);
assertCondition(activity.effectiveActiveSource === "heartbeat-fresh", `${label} activity should choose heartbeat-fresh source`, activity);
assertCondition(activity.databaseRunningTaskCount === 8, `${label} activity should expose DB running count`, activity);
assertCondition(activity.heartbeatFreshActiveTaskCount === 8, `${label} activity should expose heartbeat-effective active count`, activity);
assertCondition(activity.schedulerLocalActiveQueueCount === 0, `${label} activity should expose scheduler-local queue count`, activity);
assertCondition(activity.schedulerLocalActiveRunSlotCount === 0, `${label} activity should expose scheduler-local slot count`, activity);
assertCondition(activity.runnableQueueCount === 0, `${label} activity should expose runnable queue count`, activity);
assertCondition(activity.splitBrainLive === true, `${label} activity should preserve split-brain live`, activity);
assertCondition(activity.splitBrainDisposition === "live-count-as-active", `${label} activity should count live split-brain as active`, activity);
const commanderConcurrency = asRecord(queues.commanderConcurrency);
assertCondition(commanderConcurrency.activeRunnerCount === 8, `${label} should expose commander-facing active runner count`, commanderConcurrency);
assertCondition(commanderConcurrency.activeRunnerCountField === "activity.effectiveActiveTaskCount", `${label} should name the active runner count field`, commanderConcurrency);
assertCondition(commanderConcurrency.splitBrainDisposition === "live-count-as-active", `${label} should classify live split-brain capacity`, commanderConcurrency);
assertCondition(commanderConcurrency.interventionRequired === false, `${label} should not require intervention for fresh split-brain`, commanderConcurrency);
assertCondition(String(commanderConcurrency.decisionRule ?? "").includes("15 - activeRunnerCount"), `${label} should give 15-concurrency arithmetic`, commanderConcurrency);
assertCondition(String(activity.activeQueueIdsNote ?? "").includes("zero local queue ids does not mean zero active runners"), `${label} activity note should prevent zero-active misread`, activity);
assertCondition(String(activity.interpretation ?? "").includes("continue supervision"), `${label} activity interpretation should keep supervision action`, activity);
}
export function runCodeQueueQueuesShapeContract(): JsonRecord {
const fetcher = (path: string): JsonRecord => {
assertCondition(path === "/api/microservices/code-queue/proxy/api/queues", "codex queues should use stable proxy path", { path });
return fixtureResponse();
};
const splitBrainFetcher = (path: string): JsonRecord => {
assertCondition(path === "/api/microservices/code-queue/proxy/api/queues", "codex queues should use stable proxy path", { path });
return splitBrainLiveResponse();
};
const summary = codexQueuesQueryForTest([], fetcher);
assertQueuesShape("summary", summary, "summary");
const summaryQueues = asRecord(asRecord(summary).queues);
assertCondition(summaryQueues.deprecatedFullArray === undefined, "summary should not expose deprecated full array compatibility field", summaryQueues);
const full = codexQueuesQueryForTest(["--full"], fetcher);
assertQueuesShape("full", full, "full");
const fullQueues = asRecord(asRecord(full).queues);
assertCondition(!Array.isArray(fullQueues), "full queues payload must be an object, not the deprecated array shape", fullQueues);
assertCondition(fullQueues.bounded === true, "full queues output should now be paged by default", fullQueues);
assertCondition(fullQueues.deprecatedFullArray === undefined, "full should not expose deprecated unbounded array by default", fullQueues);
const compatibility = asRecord(fullQueues.compatibility);
assertCondition(compatibility.stablePath === "data.queues.items[]", "compatibility metadata should document stable path", compatibility);
assertCondition(compatibility.deprecated === true, "compatibility metadata should mark old array path deprecated", compatibility);
assertCondition(compatibility.deprecatedFullArrayOmitted === true, "compatibility metadata should explain deprecated array omission", compatibility);
const limitedFull = codexQueuesQueryForTest(["--full", "--limit", "2"], fetcher);
const limitedFullQueues = asRecord(asRecord(limitedFull).queues);
assertCondition(limitedFullQueues.bounded === true, "full with explicit --limit should be bounded", limitedFullQueues);
assertCondition(asArray(limitedFullQueues.items).length === 2, "full with explicit --limit should limit data.queues.items[]", limitedFullQueues);
assertCondition(limitedFullQueues.hasMore === true, "limited full should expose next page", limitedFullQueues);
const limitedCommands = asRecord(limitedFullQueues.commands);
assertCondition(String(limitedCommands.next ?? "").includes("--offset 2"), "limited full should expose offset pagination command", limitedCommands);
const offsetFull = codexQueuesQueryForTest(["--full", "--limit", "2", "--offset", "2"], fetcher);
const offsetFullQueues = asRecord(asRecord(offsetFull).queues);
assertCondition(offsetFullQueues.offset === 2, "offset full should preserve offset", offsetFullQueues);
assertCondition(offsetFullQueues.hasPrevious === true, "offset full should expose previous page", offsetFullQueues);
assertCondition(asRecord(asArray(offsetFullQueues.items)[0]).id === "gamma", "offset full should return second page rows", offsetFullQueues);
const splitSummary = codexQueuesQueryForTest([], splitBrainFetcher);
assertSplitBrainLiveActivity("split-brain summary", splitSummary);
const splitFull = codexQueuesQueryForTest(["--full"], splitBrainFetcher);
assertSplitBrainLiveActivity("split-brain full", splitFull);
return {
ok: true,
checks: [
"summary data.queues.items[] shape",
"summary queue metadata",
"full data.queues.items[] shape",
"full queue metadata",
"deprecated full array omitted from default output",
"full explicit limit remains bounded and paged",
"offset pagination",
"split-brain live activity counts distinguish scheduler-local queues, DB running tasks, and heartbeat-fresh runners",
"commander concurrency block names the active runner count and 15-concurrency rule",
],
};
}
if (import.meta.main) {
process.stdout.write(`${JSON.stringify(runCodeQueueQueuesShapeContract(), null, 2)}\n`);
}