feat(codex): default task query to review summary
This commit is contained in:
@@ -47,7 +47,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文
|
||||
- `bun scripts/cli.ts ci install/status/run/publish-backend-core/publish-user-service/run-dev-e2e/logs`:在 D601 原生 k3s 上安装和运行 Tekton CI,支持每 commit 检查、Code Queue 只读性能门禁、`CI.json` catalog 驱动的 backend-core 与 user-service commit-pinned 镜像发布和手动触发的 `origin/master:deploy.json#environments.dev` 临时 namespace e2e;catalog/producer/consumer 分工见 `docs/reference/cicd-standardization.md`,`run-dev-e2e` 的 Git 控制 runner、短 launcher 和 no-CD 边界见 `docs/reference/dev-ci-runner.md`,Tekton 规则见 `docs/reference/ci.md`。
|
||||
- `bun scripts/cli.ts codex deploy <commitId>`:旧 Code Queue 兼容部署入口已禁用,原因是它会绕过受控部署边界直连 D601 部署 Code Queue;规则见 `docs/reference/codex-deploy.md`。
|
||||
- `bun scripts/cli.ts codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue <id>]`:通过 backend-core 私有代理提交 Code Queue 任务;控制面默认走主 server `code-queue-mgr` 写入 PostgreSQL,`--dry-run` 可只检查请求体不入队,规则见 `docs/reference/cli.md`。
|
||||
- `bun scripts/cli.ts codex task <taskId>`:按 Code Queue 任务 ID 查询初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,便于新任务引用历史 session。
|
||||
- `bun scripts/cli.ts codex task <taskId>`:按 Code Queue 任务 ID 查询默认审阅摘要,只返回原始 prompt、最终 response、最后错误和渐进披露命令;需要工具调用、attempt/judge 和详细耗时时显式加 `--detail`。
|
||||
- `bun scripts/cli.ts codex judge <taskId> --attempt <n> [--dry-run]`:按指定 task/attempt 用与队列 worker 相同的上下文构建和 MiniMax judge 调用路径单步复现完成判定;`--dry-run` 只输出 prompt/payload 诊断。
|
||||
- `bun scripts/cli.ts codex steer <taskId> [prompt|--prompt-file path|--prompt-stdin] [--dry-run]`:通过 Code Queue 私有代理向运行中的 active turn 注入纠偏提示,正式替代底层 `microservice proxy ... /steer` 调用。
|
||||
- `bun scripts/cli.ts codex interrupt|cancel <taskId>`:通过 Code Queue 私有代理中断运行任务或取消 queued/retry_wait 任务,规则见 `docs/reference/cli.md`。
|
||||
|
||||
@@ -40,9 +40,9 @@ CLI 可以从 `master` 快速演进,但必须兼容 `deploy.json` 固定的 CI
|
||||
- `schedule list|get|runs|run|retry-run|delete|upsert-pgdata-backup` 管理 backend-core 定时任务和运行历史。`schedule runs --limit N` 是全局历史视图,返回 `scope=global` 和 `scheduleId=null`;`schedule runs <scheduleId> --limit N` 是指定 schedule 历史视图,返回 `scope=schedule` 和对应 `scheduleId`。CLI 必须拒绝 `schedule runs 50` 这类纯数字位置参数,并提示使用 `schedule runs --limit 50`,避免把空数组误判成“没有历史 run”。`schedule run <id> --wait-ms N` 触发同一 schedule,并且即使 wait 超时也必须返回 `newRunId` 和 `observeCommand`;`schedule retry-run <failedRunId>` 只接受 failed run,从原 run 反查 `scheduleId` 后重触发同一 schedule,并输出 `originalRunId`、`scheduleId`、`newRunId` 和 `observeCommand`。
|
||||
- `codex deploy <commitId>` 是旧 Code Queue 兼容部署入口,已禁用以防止维护通道直连 D601 部署 Code Queue;当前 dev 自动化只做 `ci run-dev-e2e` smoke,不提供 Code Queue CD,详细规则见 `docs/reference/codex-deploy.md`。
|
||||
- `codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue queueId] [--provider-id id] [--cwd path] [--model model] [--reasoning-effort effort] [--execution-mode mode] [--max-attempts N] [--reference-task-id id] [--dry-run]` 通过 backend-core 私有代理向稳定 `code-queue` 用户服务路径提交任务;prompt 必须且只能来自位置参数、文件或 stdin 之一,`--dry-run` 只返回结构化请求且不实际入队。提交确认和 dry-run 必须返回完整 prompt、字符数和 `truncated=false`,不能套用任务详情的预览截断策略,否则长任务 prompt 无法被人工验收。真实提交会经过本机本地串行化保护和短节流,避免同一指挥端并发 submit 把低内存主机或 `code-queue-mgr` 控制面打抖;返回值会附带 `submitConcurrencyGuard` 说明本次提交的锁与等待信息。backend-core 默认把提交、队列 CRUD、已读状态、历史摘要和轻量 Trace 读取分流到主 server `code-queue-mgr`,由它写入主 PostgreSQL;D601 scheduler 只轮询并执行已入库任务。
|
||||
- `codex task <taskId>` 通过 Code Queue 私有代理按任务 ID 查询结构化执行摘要;默认只返回有界 prompt/response 预览、执行 Provider、工作目录、最后 assistant message、最近工具调用摘要、attempt、judge、错误、耗时和 trace 翻页提示,适合在新队列任务中引用历史 session 且避免噪声爆炸。该摘要读取默认由主 server `code-queue-mgr` 从 PostgreSQL 返回,不依赖 D601 `code-queue-read` Service 可用。
|
||||
- `codex task <taskId>` 通过 Code Queue 私有代理按任务 ID 查询结构化审阅摘要;默认只返回任务身份、执行 Provider、工作目录、attempt 计数、原始 prompt、最终 response、最后错误和渐进披露命令,适合指挥官审阅完成未读任务且避免上下文爆炸。需要旧式详细摘要时显式加 `--detail`;需要完整 prompt/response 文本时加 `--full`;需要工具调用、judge、attempt 全量摘要时使用 `--detail --full --tool-limit N`。该摘要读取默认由主 server `code-queue-mgr` 从 PostgreSQL 返回,不依赖 D601 `code-queue-read` Service 可用。
|
||||
- `codex tasks [--view supervisor|full] [--queue id] [--status succeeded|running|queued|failed|canceled|judging|retry_wait[,..]] [--unread|--unread-only] [--limit N] [--before-id id]` 通过同一私有代理输出渐进式披露视图。默认 `supervisor` 只返回 `running`、`completedUnread`、`recentCompleted`、`queued` 和 `executionDiagnostics` 摘要,不嵌入完整 Trace、final response 或全量 overview;每个条目都带 `commands.show`、`commands.trace`、`commands.output`、`commands.read` 和 `commands.full`。`--unread` 是 `--unread-only` 的别名,必须只保留未读终态;`--status` 必须真实过滤支持的状态,未知参数或未知状态必须结构化失败,不能静默忽略。需要完整当前页任务简表时显式使用 `--view full` 或 `--full`,仍受 `--limit` 和 `--before-id` 分页约束。
|
||||
- `codex task <taskId> --trace --tail|--from-start|--after-seq N|--before-seq N --limit N` 按页拉取 Code Queue 的逻辑 trace;响应会返回 `nextAfterSeq`、`previousBeforeSeq`、`hasMore`、`hasBefore` 和下一页/上一页命令,默认 `--trace` 取最新一页,需要完整 prompt/最后 response 时加 `--full`。
|
||||
- `codex task <taskId> --trace --tail|--from-start|--after-seq N|--before-seq N --limit N` 按页拉取 Code Queue 的逻辑 trace;响应会返回 `nextAfterSeq`、`previousBeforeSeq`、`hasMore`、`hasBefore` 和下一页/上一页命令,默认 `--trace` 取最新一页,且仍以分页 trace 为主;需要完整 prompt/最终 response 时加 `--full`,需要详细 task 摘要时加 `--detail`。
|
||||
- `codex output <taskId> --tail|--from-start|--after-seq N|--before-seq N --limit N [--full-text]` 按原始 output seq 分页读取底层记录;当 trace 行提示 `commandOmittedLines`、`bodyOmittedLines` 或 `rawSeqs` 时,用该命令按 seq 补取完整信息,默认仍有单条文本预览上限,显式 `--full-text` 才返回该页全文。
|
||||
- `codex read <taskId>` 在人工审阅后标记单个终态任务已读;列表、overview 和 supervisor 视图只返回这个命令字段,不得自动执行,也不得批量清空未读状态。
|
||||
- `codex dev-ready` 查询 Code Queue `/api/dev-ready` 并返回有界 readiness 摘要,包括工具、Docker、Codex config、SSH 和 `devReady.skills`。`devReady.skills` 只暴露 `UNIDESK_SKILLS_PATH`、是否存在、是否只读、skillCount、`cli-spec` 是否可见和修复建议,不输出宿主 auth/token 文件内容。
|
||||
|
||||
@@ -132,12 +132,14 @@ bun scripts/code-queue-pr-preflight-example.ts --repo pikasTech/unidesk --base m
|
||||
- `bun scripts/cli.ts codex queues`:查看低噪声队列计数、active task id、完成未读队列、runnable 队列和控制面诊断;只有需要完整队列行时才加 `--full`。
|
||||
- `bun scripts/cli.ts codex tasks --unread --limit N`:查看完成未读审阅积压;`--unread` 与 `--unread-only` 等价,不能被静默忽略。
|
||||
- `bun scripts/cli.ts codex tasks --status succeeded --unread --limit N`:按具体终态过滤监督结果;不支持的 status filter 必须显式失败,不能扩大为未过滤结果。
|
||||
- `bun scripts/cli.ts codex task <taskId>`:查看 attempt、最后 assistant message、最后错误、cancel flag 和当前状态。
|
||||
- 当摘要不足时,再使用 `bun scripts/cli.ts codex task <taskId> --trace --limit N` 或 `codex output`。
|
||||
- `bun scripts/cli.ts codex task <taskId>`:默认只查看原始 prompt、最终 response、最后错误和 drill-down 命令,这是完成未读任务审阅的第一步。
|
||||
- 当默认审阅摘要不足时,再逐级使用 `bun scripts/cli.ts codex task <taskId> --detail`、`bun scripts/cli.ts codex task <taskId> --trace --limit N` 或 `codex output`。
|
||||
- 当 master 控制面状态和 D601 scheduler 状态看起来分裂时,使用 `docs/reference/observability.md` 中的活性规则判断。
|
||||
|
||||
默认 supervisor 视图必须保持低噪声。每个任务应带 `commands.show`、`commands.trace`、`commands.output`、`commands.full` 和 `commands.read`,让下一步渐进披露动作明确;默认不得嵌入完整 queue 列表、完整 final response、raw output 页或完整 trace 行。`commands.read` 只是在人工审阅后的建议命令,listing 命令绝不能自动执行。
|
||||
|
||||
完成未读任务的审阅也必须遵循渐进披露。指挥官默认只拉取原始 prompt 和最终 response,用它判断任务是否声称完成、是否有明显越界、是否缺少验收证据;不要默认拉完整 trace、全量 tool summary 或 raw output。只有当 final response 与目标不一致、证据不足、远端 commit 无法验证、任务疑似造假、或需要追溯失败原因时,才继续展开 `--detail`、分页 `--trace`、或按 seq 读取 `codex output`。这条规则的目标是降低上下文压力,同时保留通过多步查询拿到完整证据的能力。
|
||||
|
||||
队列诊断中的 `split-brain` 表示控制面/执行面观测分裂,不自动证明任务已经死亡。如果任务 heartbeat 新鲜且 trace 仍在推进,应把任务视为 live,继续监督,而不是 interrupt 或替换。队列摘要应显示 `effectiveLiveness=live`、`splitBrainLive=true` 和 `recommendedAction=continue-supervision`;如果 heartbeat expired/missing 或满足 stale-recovery 条件,应显示 `effectiveLiveness=at-risk`。
|
||||
|
||||
单次 `provider is not online`、SSH 超时、proxy 超时或 registry 请求失败只能证明“当前观察路径失败”,不能单独升级为 D601 全局离线、CI/CD 全局阻塞或业务任务不可推进。指挥官和 runner 必须用多信号裁决运行面状态,至少区分以下观察面:
|
||||
|
||||
@@ -17,6 +17,7 @@ const submitLockStaleMs = 120_000;
|
||||
const submitThrottleMs = nonNegativeIntegerEnv("UNIDESK_CODEX_SUBMIT_THROTTLE_MS", 2000);
|
||||
|
||||
interface CodexTaskOptions {
|
||||
detail: boolean;
|
||||
trace: boolean;
|
||||
traceLimit: number;
|
||||
traceMode: "tail" | "after" | "before";
|
||||
@@ -117,6 +118,7 @@ interface CodexTasksEntry {
|
||||
steer: string;
|
||||
read: string;
|
||||
full: string;
|
||||
detail: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -493,6 +495,19 @@ function compactLastAssistant(value: unknown, full: boolean): Record<string, unk
|
||||
};
|
||||
}
|
||||
|
||||
function compactFinalResponse(value: unknown, full: boolean): Record<string, unknown> {
|
||||
const record = compactLastAssistant(value, full);
|
||||
return {
|
||||
at: record.at,
|
||||
seq: record.seq,
|
||||
source: record.source,
|
||||
text: record.text,
|
||||
chars: record.chars,
|
||||
truncated: record.truncated,
|
||||
omittedChars: record.omittedChars,
|
||||
};
|
||||
}
|
||||
|
||||
function compactQueuedReason(value: unknown): Record<string, unknown> | null {
|
||||
const record = asRecord(value);
|
||||
if (record === null) return null;
|
||||
@@ -684,7 +699,53 @@ function compactSummary(summary: unknown, options: CodexTaskOptions, taskId: str
|
||||
nextPageTemplate: `bun scripts/cli.ts codex task ${taskId} --trace --after-seq <nextAfterSeq> --limit ${defaultTraceLimit}`,
|
||||
previousPageTemplate: `bun scripts/cli.ts codex task ${taskId} --trace --before-seq <previousBeforeSeq> --limit ${defaultTraceLimit}`,
|
||||
rawOutputTemplate: `bun scripts/cli.ts codex output ${taskId} --after-seq <rawSeq> --limit ${defaultOutputLimit}`,
|
||||
fullTextSummary: `bun scripts/cli.ts codex task ${taskId} --full --tool-limit ${Math.max(options.toolLimit, defaultToolLimit)}`,
|
||||
fullTextSummary: `bun scripts/cli.ts codex task ${taskId} --detail --full --tool-limit ${Math.max(options.toolLimit, defaultToolLimit)}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function compactReviewSummary(summary: unknown, options: CodexTaskOptions, taskId: string): Record<string, unknown> {
|
||||
const record = asRecord(summary) ?? {};
|
||||
const initialPrompt = asString(record.basePrompt || record.initialPrompt || record.prompt);
|
||||
const transcriptCount = asNumber(record.transcriptCount, 0);
|
||||
return {
|
||||
id: record.id ?? taskId,
|
||||
queueId: record.queueId ?? null,
|
||||
status: record.status ?? null,
|
||||
providerId: record.providerId ?? null,
|
||||
model: record.model ?? null,
|
||||
agentPort: record.agentPort ?? null,
|
||||
agentPortInfo: record.agentPortInfo ?? null,
|
||||
cwd: record.cwd ?? null,
|
||||
attempts: {
|
||||
currentAttempt: record.currentAttempt ?? null,
|
||||
maxAttempts: record.maxAttempts ?? null,
|
||||
currentMode: record.currentMode ?? null,
|
||||
},
|
||||
timing: record.timing ?? null,
|
||||
createdAt: record.createdAt ?? null,
|
||||
startedAt: record.startedAt ?? null,
|
||||
updatedAt: record.updatedAt ?? null,
|
||||
finishedAt: record.finishedAt ?? null,
|
||||
originalPrompt: textView(initialPrompt, options.full, 3000),
|
||||
finalResponse: compactFinalResponse(record.lastAssistantMessage, options.full),
|
||||
lastError: record.lastError ?? null,
|
||||
counts: {
|
||||
transcript: record.transcriptCount ?? null,
|
||||
output: record.outputCount ?? null,
|
||||
events: record.eventCount ?? null,
|
||||
},
|
||||
disclosure: {
|
||||
mode: "review",
|
||||
defaultScope: "original prompt and final response only; use detail/trace/output commands for progressive disclosure",
|
||||
fullPromptAndResponse: `bun scripts/cli.ts codex task ${taskId} --full`,
|
||||
detail: `bun scripts/cli.ts codex task ${taskId} --detail`,
|
||||
fullDetail: `bun scripts/cli.ts codex task ${taskId} --detail --full --tool-limit ${Math.max(options.toolLimit, defaultToolLimit)}`,
|
||||
traceTail: `bun scripts/cli.ts codex task ${taskId} --trace --tail --limit ${defaultTraceLimit}`,
|
||||
outputTail: `bun scripts/cli.ts codex output ${taskId} --tail --limit ${defaultOutputLimit}`,
|
||||
rawOutputTemplate: `bun scripts/cli.ts codex output ${taskId} --after-seq <rawSeq> --limit ${defaultOutputLimit}`,
|
||||
transcriptTotal: transcriptCount,
|
||||
transcriptMaxSeq: transcriptCount > 0 ? record.transcriptMaxSeq ?? null : null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -853,7 +914,7 @@ function compactTracePage(body: Record<string, unknown>, taskId: string, limit:
|
||||
|
||||
function parseTaskOptions(args: string[]): CodexTaskOptions {
|
||||
assertKnownOptions(args, {
|
||||
flags: ["--trace", "--tail", "--from-start", "--first", "--full", "--raw-summary"],
|
||||
flags: ["--detail", "--trace", "--tail", "--from-start", "--first", "--full", "--raw-summary"],
|
||||
valueOptions: ["--before-seq", "--beforeSeq", "--after-seq", "--afterSeq", "--trace-limit", "--limit", "--tool-limit"],
|
||||
}, "codex task");
|
||||
const beforeSeq = nullablePositiveNumberOption(args, ["--before-seq", "--beforeSeq"]);
|
||||
@@ -861,7 +922,9 @@ function parseTaskOptions(args: string[]): CodexTaskOptions {
|
||||
const fromStart = hasFlag(args, "--from-start") || hasFlag(args, "--first");
|
||||
const trace = hasFlag(args, "--trace") || beforeSeq !== null || args.some((arg) => arg === "--after-seq" || arg === "--afterSeq") || fromStart || hasFlag(args, "--tail");
|
||||
const traceMode = beforeSeq !== null ? "before" : fromStart || args.some((arg) => arg === "--after-seq" || arg === "--afterSeq") ? "after" : "tail";
|
||||
const rawSummary = hasFlag(args, "--raw-summary");
|
||||
return {
|
||||
detail: hasFlag(args, "--detail") || rawSummary,
|
||||
trace,
|
||||
traceLimit: positiveIntegerOption(args, ["--trace-limit", "--limit"], defaultTraceLimit, maxTraceLimit),
|
||||
traceMode,
|
||||
@@ -869,7 +932,7 @@ function parseTaskOptions(args: string[]): CodexTaskOptions {
|
||||
beforeSeq,
|
||||
toolLimit: positiveIntegerOption(args, ["--tool-limit"], defaultToolLimit, 500),
|
||||
full: hasFlag(args, "--full") || hasFlag(args, "--raw-summary"),
|
||||
rawSummary: hasFlag(args, "--raw-summary"),
|
||||
rawSummary,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -963,7 +1026,7 @@ function codexTaskSummary(taskId: string, options: CodexTaskOptions, fetcher: Co
|
||||
const summary = summaryResponse.body.summary;
|
||||
const result: Record<string, unknown> = {
|
||||
upstream: summaryResponse.upstream,
|
||||
summary: compactSummary(summary, options, taskId),
|
||||
summary: options.detail ? compactSummary(summary, options, taskId) : compactReviewSummary(summary, options, taskId),
|
||||
};
|
||||
if (options.rawSummary) result.rawSummary = summary;
|
||||
if (options.trace) {
|
||||
@@ -1124,6 +1187,7 @@ function taskWatchEntry(task: Record<string, unknown>, summary: Record<string, u
|
||||
steer: steerCommand,
|
||||
read: `bun scripts/cli.ts codex read ${taskId}`,
|
||||
full: `bun scripts/cli.ts codex task ${taskId} --full`,
|
||||
detail: `bun scripts/cli.ts codex task ${taskId} --detail`,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1462,7 +1526,7 @@ async function codexTaskSummaryAsync(taskId: string, options: CodexTaskOptions,
|
||||
const summary = summaryResponse.body.summary;
|
||||
const result: Record<string, unknown> = {
|
||||
upstream: summaryResponse.upstream,
|
||||
summary: compactSummary(summary, options, taskId),
|
||||
summary: options.detail ? compactSummary(summary, options, taskId) : compactReviewSummary(summary, options, taskId),
|
||||
};
|
||||
if (options.rawSummary) result.rawSummary = summary;
|
||||
if (options.trace) {
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ export function rootHelp(): unknown {
|
||||
{ command: "schedule upsert-pgdata-backup [--time HH:MM] [--remote-base /SERVER_DATA/UNIDESK_PG_DATA]", description: "Create or update the daily PGDATA physical backup task that uploads monthly rotated archives to Baidu Netdisk." },
|
||||
{ command: "codex deploy <commitId> [--provider-id D601] [--timeout-ms N]", description: "Disabled legacy Code Queue deploy path; use the dev-only artifact consumer instead." },
|
||||
{ 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 task <taskId> [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]", description: "Fetch a compact Code Queue task summary; trace rows are opt-in and paged with next/previous commands to avoid output explosion." },
|
||||
{ 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 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." },
|
||||
@@ -209,7 +209,7 @@ function codexHelp(): unknown {
|
||||
usage: [
|
||||
"bun scripts/cli.ts codex deploy <commitId> # disabled legacy deployment entry",
|
||||
"bun scripts/cli.ts codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue id] [--dry-run]",
|
||||
"bun scripts/cli.ts codex task <taskId> [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]",
|
||||
"bun scripts/cli.ts codex task <taskId> [--detail] [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]",
|
||||
"bun scripts/cli.ts codex tasks [--view supervisor|full] [--queue id] [--status succeeded,running] [--unread|--unread-only] [--limit N] [--before-id id]",
|
||||
"bun scripts/cli.ts codex output <taskId> [--tail|--from-start|--after-seq N|--before-seq N --limit N] [--full-text]",
|
||||
"bun scripts/cli.ts codex read <taskId>",
|
||||
|
||||
Reference in New Issue
Block a user