fix: reduce codex supervisor output noise
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { codexPrPreflightQueryForTest } from "./src/code-queue";
|
||||
import type { UniDeskConfig } from "./src/config";
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
@@ -354,37 +355,46 @@ async function main(): Promise<void> {
|
||||
assertCondition(remoteControlPlaneMissingRecord.degradedReason === "remote-control-plane-unreachable", "missing control plane should classify as remote-control-plane-unreachable", remoteControlPlaneMissingRecord);
|
||||
assertCondition(asRecord(remoteControlPlaneMissingRecord.controlPlane).localBackendCoreMissing === true, "local backend-core absence should remain evidence only", remoteControlPlaneMissingRecord.controlPlane);
|
||||
|
||||
const directAuthMissing = remoteControlPlaneResult({
|
||||
ok: false,
|
||||
failureKind: "auth-missing",
|
||||
degradedReason: "GH_TOKEN/GITHUB_TOKEN missing",
|
||||
runnerDisposition: "infra-blocked",
|
||||
message: "GH_TOKEN/GITHUB_TOKEN missing in remote control plane",
|
||||
tokenCoverage: {
|
||||
const directAuthMissing = await codexPrPreflightQueryForTest(["--remote"], {
|
||||
config: { network: { publicHost: "74.48.78.17", frontend: { port: 18081 } } } as unknown as UniDeskConfig,
|
||||
coreFetch: () => localBackendCoreMissingFixture(),
|
||||
remoteMainServerPrPreflight: () => remoteControlPlaneResult({
|
||||
ok: false,
|
||||
source: null,
|
||||
ghTokenPresent: false,
|
||||
githubTokenPresent: false,
|
||||
ghCredentialStorePresent: false,
|
||||
failureKind: "auth-missing",
|
||||
degradedReason: "GH_TOKEN/GITHUB_TOKEN missing",
|
||||
runnerDisposition: "infra-blocked",
|
||||
missing: ["GH_TOKEN", "GITHUB_TOKEN"],
|
||||
scope: "scheduler-runner-env",
|
||||
},
|
||||
prCapabilityContract: {
|
||||
targetBranch: "master",
|
||||
tokenSource: null,
|
||||
systemGhBinaryRequiredForWrites: false,
|
||||
unideskGhCli: { ok: true, path: "/workspace/unidesk/scripts/cli.ts", present: true, role: "repo-native REST GitHub CLI used by bun scripts/cli.ts gh", requiresSystemGhBinary: false },
|
||||
pushDryRun: { requested: false, ref: "refs/heads/probe/code-queue-pr-capability-dryrun", writesRemote: false, commandShape: "git push --dry-run origin HEAD:refs/heads/probe/code-queue-pr-capability-dryrun" },
|
||||
prCreateDryRun: { requested: false, headBranch: "feature/code-queue-pr-preflight", writesRemote: false, commandShape: "bun scripts/cli.ts gh pr create --repo pikasTech/unidesk --base master --head feature/code-queue-pr-preflight --dry-run" },
|
||||
expectedPrHandoff: { sourceBranch: "feature/code-queue-pr-preflight", targetBranch: "master", runnerCreatesPrAfterAuthorization: true, commanderReviewsAndMerges: true, preflightCreatesPr: false, preflightMergesPr: false },
|
||||
unsupportedMergeBoundary: { supported: false, command: "bun scripts/cli.ts gh pr merge <number> --repo pikasTech/unidesk", degradedReason: "unsupported-command", runnerDisposition: "business-failed", note: "UniDesk CLI intentionally does not merge PRs in this phase; runner handoff stops at PR creation and evidence." },
|
||||
},
|
||||
message: "GH_TOKEN/GITHUB_TOKEN missing in remote control plane",
|
||||
tokenCoverage: {
|
||||
ok: false,
|
||||
source: null,
|
||||
ghTokenPresent: false,
|
||||
githubTokenPresent: false,
|
||||
ghCredentialStorePresent: false,
|
||||
runnerDisposition: "infra-blocked",
|
||||
missing: ["GH_TOKEN", "GITHUB_TOKEN"],
|
||||
scope: "scheduler-runner-env",
|
||||
},
|
||||
prCapabilityContract: {
|
||||
targetBranch: "master",
|
||||
tokenSource: null,
|
||||
systemGhBinaryRequiredForWrites: false,
|
||||
unideskGhCli: { ok: true, path: "/workspace/unidesk/scripts/cli.ts", present: true, role: "repo-native REST GitHub CLI used by bun scripts/cli.ts gh", requiresSystemGhBinary: false },
|
||||
pushDryRun: { requested: false, ref: "refs/heads/probe/code-queue-pr-capability-dryrun", writesRemote: false, commandShape: "git push --dry-run origin HEAD:refs/heads/probe/code-queue-pr-capability-dryrun" },
|
||||
prCreateDryRun: { requested: false, headBranch: "feature/code-queue-pr-preflight", writesRemote: false, commandShape: "bun scripts/cli.ts gh pr create --repo pikasTech/unidesk --base master --head feature/code-queue-pr-preflight --dry-run" },
|
||||
expectedPrHandoff: { sourceBranch: "feature/code-queue-pr-preflight", targetBranch: "master", runnerCreatesPrAfterAuthorization: true, commanderReviewsAndMerges: true, preflightCreatesPr: false, preflightMergesPr: false },
|
||||
unsupportedMergeBoundary: { supported: false, command: "bun scripts/cli.ts gh pr merge <number> --repo pikasTech/unidesk", degradedReason: "unsupported-command", runnerDisposition: "business-failed", note: "UniDesk CLI intentionally does not merge PRs in this phase; runner handoff stops at PR creation and evidence." },
|
||||
},
|
||||
}),
|
||||
});
|
||||
const directAuthMissingRecord = asRecord(directAuthMissing);
|
||||
assertCondition(directAuthMissingRecord.ok === false, "auth-missing remote result should fail", directAuthMissingRecord);
|
||||
assertCondition(directAuthMissingRecord.failureKind === "auth-missing", "missing token should classify as auth-missing", directAuthMissingRecord);
|
||||
assertCondition(directAuthMissingRecord.degradedReason === "GH_TOKEN/GITHUB_TOKEN missing", "auth missing should state token gap", directAuthMissingRecord);
|
||||
const directAuthScopeBoundary = asRecord(directAuthMissingRecord.scopeBoundary);
|
||||
const directAuthActiveRunner = asRecord(directAuthMissingRecord.activeRunnerDevContainer);
|
||||
assertCondition(directAuthScopeBoundary.scopesAreIndependent === true, "remote auth-missing must distinguish scheduler env from active runner dev container", directAuthScopeBoundary);
|
||||
assertCondition(String(directAuthScopeBoundary.authMissingInterpretation ?? "").includes("do not simplify"), "remote auth-missing must warn against overbroad interpretation", directAuthScopeBoundary);
|
||||
assertCondition(directAuthActiveRunner.notEquivalentToSchedulerEnv === true, "active runner token capability must be a separate scope", directAuthActiveRunner);
|
||||
|
||||
const gitRemoteGap = remoteControlPlaneResult({
|
||||
ok: false,
|
||||
@@ -575,8 +585,12 @@ async function main(): Promise<void> {
|
||||
assertCondition(dryRunRecord.failureKind === "auth-missing", "missing runner token should remain auth-missing even when system gh is absent", dryRunRecord);
|
||||
const dryRunPreflight = asRecord(dryRunRecord.preflight);
|
||||
const dryRunAuthBroker = asRecord(dryRunPreflight.authBroker);
|
||||
const dryRunScopeBoundary = asRecord(dryRunPreflight.scopeBoundary);
|
||||
const dryRunActiveRunner = asRecord(dryRunPreflight.activeRunnerDevContainer);
|
||||
assertCondition(dryRunAuthBroker.source === "broker/auth-broker-needed", "missing runner token should expose broker/auth-broker-needed", dryRunAuthBroker);
|
||||
assertCondition(dryRunAuthBroker.degradedReason === "auth-broker-needed", "auth broker degraded reason should be explicit", dryRunAuthBroker);
|
||||
assertCondition(dryRunScopeBoundary.scopesAreIndependent === true, "local compact preflight should expose independent auth scopes", dryRunScopeBoundary);
|
||||
assertCondition(dryRunActiveRunner.scope === "current-cli-process", "local compact preflight should expose current CLI process capability", dryRunActiveRunner);
|
||||
const dryRunBrokerEvidence = asRecord(dryRunAuthBroker.evidence);
|
||||
assertCondition(dryRunBrokerEvidence.systemGhBinaryOk === false, "system gh absence should be reported separately", dryRunBrokerEvidence);
|
||||
assertCondition(dryRunBrokerEvidence.unideskGhCliOk === true, "UniDesk REST gh CLI should not be marked unavailable because system gh is missing", dryRunBrokerEvidence);
|
||||
@@ -713,11 +727,15 @@ async function main(): Promise<void> {
|
||||
assertCondition(missingTokenRecord.degradedReason === "auth-broker-needed", "missing-token branch should expose broker-needed degraded reason", missingTokenRecord);
|
||||
const missingTokenPreflight = asRecord(missingTokenRecord.preflight);
|
||||
const missingTokenAuthBroker = asRecord(missingTokenPreflight.authBroker);
|
||||
const missingTokenScopeBoundary = asRecord(missingTokenPreflight.scopeBoundary);
|
||||
const missingTokenActiveRunner = asRecord(missingTokenPreflight.activeRunnerDevContainer);
|
||||
const missingTokenCapability = asRecord(missingTokenAuthBroker.capability);
|
||||
assertCondition(missingTokenAuthBroker.source === "broker/auth-broker-needed", "missing-token branch should expose broker/auth-broker-needed", missingTokenAuthBroker);
|
||||
assertCondition(missingTokenAuthBroker.nextAction === "configure-auth-broker-or-env-token", "missing-token branch should expose nextAction", missingTokenAuthBroker);
|
||||
assertCondition(missingTokenCapability.source === "missing-token", "missing-token branch should expose missing-token capability", missingTokenCapability);
|
||||
assertCondition(missingTokenCapability.systemGhBinaryRequiredForWrites === false, "missing-token branch should still not require system gh binary for UniDesk gh CLI", missingTokenCapability);
|
||||
assertCondition(String(missingTokenScopeBoundary.currentRunnerCheck ?? "").includes("gh auth status"), "missing-token branch should point to active runner auth check", missingTokenScopeBoundary);
|
||||
assertCondition(missingTokenActiveRunner.relationToRemotePreflight === "independent-scope; scheduler-runner-env auth-missing does not prove the active runner/dev container lacks GitHub PR capability", "missing-token branch should not overstate active runner PR capability", missingTokenActiveRunner);
|
||||
|
||||
process.stdout.write(`${JSON.stringify({
|
||||
ok: true,
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
import { codexTasksQueryForTest } 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 longText(marker: string, repeat: number): string {
|
||||
return Array.from({ length: repeat }, (_, index) => `${marker}-${index} #132 Gate report diagnostic review evidence direct workbench fix`).join("\n");
|
||||
}
|
||||
|
||||
function task(id: string, status: string, updatedAt: string, readAt: string | null = null): JsonRecord {
|
||||
return {
|
||||
id,
|
||||
queueId: "default",
|
||||
status,
|
||||
currentAttempt: status === "running" ? 2 : 1,
|
||||
updatedAt,
|
||||
finishedAt: status === "succeeded" ? updatedAt : null,
|
||||
readAt,
|
||||
prompt: longText(`prompt-${id}`, 90),
|
||||
basePrompt: longText(`base-${id}`, 70),
|
||||
displayPrompt: longText(`display-${id}`, 80),
|
||||
lastAssistantMessage: {
|
||||
at: updatedAt,
|
||||
seq: 99,
|
||||
source: "assistant",
|
||||
text: longText(`assistant-${id}`, 120),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function fixtureResponse(path: string): JsonRecord {
|
||||
if (path.includes("/summary")) {
|
||||
const taskId = decodeURIComponent(path.split("/api/tasks/")[1]?.split("/")[0] ?? "unknown");
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
body: {
|
||||
ok: true,
|
||||
summary: {
|
||||
id: taskId,
|
||||
queueId: "default",
|
||||
status: taskId.includes("running") ? "running" : "succeeded",
|
||||
currentAttempt: 1,
|
||||
maxAttempts: 99,
|
||||
prompt: longText(`summary-prompt-${taskId}`, 100),
|
||||
basePrompt: longText(`summary-base-${taskId}`, 80),
|
||||
lastAssistantMessage: {
|
||||
at: "2026-05-22T00:00:00.000Z",
|
||||
seq: 120,
|
||||
source: "assistant",
|
||||
text: longText(`summary-assistant-${taskId}`, 130),
|
||||
},
|
||||
commands: {
|
||||
show: `bun scripts/cli.ts codex task ${taskId}`,
|
||||
trace: `bun scripts/cli.ts codex task ${taskId} --trace --tail --limit 80`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
assertCondition(path.startsWith("/api/microservices/code-queue/proxy/api/tasks/overview"), "unexpected path", { path });
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
body: {
|
||||
ok: true,
|
||||
queue: {
|
||||
executionDiagnostics: {
|
||||
effectiveLiveness: "live",
|
||||
splitBrainLive: true,
|
||||
recommendedAction: "continue-supervision",
|
||||
},
|
||||
},
|
||||
pagination: {
|
||||
limit: 200,
|
||||
returned: 15,
|
||||
total: 15,
|
||||
hasMore: false,
|
||||
nextBeforeId: null,
|
||||
includeActive: true,
|
||||
},
|
||||
tasks: [
|
||||
task("task-running", "running", "2026-05-22T00:09:00.000Z"),
|
||||
task("task-succeeded-1", "succeeded", "2026-05-22T00:08:00.000Z"),
|
||||
task("task-succeeded-2", "succeeded", "2026-05-22T00:07:00.000Z"),
|
||||
task("task-succeeded-3", "succeeded", "2026-05-22T00:06:00.000Z"),
|
||||
task("task-succeeded-4", "succeeded", "2026-05-22T00:05:00.000Z"),
|
||||
task("task-succeeded-5", "succeeded", "2026-05-22T00:04:00.000Z"),
|
||||
task("task-succeeded-6", "succeeded", "2026-05-22T00:03:00.000Z"),
|
||||
task("task-succeeded-7", "succeeded", "2026-05-22T00:02:00.000Z"),
|
||||
task("task-read-1", "succeeded", "2026-05-22T00:01:50.000Z", "2026-05-22T00:01:55.000Z"),
|
||||
task("task-read-2", "succeeded", "2026-05-22T00:01:40.000Z", "2026-05-22T00:01:45.000Z"),
|
||||
task("task-read-3", "succeeded", "2026-05-22T00:01:30.000Z", "2026-05-22T00:01:35.000Z"),
|
||||
task("task-read-4", "succeeded", "2026-05-22T00:01:20.000Z", "2026-05-22T00:01:25.000Z"),
|
||||
task("task-read-5", "succeeded", "2026-05-22T00:01:10.000Z", "2026-05-22T00:01:15.000Z"),
|
||||
task("task-read-6", "succeeded", "2026-05-22T00:01:05.000Z", "2026-05-22T00:01:09.000Z"),
|
||||
task("task-queued", "queued", "2026-05-22T00:01:00.000Z"),
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function runCodeQueueSupervisorDisclosureContract(): JsonRecord {
|
||||
const supervisor = codexTasksQueryForTest(["--view", "supervisor", "--limit", "20"], fixtureResponse);
|
||||
const full = codexTasksQueryForTest(["--view", "full", "--limit", "20"], fixtureResponse);
|
||||
|
||||
const supervisorBody = JSON.stringify(supervisor);
|
||||
const fullBody = JSON.stringify(full);
|
||||
const supervisorData = asRecord(supervisor);
|
||||
const supervisorView = asRecord(supervisorData.supervisor);
|
||||
const disclosure = asRecord(supervisorView.disclosure);
|
||||
const runningItem = asRecord(asArray(asRecord(supervisorView.running).items)[0]);
|
||||
const recentCompleted = asRecord(supervisorView.recentCompleted);
|
||||
const recentItems = asArray(recentCompleted.items);
|
||||
const prompt = asRecord(runningItem.prompt);
|
||||
const lastMessage = asRecord(runningItem.lastMessage);
|
||||
const commands = asRecord(runningItem.commands);
|
||||
const fullItem = asRecord(asArray(asRecord(asRecord(full).tasks).items)[0]);
|
||||
const completedUnread = asRecord(supervisorView.completedUnread);
|
||||
const fullTasks = asRecord(asRecord(full).tasks);
|
||||
|
||||
assertCondition(supervisorBody.length < fullBody.length * 0.55, "supervisor output should be materially smaller than full output", { supervisorChars: supervisorBody.length, fullChars: fullBody.length });
|
||||
assertCondition(recentItems.length === 5, "recentCompleted should be capped below --limit by default", { returned: recentItems.length });
|
||||
assertCondition(asArray(completedUnread.items).length === 7, "completedUnread should keep unread terminal tasks separate from recentCompleted", completedUnread);
|
||||
assertCondition(recentItems.every((item) => asRecord(item).unreadTerminal === false), "recentCompleted should not duplicate unread terminal tasks", { recentItems });
|
||||
assertCondition(asArray(runningItem.issueRefs).includes("#132"), "supervisor row should expose issue refs for triage", runningItem);
|
||||
assertCondition(Number(prompt.chars) > String(prompt.text ?? "").length && prompt.truncated === true, "supervisor prompt must be a short preview with original char count", prompt);
|
||||
assertCondition(Number(lastMessage.chars) > String(lastMessage.text ?? "").length && lastMessage.truncated === true, "supervisor body must be a short preview with original char count", lastMessage);
|
||||
assertCondition(commands.show !== undefined && commands.trace !== undefined && commands.output !== undefined && commands.full !== undefined, "supervisor row must keep progressive drill-down commands", commands);
|
||||
assertCondition(runningItem.promptPreview === undefined && runningItem.lastAssistantMessage === undefined, "supervisor rows must not expose legacy long list fields", runningItem);
|
||||
assertCondition(asRecord(fullItem.promptPreview).chars !== undefined && fullItem.lastAssistantMessage !== undefined, "full view must retain detailed task row fields", fullItem);
|
||||
assertCondition(fullTasks.returned === 15, "full view must not inherit supervisor recentCompleted cap", fullTasks);
|
||||
assertCondition(asRecord(disclosure.outputBudget).recentCompletedReturnedLimit === 5, "supervisor must expose output budget metadata", disclosure);
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
checks: [
|
||||
"supervisor output materially smaller than full",
|
||||
"recentCompleted capped",
|
||||
"prompt/body previews bounded",
|
||||
"drill-down commands preserved",
|
||||
"full view remains detailed",
|
||||
],
|
||||
supervisorChars: supervisorBody.length,
|
||||
fullChars: fullBody.length,
|
||||
};
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
process.stdout.write(`${JSON.stringify(runCodeQueueSupervisorDisclosureContract(), null, 2)}\n`);
|
||||
}
|
||||
@@ -30,6 +30,7 @@ const syntaxFiles = [
|
||||
"scripts/host-codex-commander-no-daemon-smoke-contract-test.ts",
|
||||
"scripts/host-codex-commander-skeleton-contract-test.ts",
|
||||
"scripts/auth-broker-contract-test.ts",
|
||||
"scripts/code-queue-supervisor-disclosure-contract-test.ts",
|
||||
"src/components/frontend/src/index.ts",
|
||||
"src/components/frontend/src/app.tsx",
|
||||
"src/components/frontend/src/decision-center.tsx",
|
||||
@@ -303,6 +304,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
|
||||
fileItem("scripts/code-queue-trace-summary-contract-test.ts"),
|
||||
fileItem("scripts/code-queue-pr-preflight-contract-test.ts"),
|
||||
fileItem("scripts/code-queue-submit-routing-contract-test.ts"),
|
||||
fileItem("scripts/code-queue-supervisor-disclosure-contract-test.ts"),
|
||||
fileItem("scripts/host-codex-commander-skeleton-contract-test.ts"),
|
||||
fileItem("scripts/host-codex-commander-no-daemon-smoke-contract-test.ts"),
|
||||
fileItem("scripts/provider-runner-triage-contract-test.ts"),
|
||||
@@ -338,6 +340,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
|
||||
items.push(commandItem("code-queue:trace-summary-contract", ["bun", "scripts/code-queue-trace-summary-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:pr-preflight-contract", ["bun", "scripts/code-queue-pr-preflight-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:submit-routing-contract", ["bun", "scripts/code-queue-submit-routing-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:supervisor-disclosure-contract", ["bun", "scripts/code-queue-supervisor-disclosure-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("host-codex-commander:skeleton-contract", ["bun", "scripts/host-codex-commander-skeleton-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("host-codex-commander:no-daemon-smoke-contract", ["bun", "scripts/host-codex-commander-no-daemon-smoke-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("provider:runner-triage-contract", ["bun", "scripts/provider-runner-triage-contract-test.ts"], 30_000));
|
||||
@@ -362,6 +365,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
|
||||
items.push(skippedItem("code-queue:trace-summary-contract", "Code Queue trace summary contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:pr-preflight-contract", "Code Queue PR preflight contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:submit-routing-contract", "Code Queue submit routing contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:supervisor-disclosure-contract", "Code Queue supervisor disclosure contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("host-codex-commander:skeleton-contract", "host Codex commander skeleton contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("host-codex-commander:no-daemon-smoke-contract", "host Codex commander no-daemon smoke contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("provider:runner-triage-contract", "Provider runner triage contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
|
||||
+255
-13
@@ -12,6 +12,10 @@ const defaultOutputLimit = 20;
|
||||
const defaultTextPreviewChars = 12_000;
|
||||
const defaultTasksLimit = 20;
|
||||
const maxTasksLimit = 100;
|
||||
const supervisorRecentCompletedLimit = 5;
|
||||
const supervisorPromptPreviewChars = 160;
|
||||
const supervisorBodyPreviewChars = 180;
|
||||
const supervisorRecentBodyPreviewChars = 80;
|
||||
const steerPromptPreviewChars = 320;
|
||||
const minimaxSubmitModel = "minimax-m2.7";
|
||||
const deepseekSubmitModel = "deepseek-chat";
|
||||
@@ -187,7 +191,35 @@ interface CodexTasksEntry {
|
||||
};
|
||||
}
|
||||
|
||||
interface CodexTasksSection {
|
||||
interface CodexTasksSupervisorEntry {
|
||||
taskId: string;
|
||||
queueId: string | null;
|
||||
status: string | null;
|
||||
currentAttempt: number | null;
|
||||
updatedAt: string | null;
|
||||
finishedAt: string | null;
|
||||
unreadTerminal: boolean;
|
||||
issueRefs: string[];
|
||||
classification: {
|
||||
kind: "direct-progress" | "deployment-fix" | "verification" | "management-noise" | "documentation" | "unknown";
|
||||
labels: string[];
|
||||
managementNoise: boolean;
|
||||
reason: string;
|
||||
};
|
||||
prompt: Record<string, unknown>;
|
||||
lastMessage: Record<string, unknown> | null;
|
||||
queuedReason: Record<string, unknown> | null;
|
||||
commands: {
|
||||
show: string;
|
||||
detail: string;
|
||||
trace: string;
|
||||
output: string;
|
||||
full: string;
|
||||
read: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CodexTasksSection<T = CodexTasksEntry> {
|
||||
count: number;
|
||||
returned: number;
|
||||
truncated: boolean;
|
||||
@@ -195,8 +227,11 @@ interface CodexTasksSection {
|
||||
commands: {
|
||||
next: string | null;
|
||||
full: string;
|
||||
detailTemplate?: string;
|
||||
traceTemplate?: string;
|
||||
outputTemplate?: string;
|
||||
};
|
||||
items: CodexTasksEntry[];
|
||||
items: T[];
|
||||
}
|
||||
|
||||
interface CodexTasksDegraded {
|
||||
@@ -362,6 +397,10 @@ function textPreview(value: string, maxChars: number): Record<string, unknown> {
|
||||
};
|
||||
}
|
||||
|
||||
function compactInlinePreview(value: string, maxChars: number): Record<string, unknown> {
|
||||
return textPreview(value.replace(/\s+/gu, " ").trim(), maxChars);
|
||||
}
|
||||
|
||||
function fmtDuration(ms: unknown): string {
|
||||
const value = Number(ms);
|
||||
if (!Number.isFinite(value) || value < 0) return "--";
|
||||
@@ -1572,6 +1611,75 @@ function taskQueuedRunnable(task: Record<string, unknown>): boolean {
|
||||
return asRecord(task.queuedReason)?.code === "ready";
|
||||
}
|
||||
|
||||
function taskIssueRefs(task: Record<string, unknown>, summary: Record<string, unknown> | null): string[] {
|
||||
const text = [
|
||||
asString(task.displayPrompt),
|
||||
asString(task.basePrompt),
|
||||
asString(task.prompt),
|
||||
asString(summary?.initialPrompt),
|
||||
asString(summary?.basePrompt),
|
||||
asString(summary?.prompt),
|
||||
asString(summary?.lastError),
|
||||
asString(task.lastError),
|
||||
].join("\n");
|
||||
return Array.from(new Set(Array.from(text.matchAll(/#(\d{1,6})\b/gu)).map((match) => `#${match[1]}`))).slice(0, 8);
|
||||
}
|
||||
|
||||
function taskClassification(task: Record<string, unknown>, summary: Record<string, unknown> | null): CodexTasksSupervisorEntry["classification"] {
|
||||
const text = [
|
||||
asString(task.displayPrompt),
|
||||
asString(task.basePrompt),
|
||||
asString(task.prompt),
|
||||
asString(task.lastError),
|
||||
asString(summary?.lastError),
|
||||
asString(asRecord(summary?.lastAssistantMessage)?.text),
|
||||
].join("\n").toLowerCase();
|
||||
const matches = (pattern: RegExp): boolean => pattern.test(text);
|
||||
const labels: string[] = [];
|
||||
if (matches(/\b(?:gate|report|aggregator|runbook|contract|audit|review|brief|evidence|diagnostic|observability|visibility|preflight|smoke)\b|报告|审查|汇总|观测|诊断|预检|门禁/iu)) labels.push("management-or-verification");
|
||||
if (matches(/\b(?:deploy|deployment|prod|dev|release|artifact|ci|cd)\b|部署|发布|上线/iu)) labels.push("deployment");
|
||||
if (matches(/\b(?:fix|bug|repair|implement|feature|ui|frontend|backend|api|database|db|workbench|patch-panel|box-simu|gateway-simu)\b|修复|实现|用户|工作台|接线|仿真|数据库/iu)) labels.push("direct-work");
|
||||
if (matches(/\b(?:doc|docs|reference|markdown)\b|文档|参考/iu)) labels.push("documentation");
|
||||
if (labels.length === 0) labels.push("uncategorized");
|
||||
|
||||
if (labels.includes("management-or-verification") && !labels.includes("direct-work") && !labels.includes("deployment")) {
|
||||
return { kind: "management-noise", labels, managementNoise: true, reason: "matched report/gate/review/diagnostic terms without direct implementation or deployment terms" };
|
||||
}
|
||||
if (labels.includes("deployment")) {
|
||||
return { kind: "deployment-fix", labels, managementNoise: labels.includes("management-or-verification") && !labels.includes("direct-work"), reason: "matched deployment or artifact terms" };
|
||||
}
|
||||
if (labels.includes("direct-work")) {
|
||||
return { kind: "direct-progress", labels, managementNoise: false, reason: "matched implementation, user-visible, runtime, or repair terms" };
|
||||
}
|
||||
if (labels.includes("management-or-verification")) {
|
||||
return { kind: "verification", labels, managementNoise: true, reason: "matched verification/report terms; keep folded unless it blocks real work" };
|
||||
}
|
||||
if (labels.includes("documentation")) {
|
||||
return { kind: "documentation", labels, managementNoise: false, reason: "matched documentation terms" };
|
||||
}
|
||||
return { kind: "unknown", labels, managementNoise: false, reason: "no strong classifier term matched" };
|
||||
}
|
||||
|
||||
function supervisorLastMessage(summaryLastAssistant: unknown, maxChars: number): Record<string, unknown> | null {
|
||||
if (summaryLastAssistant === undefined || summaryLastAssistant === null) return null;
|
||||
const record = asRecord(summaryLastAssistant) ?? {};
|
||||
const text = asString(record.text);
|
||||
if (text.length === 0) {
|
||||
return {
|
||||
at: record.at ?? null,
|
||||
seq: record.seq ?? null,
|
||||
source: record.source ?? "none",
|
||||
...compactInlinePreview("", maxChars),
|
||||
};
|
||||
}
|
||||
return {
|
||||
at: record.at ?? null,
|
||||
seq: record.seq ?? null,
|
||||
source: record.source ?? "none",
|
||||
...compactInlinePreview(text, maxChars),
|
||||
};
|
||||
}
|
||||
|
||||
function taskWatchEntry(task: Record<string, unknown>, summary: Record<string, unknown> | null): CodexTasksEntry {
|
||||
const taskId = asString(task.id);
|
||||
const summaryCommands = summary === null ? null : asRecord(summary.commands);
|
||||
@@ -1610,6 +1718,40 @@ function taskWatchEntry(task: Record<string, unknown>, summary: Record<string, u
|
||||
};
|
||||
}
|
||||
|
||||
function taskSupervisorEntry(task: Record<string, unknown>, summary: Record<string, unknown> | null, bodyPreviewChars = supervisorBodyPreviewChars): CodexTasksSupervisorEntry {
|
||||
const taskId = asString(task.id);
|
||||
const summaryCommands = summary === null ? null : asRecord(summary.commands);
|
||||
const summaryLastAssistant = summary?.lastAssistantMessage ?? task.lastAssistantMessage;
|
||||
const showCommand = typeof summary?.cliHint === "string" && summary.cliHint.length > 0
|
||||
? summary.cliHint
|
||||
: `bun scripts/cli.ts codex task ${taskId}`;
|
||||
const traceCommand = typeof summary?.traceHint === "string" && summary.traceHint.length > 0
|
||||
? summary.traceHint
|
||||
: `bun scripts/cli.ts codex task ${taskId} --trace --tail --limit ${defaultTraceLimit}`;
|
||||
return {
|
||||
taskId,
|
||||
queueId: asString(task.queueId) || null,
|
||||
status: asString(task.status) || null,
|
||||
currentAttempt: typeof task.currentAttempt === "number" && Number.isFinite(task.currentAttempt) ? task.currentAttempt : null,
|
||||
updatedAt: asString(task.updatedAt) || null,
|
||||
finishedAt: asString(task.finishedAt) || null,
|
||||
unreadTerminal: taskUnreadTerminal(task),
|
||||
issueRefs: taskIssueRefs(task, summary),
|
||||
classification: taskClassification(task, summary),
|
||||
prompt: compactInlinePreview(asString(task.displayPrompt ?? task.basePrompt ?? task.prompt), supervisorPromptPreviewChars),
|
||||
lastMessage: supervisorLastMessage(summaryLastAssistant, bodyPreviewChars),
|
||||
queuedReason: compactQueuedReason(task.queuedReason),
|
||||
commands: {
|
||||
show: typeof summaryCommands?.show === "string" && summaryCommands.show.length > 0 ? summaryCommands.show : showCommand,
|
||||
detail: `bun scripts/cli.ts codex task ${taskId} --detail`,
|
||||
trace: typeof summaryCommands?.trace === "string" && summaryCommands.trace.length > 0 ? summaryCommands.trace : traceCommand,
|
||||
output: `bun scripts/cli.ts codex output ${taskId} --tail --limit ${defaultOutputLimit}`,
|
||||
full: `bun scripts/cli.ts codex task ${taskId} --full`,
|
||||
read: `bun scripts/cli.ts codex read ${taskId}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildTaskWatchSection(
|
||||
tasks: Record<string, unknown>[],
|
||||
summaries: Map<string, Record<string, unknown>>,
|
||||
@@ -1633,6 +1775,33 @@ function buildTaskWatchSection(
|
||||
};
|
||||
}
|
||||
|
||||
function buildSupervisorTaskSection(
|
||||
tasks: Record<string, unknown>[],
|
||||
summaries: Map<string, Record<string, unknown>>,
|
||||
limit: number,
|
||||
nextCommand: string | null,
|
||||
fullCommand: string,
|
||||
bodyPreviewChars = supervisorBodyPreviewChars,
|
||||
): CodexTasksSection<CodexTasksSupervisorEntry> {
|
||||
const visibleTasks = tasks.slice(0, limit);
|
||||
const items = visibleTasks.map((task) => taskSupervisorEntry(task, summaries.get(taskOverviewCandidateKey(task)) ?? null, bodyPreviewChars));
|
||||
const truncated = tasks.length > limit;
|
||||
return {
|
||||
count: tasks.length,
|
||||
returned: items.length,
|
||||
truncated,
|
||||
hasMore: truncated,
|
||||
commands: {
|
||||
next: truncated ? nextCommand : null,
|
||||
full: fullCommand,
|
||||
detailTemplate: "bun scripts/cli.ts codex task <taskId> --detail",
|
||||
traceTemplate: `bun scripts/cli.ts codex task <taskId> --trace --tail --limit ${defaultTraceLimit}`,
|
||||
outputTemplate: `bun scripts/cli.ts codex output <taskId> --tail --limit ${defaultOutputLimit}`,
|
||||
},
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
function collectTaskWatchDegraded(summaryErrors: Array<{ taskId: string; message: string }>, omittedTaskCount = 0): CodexTasksDegraded | null {
|
||||
if (summaryErrors.length === 0 && omittedTaskCount === 0) return null;
|
||||
return {
|
||||
@@ -1784,18 +1953,26 @@ function codexTasksOverviewResult(
|
||||
const allTasks = filterTasksForOptions(taskPage.tasks, options);
|
||||
const runningTasks = sortRunningWatchTasks(allTasks);
|
||||
const unreadCompletedTasks = sortCompletedWatchTasks(allTasks).filter((task) => taskUnreadTerminal(task));
|
||||
const recentCompletedTasks = options.unreadOnly ? [] : sortCompletedWatchTasks(allTasks);
|
||||
const recentCompletedTasks = options.unreadOnly ? [] : sortCompletedWatchTasks(allTasks).filter((task) => !taskUnreadTerminal(task));
|
||||
const queuedTasks = options.unreadOnly ? [] : sortQueuedWatchTasks(allTasks);
|
||||
const nextBeforeId = asString(taskPage.pagination.nextBeforeId) || null;
|
||||
const sourceHasMore = asBoolean(taskPage.pagination.hasMore);
|
||||
const nextCommand = sourceHasMore && nextBeforeId !== null ? taskListCommand({ ...options, beforeId: nextBeforeId }) : null;
|
||||
const fullCommand = taskListCommand({ ...options, view: "full" });
|
||||
const runningSection = buildTaskWatchSection(runningTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const unreadSection = buildTaskWatchSection(unreadCompletedTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const recentSection = buildTaskWatchSection(recentCompletedTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const queuedSection = buildTaskWatchSection(queuedTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const recentLimit = Math.min(options.limit, supervisorRecentCompletedLimit);
|
||||
const runningSection = buildSupervisorTaskSection(runningTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const unreadSection = buildSupervisorTaskSection(unreadCompletedTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const recentSection = buildSupervisorTaskSection(recentCompletedTasks, summaries, recentLimit, nextCommand, fullCommand, supervisorRecentBodyPreviewChars);
|
||||
const queuedSection = buildSupervisorTaskSection(queuedTasks, summaries, options.limit, nextCommand, fullCommand);
|
||||
const pagination = taskPage.pagination;
|
||||
const diagnostics = compactExecutionDiagnostics(asRecord(taskPage.queue)?.executionDiagnostics);
|
||||
const visibleSupervisorItems = [...runningSection.items, ...unreadSection.items, ...recentSection.items, ...queuedSection.items];
|
||||
const classifierCounts = visibleSupervisorItems.reduce((counts, item) => {
|
||||
const key = item.classification.kind;
|
||||
counts[key] = (counts[key] ?? 0) + 1;
|
||||
if (item.classification.managementNoise) counts.managementNoise = (counts.managementNoise ?? 0) + 1;
|
||||
return counts;
|
||||
}, {} as Record<string, number>);
|
||||
return {
|
||||
upstream,
|
||||
supervisor: {
|
||||
@@ -1820,6 +1997,13 @@ function codexTasksOverviewResult(
|
||||
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",
|
||||
outputBudget: {
|
||||
promptPreviewChars: supervisorPromptPreviewChars,
|
||||
bodyPreviewChars: supervisorBodyPreviewChars,
|
||||
recentCompletedReturnedLimit: recentLimit,
|
||||
recentCompletedBodyPreviewChars: supervisorRecentBodyPreviewChars,
|
||||
},
|
||||
fullCommand,
|
||||
next: nextCommand,
|
||||
rawOverview: `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview${tasksListQueryString(options)} --raw`,
|
||||
@@ -1831,6 +2015,7 @@ function codexTasksOverviewResult(
|
||||
recentCompleted: recentSection.count,
|
||||
queued: queuedSection.count,
|
||||
},
|
||||
classifierCounts,
|
||||
executionDiagnostics: diagnostics,
|
||||
degraded,
|
||||
commands: {
|
||||
@@ -1901,7 +2086,7 @@ function visibleTaskIdsForOverview(tasks: Record<string, unknown>[], options: Co
|
||||
return Array.from(new Set([
|
||||
...sortRunningWatchTasks(filtered).slice(0, options.limit),
|
||||
...sortCompletedWatchTasks(filtered).filter((task) => taskUnreadTerminal(task)).slice(0, options.limit),
|
||||
...sortCompletedWatchTasks(filtered).slice(0, options.limit),
|
||||
...sortCompletedWatchTasks(filtered).filter((task) => !taskUnreadTerminal(task)).slice(0, Math.min(options.limit, supervisorRecentCompletedLimit)),
|
||||
...sortQueuedWatchTasks(filtered).slice(0, options.limit),
|
||||
].map((task) => taskOverviewCandidateKey(task))))
|
||||
.filter((taskId) => taskId.length > 0);
|
||||
@@ -1915,6 +2100,10 @@ function codexTasksQuery(taskArgs: string[], fetcher: CodexResponseFetcher = cor
|
||||
return codexTasksOverviewResult(page, upstream, options, summaries, degraded);
|
||||
}
|
||||
|
||||
export function codexTasksQueryForTest(taskArgs: string[], fetcher: CodexResponseFetcher): unknown {
|
||||
return codexTasksQuery(taskArgs, fetcher);
|
||||
}
|
||||
|
||||
async function codexTasksQueryAsync(taskArgs: string[], fetcher: AsyncCodexResponseFetcher): Promise<unknown> {
|
||||
const options = parseTasksOptions(taskArgs);
|
||||
const byId = new Map<string, Record<string, unknown>>();
|
||||
@@ -2566,6 +2755,57 @@ function authBrokerNeededStatus(tokenCoverage: Record<string, unknown>, runtimeA
|
||||
};
|
||||
}
|
||||
|
||||
function activeRunnerDevContainerCapability(): Record<string, unknown> {
|
||||
const ghTokenPresent = typeof process.env.GH_TOKEN === "string" && process.env.GH_TOKEN.length > 0;
|
||||
const githubTokenPresent = typeof process.env.GITHUB_TOKEN === "string" && process.env.GITHUB_TOKEN.length > 0;
|
||||
const anyToken = ghTokenPresent || githubTokenPresent;
|
||||
return {
|
||||
scope: "current-cli-process",
|
||||
applicableWhen: "this command is running inside the active Code Queue runner/dev container",
|
||||
observed: true,
|
||||
ok: anyToken,
|
||||
ghTokenPresent,
|
||||
githubTokenPresent,
|
||||
credentialSource: ghTokenPresent ? "GH_TOKEN" : githubTokenPresent ? "GITHUB_TOKEN" : null,
|
||||
notEquivalentToSchedulerEnv: true,
|
||||
relationToRemotePreflight: "independent-scope; scheduler-runner-env auth-missing does not prove the active runner/dev container lacks GitHub PR capability",
|
||||
valuesPrinted: false,
|
||||
commands: {
|
||||
authStatus: "bun scripts/cli.ts gh auth status --repo pikasTech/unidesk",
|
||||
prCreateDryRun: "bun scripts/cli.ts gh pr create --repo pikasTech/unidesk --title <title> --body-file <file> --base master --head <head> --dry-run",
|
||||
prCommentDryRun: "bun scripts/cli.ts gh pr comment create <number> --repo pikasTech/unidesk --body-file <file> --dry-run",
|
||||
},
|
||||
interpretation: anyToken
|
||||
? "current CLI process has a GitHub token candidate; validate with gh auth status and PR dry-run before declaring this runner unable to create/comment PRs"
|
||||
: "current CLI process did not expose GH_TOKEN/GITHUB_TOKEN; this still does not prove another active runner/dev container lacks token coverage",
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightScopeBoundary(tokenCoverage: Record<string, unknown> | null): Record<string, unknown> {
|
||||
const schedulerScope = typeof tokenCoverage?.scope === "string" ? tokenCoverage.scope : "scheduler-runner-env";
|
||||
return {
|
||||
schedulerPreflightScope: schedulerScope,
|
||||
activeRunnerDevContainerScope: "current-cli-process",
|
||||
scopesAreIndependent: true,
|
||||
authMissingInterpretation: "auth-missing from codex pr-preflight --remote is scoped to the scheduler/runtime preflight surface; do not simplify it to 'the active runner cannot create PRs'",
|
||||
currentRunnerCheck: "use activeRunnerDevContainer plus bun scripts/cli.ts gh auth status --repo pikasTech/unidesk for the current dev container",
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function decoratePrPreflightScopeBoundary(record: Record<string, unknown>): Record<string, unknown> {
|
||||
const preflight = asRecord(record.preflight);
|
||||
const tokenCoverage = asRecord(preflight?.tokenCoverage ?? record.tokenCoverage);
|
||||
const scopeBoundary = prPreflightScopeBoundary(tokenCoverage);
|
||||
const activeRunnerDevContainer = activeRunnerDevContainerCapability();
|
||||
return {
|
||||
...record,
|
||||
scopeBoundary,
|
||||
activeRunnerDevContainer,
|
||||
...(preflight === null ? {} : { preflight: { ...preflight, scopeBoundary } }),
|
||||
};
|
||||
}
|
||||
|
||||
function compactPrRuntimePreflight(preflight: Record<string, unknown>, options: CodexPrPreflightOptions): Record<string, unknown> {
|
||||
const pull = asRecord(preflight.pullRequestDelivery) ?? {};
|
||||
const tools = asRecord(pull.tools) ?? {};
|
||||
@@ -2615,6 +2855,7 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
},
|
||||
tokenCoverage,
|
||||
authBroker: authBrokerNeededStatus(tokenCoverage, authBrokerRuntime, systemGhBinary, unideskGhCli),
|
||||
scopeBoundary: prPreflightScopeBoundary(tokenCoverage),
|
||||
prCapabilityContract: {
|
||||
targetBranch,
|
||||
tokenSource: tokenCoverage.source,
|
||||
@@ -2711,11 +2952,12 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
limitations,
|
||||
risks,
|
||||
runnerDisposition: ok ? "ready" : "infra-blocked",
|
||||
activeRunnerDevContainer: activeRunnerDevContainerCapability(),
|
||||
recoveryHint: ok
|
||||
? tokenCoverage.source === "auth-broker"
|
||||
? "Runner PR workflow has auth-broker coverage for GitHub REST preflight; real PR creation still requires commander authorization."
|
||||
: "Runner PR workflow has env-token coverage for the scheduler."
|
||||
: "Configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN into the Code Queue scheduler runtime secret for the target queue, then rerun this preflight before creating a PR.",
|
||||
: "Scheduler preflight lacks GitHub auth coverage. Configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN into the scheduler runtime secret for scheduler-scoped admission; separately check activeRunnerDevContainer and gh auth status before declaring the current runner unable to create/comment PRs.",
|
||||
commands: {
|
||||
local: "bun scripts/cli.ts gh auth status --repo pikasTech/unidesk",
|
||||
runner: "bun scripts/cli.ts codex pr-preflight --remote",
|
||||
@@ -2815,7 +3057,7 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
const remoteRecord = asRecord(remoteResponse);
|
||||
if (remoteRecord !== null) {
|
||||
if (remoteRecord.ok === false) {
|
||||
return {
|
||||
return decoratePrPreflightScopeBoundary({
|
||||
...remoteRecord,
|
||||
controlPlane: {
|
||||
...(asRecord(remoteRecord.controlPlane) ?? {}),
|
||||
@@ -2827,9 +3069,9 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
},
|
||||
localObservation: localRecord,
|
||||
remoteObservation: remoteRecord,
|
||||
};
|
||||
});
|
||||
}
|
||||
return {
|
||||
return decoratePrPreflightScopeBoundary({
|
||||
...remoteRecord,
|
||||
controlPlane: {
|
||||
...(asRecord(remoteRecord.controlPlane) ?? {}),
|
||||
@@ -2841,7 +3083,7 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
},
|
||||
localObservation: localRecord,
|
||||
remoteObservation: remoteRecord,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
if (localRecord?.ok !== true) {
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ export function rootHelp(): unknown {
|
||||
{ command: "codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue queueId] [--provider-id id] [--cwd path] [--model model] [--execution-mode mode] [--max-attempts N] [--reference-task-id id] [--dry-run]", description: "Submit a Code Queue task through backend-core -> code-queue proxy; --dry-run shows the structured request without enqueueing." },
|
||||
{ command: "codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/<name>] [--pr-create-dry-run --pr-create-dry-run-head <head>] [--issue N]", description: "Read-only PR admission check against the D601 scheduler/runner token, GitHub egress, repo visibility, optional push dry-run, and PR body/create dry-run guard." },
|
||||
{ command: "codex task <taskId> [--detail] [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]", description: "Fetch the bounded review view by default: original prompt, final response, and drill-down commands; detail and trace are opt-in." },
|
||||
{ command: "codex tasks [--view supervisor|full] [--queue id] [--status status[,status]] [--unread|--unread-only] [--limit N] [--before-id id]", description: "Show the bounded supervisor view by default: running, unread terminal, recent completed, queued, diagnostics, and drill-down commands." },
|
||||
{ command: "codex tasks [--view supervisor|full] [--queue id] [--status status[,status]] [--unread|--unread-only] [--limit N] [--before-id id]", description: "Show the low-noise supervisor view by default: compact task rows, capped recent completions, diagnostics, and drill-down commands; use --view full for detailed rows." },
|
||||
{ command: "codex output <taskId> [--tail|--from-start|--after-seq N|--before-seq N --limit N] [--full-text]", description: "Fetch paged raw Code Queue output records by seq when a trace row has omitted command/output text." },
|
||||
{ command: "codex read <taskId>", description: "Mark one reviewed terminal task read; never run automatically as part of listing." },
|
||||
{ command: "codex dev-ready", description: "Fetch execution-container readiness, including sanitized skill injection status from /api/dev-ready." },
|
||||
|
||||
Reference in New Issue
Block a user