fix: disclose codex task limit caps
This commit is contained in:
@@ -242,8 +242,10 @@ function splitBrainLiveSupervisorFixtureResponse(path: string): JsonRecord {
|
||||
}
|
||||
|
||||
export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
const supervisor = codexTasksQueryForTest(["--view", "supervisor", "--limit", "260"], fixtureResponse);
|
||||
const supervisor = codexTasksQueryForTest(["--view", "supervisor", "--limit", "20"], fixtureResponse);
|
||||
const cappedLimit = codexTasksQueryForTest(["--view", "supervisor", "--limit", "260"], fixtureResponse);
|
||||
const full = codexTasksQueryForTest(["--view", "full", "--limit", "20"], fixtureResponse);
|
||||
const cappedFull = codexTasksQueryForTest(["--view", "full", "--limit", "260"], fixtureResponse);
|
||||
const runningFiltered = codexTasksQueryForTest(["--status", "running", "--limit", "40"], manyRunningFixtureResponse);
|
||||
const unreadFiltered = codexTasksQueryForTest(["--unread", "--limit", "20"], fixtureResponse);
|
||||
const splitBrainLive = codexTasksQueryForTest(["--view", "supervisor", "--limit", "20"], splitBrainLiveSupervisorFixtureResponse);
|
||||
@@ -254,6 +256,7 @@ export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
const unreadFilteredBody = JSON.stringify(unreadFiltered);
|
||||
const supervisorData = asRecord(supervisor);
|
||||
const supervisorView = asRecord(supervisorData.supervisor);
|
||||
const cappedSupervisorView = asRecord(asRecord(cappedLimit).supervisor);
|
||||
const runningFilteredView = asRecord(asRecord(runningFiltered).supervisor);
|
||||
const runningFilteredSection = asRecord(runningFilteredView.running);
|
||||
const unreadFilteredView = asRecord(asRecord(unreadFiltered).supervisor);
|
||||
@@ -265,6 +268,7 @@ export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
const fullItem = asRecord(asArray(asRecord(asRecord(full).tasks).items)[0]);
|
||||
const completedUnread = asRecord(supervisorView.completedUnread);
|
||||
const fullTasks = asRecord(asRecord(full).tasks);
|
||||
const cappedFullTasks = asRecord(asRecord(cappedFull).tasks);
|
||||
const diagnostics = asRecord(supervisorView.executionDiagnostics);
|
||||
const filters = asRecord(supervisorView.filters);
|
||||
const activeRunning = asRecord(supervisorView.activeRunning);
|
||||
@@ -279,9 +283,21 @@ export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
const splitBrainLiveActivity = asRecord(splitBrainLiveView.activity);
|
||||
const splitBrainLiveConcurrency = asRecord(splitBrainLiveView.commanderConcurrency);
|
||||
const splitBrainLiveCounts = asRecord(splitBrainLiveView.counts);
|
||||
const cappedFilters = asRecord(cappedSupervisorView.filters);
|
||||
const cappedSource = asRecord(cappedSupervisorView.source);
|
||||
const cappedLimitPolicy = asRecord(asRecord(cappedSupervisorView.disclosure).limitPolicy);
|
||||
const cappedCommands = asRecord(cappedSupervisorView.commands);
|
||||
const cappedFullFilters = asRecord(cappedFullTasks.filters);
|
||||
const cappedFullSource = asRecord(cappedFullTasks.source);
|
||||
|
||||
assertCondition(supervisorBody.length < fullBody.length * 0.55, "supervisor output should be materially smaller than full output", { supervisorChars: supervisorBody.length, fullChars: fullBody.length });
|
||||
assertCondition(supervisorBody.length < 45_000, "supervisor output should remain bounded even with large diagnostics", { supervisorChars: supervisorBody.length });
|
||||
assertCondition(cappedFilters.requestedLimit === 260 && cappedFilters.effectiveLimit === 100 && cappedFilters.limit === 100 && cappedFilters.limitCapped === true, "supervisor filters should disclose requested and capped effective limit", cappedFilters);
|
||||
assertCondition(cappedSource.requestedLimit === 200 && cappedSource.effectiveLimit === 200 && cappedSource.limit === 200 && cappedSource.returned === 15, "supervisor source should disclose independent overview fetch limit", cappedSource);
|
||||
assertCondition(cappedLimitPolicy.requestedLimit === 260 && cappedLimitPolicy.effectiveLimit === 100 && cappedLimitPolicy.sourceFetchLimit === 200 && cappedLimitPolicy.sourceEffectiveLimit === 200, "supervisor disclosure should summarize requested/effective/source limits", cappedLimitPolicy);
|
||||
assertCondition(String(cappedCommands.refresh ?? "").includes("--limit 260") && String(cappedCommands.byStatus ?? "").includes("--limit 260"), "supervisor follow-up commands should preserve requested limit", cappedCommands);
|
||||
assertCondition(cappedFullFilters.requestedLimit === 260 && cappedFullFilters.effectiveLimit === 100 && cappedFullFilters.limitCapped === true, "full view filters should disclose capped requested limit", cappedFullFilters);
|
||||
assertCondition(cappedFullSource.requestedLimit === 200 && cappedFullSource.effectiveLimit === 200, "full view source should disclose independent overview fetch limit", cappedFullSource);
|
||||
assertCondition(recentItems.length === 3, "recentCompleted should be capped below --limit by default", { returned: recentItems.length });
|
||||
assertCondition(asArray(completedUnread.items).length === 3, "completedUnread should be locally paged and kept separate from recentCompleted", completedUnread);
|
||||
assertCondition(recentItems.every((item) => asRecord(item).unreadTerminal === false), "recentCompleted should not duplicate unread terminal tasks", { recentItems });
|
||||
@@ -308,8 +324,8 @@ export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
assertCondition(fullItem.status === "running" && String(fullItem.statusLabel ?? "").includes("awaiting terminal/judge"), "full view should keep raw status while exposing derived closeout label", fullItem);
|
||||
assertCondition(fullItem.awaitingTerminalJudge === true && fullItem.closeoutState === "awaiting-terminal-or-judge", "full view should expose awaiting terminal/judge state", fullItem);
|
||||
assertCondition(fullTasks.returned === 15, "full view must not inherit supervisor recentCompleted cap", fullTasks);
|
||||
assertCondition(filters.requestedLimit === 260 && filters.limit === 100 && filters.limitCapped === true, "supervisor filters should disclose requested vs effective limit", filters);
|
||||
assertCondition(outputBudget.requestedLimit === 260 && outputBudget.effectiveLimit === 100 && outputBudget.sectionReturnedLimit === 3, "supervisor must expose output budget metadata", outputBudget);
|
||||
assertCondition(filters.requestedLimit === 20 && filters.limit === 20 && filters.limitCapped === false, "supervisor filters should disclose requested vs effective limit", filters);
|
||||
assertCondition(outputBudget.requestedLimit === 20 && outputBudget.effectiveLimit === 20 && outputBudget.sectionReturnedLimit === 3, "supervisor must expose output budget metadata", outputBudget);
|
||||
assertCondition(activeRunning.count === 15 && activeRunning.exact === true && activeRunning.source === "queue-summary-counts", "activeRunning should expose exact running+judging count from queue summary", activeRunning);
|
||||
assertCondition(activeRunningRowPage.returned === 1 && activeRunningRowPage.returnedLimit === 3 && activeRunningRowPage.distinction.includes("row page"), "activeRunning row page should distinguish returned rows from active count", activeRunningRowPage);
|
||||
assertCondition(activeRunningRedline.countField === "supervisor.activeRunning.count" && activeRunningRedline.hardRedline === 15 && activeRunningRedline.state === "at-or-over-hard-redline", "activeRunning redline should name count field and interpretation", activeRunningRedline);
|
||||
@@ -349,6 +365,7 @@ export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
checks: [
|
||||
"supervisor output materially smaller than full",
|
||||
"recentCompleted capped",
|
||||
"explicit --limit cap disclosed",
|
||||
"running/unread locally paged",
|
||||
"split-brain diagnostics capped",
|
||||
"active running exact count exposed",
|
||||
|
||||
+40
-24
@@ -14,6 +14,7 @@ const maxOutputPreviewChars = 1200;
|
||||
const defaultTasksLimit = 20;
|
||||
const defaultQueuesLimit = 8;
|
||||
const maxTasksLimit = 100;
|
||||
const tasksOverviewSourceFetchLimit = 200;
|
||||
const supervisorSectionReturnedLimit = 3;
|
||||
const supervisorRecentCompletedLimit = 3;
|
||||
const supervisorPromptPreviewChars = 70;
|
||||
@@ -2411,6 +2412,32 @@ function taskListCommand(options: CodexTasksOptions, extra: string[] = []): stri
|
||||
return `bun scripts/cli.ts ${args.join(" ")}`;
|
||||
}
|
||||
|
||||
function codexTasksLimitDisclosure(options: CodexTasksOptions): Record<string, unknown> {
|
||||
return {
|
||||
requestedLimit: options.requestedLimit,
|
||||
effectiveLimit: options.limit,
|
||||
maxLimit: maxTasksLimit,
|
||||
limitCapped: options.requestedLimit > options.limit,
|
||||
};
|
||||
}
|
||||
|
||||
function codexTasksSourceDisclosure(pagination: Record<string, unknown>): Record<string, unknown> {
|
||||
const effectiveLimit = asNumber(pagination.limit, 0) || null;
|
||||
return {
|
||||
endpoint: "/api/tasks/overview",
|
||||
requestedLimit: tasksOverviewSourceFetchLimit,
|
||||
fetchLimit: tasksOverviewSourceFetchLimit,
|
||||
limit: effectiveLimit,
|
||||
effectiveLimit,
|
||||
limitCapped: effectiveLimit !== null && effectiveLimit < tasksOverviewSourceFetchLimit,
|
||||
returned: asNumber(pagination.returned, 0) || null,
|
||||
total: asNumber(pagination.total, 0) || null,
|
||||
hasMore: asBoolean(pagination.hasMore),
|
||||
nextBeforeId: asString(pagination.nextBeforeId) || null,
|
||||
includeActive: asBoolean(pagination.includeActive),
|
||||
};
|
||||
}
|
||||
|
||||
function taskSectionLimit(options: CodexTasksOptions, maxReturned = supervisorSectionReturnedLimit): number {
|
||||
return Math.min(options.limit, maxReturned);
|
||||
}
|
||||
@@ -2618,8 +2645,8 @@ type CodexTasksTaskPage = {
|
||||
|
||||
function tasksListQueryString(options: CodexTasksOptions): string {
|
||||
return queryString({
|
||||
limit: 200,
|
||||
priorityLimit: 200,
|
||||
limit: tasksOverviewSourceFetchLimit,
|
||||
priorityLimit: tasksOverviewSourceFetchLimit,
|
||||
queueId: options.queueId,
|
||||
beforeId: options.beforeId,
|
||||
includeActive: 1,
|
||||
@@ -2692,28 +2719,24 @@ function codexTasksOverviewResult(
|
||||
queueId: options.queueId ?? null,
|
||||
requestedLimit: options.requestedLimit,
|
||||
limit: options.limit,
|
||||
effectiveLimit: options.limit,
|
||||
limitCapped: options.limit < options.requestedLimit,
|
||||
...codexTasksLimitDisclosure(options),
|
||||
unreadOnly: options.unreadOnly,
|
||||
status: options.statusFilter,
|
||||
beforeId: options.beforeId ?? null,
|
||||
},
|
||||
source: {
|
||||
endpoint: "/api/tasks/overview",
|
||||
queueId: options.queueId ?? null,
|
||||
limit: asNumber(pagination.limit, 0) || null,
|
||||
limitSemantics: "upstream overview fetch limit; separate from filters.requestedLimit/effectiveLimit and compact section row counts",
|
||||
returned: asNumber(pagination.returned, 0) || null,
|
||||
total: asNumber(pagination.total, 0) || null,
|
||||
hasMore: asBoolean(pagination.hasMore),
|
||||
nextBeforeId: asString(pagination.nextBeforeId) || null,
|
||||
includeActive: asBoolean(pagination.includeActive),
|
||||
},
|
||||
source: { queueId: options.queueId ?? null, ...codexTasksSourceDisclosure(pagination) },
|
||||
bounded: true,
|
||||
disclosure: {
|
||||
defaultView: "supervisor",
|
||||
policy: "bounded summary rows only; prompt/body are short previews and raw detail requires explicit task/full/trace/output commands",
|
||||
limitSemantics: "--limit is request/scanning/page budget; supervisor sections still return compact bounded row pages and expose counts separately",
|
||||
limitPolicy: {
|
||||
...codexTasksLimitDisclosure(options),
|
||||
sourceFetchLimit: tasksOverviewSourceFetchLimit,
|
||||
sourceEffectiveLimit: asNumber(pagination.limit, 0) || null,
|
||||
sourceReturned: asNumber(pagination.returned, 0) || null,
|
||||
note: "codex tasks --limit is capped for CLI output safety; supervisor sections also keep small row caps and expose commands.next for pagination",
|
||||
},
|
||||
outputBudget: {
|
||||
promptPreviewChars: supervisorPromptPreviewChars,
|
||||
bodyPreviewChars: supervisorBodyPreviewChars,
|
||||
@@ -2786,19 +2809,12 @@ function codexTasksFullResult(
|
||||
queueId: options.queueId ?? null,
|
||||
requestedLimit: options.requestedLimit,
|
||||
limit: options.limit,
|
||||
effectiveLimit: options.limit,
|
||||
limitCapped: options.limit < options.requestedLimit,
|
||||
...codexTasksLimitDisclosure(options),
|
||||
unreadOnly: options.unreadOnly,
|
||||
status: options.statusFilter,
|
||||
beforeId: options.beforeId ?? null,
|
||||
},
|
||||
source: {
|
||||
endpoint: "/api/tasks/overview",
|
||||
returned: asNumber(pagination.returned, 0) || null,
|
||||
total: asNumber(pagination.total, 0) || null,
|
||||
hasMore: asBoolean(pagination.hasMore),
|
||||
nextBeforeId,
|
||||
},
|
||||
source: codexTasksSourceDisclosure(pagination),
|
||||
count: filtered.length,
|
||||
returned: visible.length,
|
||||
hasMore: filtered.length > visible.length || sourceHasMore,
|
||||
|
||||
Reference in New Issue
Block a user