From 1862ece0b258ee941e7e9cb4d328d50a987fafcf Mon Sep 17 00:00:00 2001 From: Explero <502024240091@smail.nju.edu.cn> Date: Sat, 25 Jul 2026 21:51:32 +0800 Subject: [PATCH 1/2] fix(codex): set valid multi-agent wait defaults --- packages/cli/src/templates/codex/config.toml | 3 +++ packages/cli/src/utils/uninstall-scrubbers.ts | 6 +++++- packages/cli/test/commands/update.integration.test.ts | 4 +++- packages/cli/test/configurators/platforms.test.ts | 1 + packages/cli/test/templates/codex.test.ts | 9 +++++++++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/templates/codex/config.toml b/packages/cli/src/templates/codex/config.toml index 8584abe..5cfc190 100644 --- a/packages/cli/src/templates/codex/config.toml +++ b/packages/cli/src/templates/codex/config.toml @@ -38,10 +38,13 @@ project_doc_fallback_filenames = ["AGENTS.md"] # - max_concurrent_threads_per_session: keeps at most three bounded workers. # - min_wait_timeout_ms: 120000 ms = 2 min. A worker that needs longer must # report progress through its task record instead of holding the coordinator. +# - default_wait_timeout_ms must be at least the configured minimum; Codex +# rejects the project config at startup when its built-in default is lower. [features.multi_agent_v2] enabled = true max_concurrent_threads_per_session = 3 min_wait_timeout_ms = 120000 +default_wait_timeout_ms = 120000 # Native custom-agent dispatch uses the validated Hermes dispatch and Result # Envelope files. It works directly in the current project workspace. diff --git a/packages/cli/src/utils/uninstall-scrubbers.ts b/packages/cli/src/utils/uninstall-scrubbers.ts index 241bd7d..736dfcb 100644 --- a/packages/cli/src/utils/uninstall-scrubbers.ts +++ b/packages/cli/src/utils/uninstall-scrubbers.ts @@ -47,6 +47,8 @@ const LEGACY_CODEX_COMMENTS = new Set([ "[agents].max_threads (codex will reject the combination).", "NOT auto-enable the feature without it.", "report progress through its task record instead of holding the coordinator.", + "default_wait_timeout_ms must be at least the configured minimum; Codex", + "rejects the project config at startup when its built-in default is lower.", "short for Trellis subagents that routinely take 2-10 min. Hard", "ceiling is 3,600,000 (1 h).", "Native custom-agent dispatch cannot mechanically replace or validate the", @@ -66,6 +68,7 @@ const LEGACY_CODEX_TABLE_VALUES = new Map>([ "min_wait_timeout_ms = 480000", "max_concurrent_threads_per_session = 3", "min_wait_timeout_ms = 120000", + "default_wait_timeout_ms = 120000", ]), ], [ @@ -93,7 +96,8 @@ function isLegacyCodexComment(comment: string | null): boolean { comment.startsWith("`wait` tool") || comment.startsWith("`enabled = true`") || comment.startsWith("- max_concurrent_threads_per_session:") || - comment.startsWith("- min_wait_timeout_ms:") + comment.startsWith("- min_wait_timeout_ms:") || + comment.startsWith("- default_wait_timeout_ms") ); } diff --git a/packages/cli/test/commands/update.integration.test.ts b/packages/cli/test/commands/update.integration.test.ts index da02b6e..919f62a 100644 --- a/packages/cli/test/commands/update.integration.test.ts +++ b/packages/cli/test/commands/update.integration.test.ts @@ -355,7 +355,8 @@ describe("update() integration", () => { .replace( "max_concurrent_threads_per_session = 3", "max_concurrent_threads_per_session = 1", - ); + ) + .replace("default_wait_timeout_ms = 120000\n", ""); fs.writeFileSync(configPath, customized); await update({}); @@ -363,6 +364,7 @@ describe("update() integration", () => { const updated = fs.readFileSync(configPath, "utf-8"); expect(updated).toContain('model = "gpt-5.6-custom"'); expect(updated).toContain("max_concurrent_threads_per_session = 3"); + expect(updated).toContain("default_wait_timeout_ms = 120000"); expect(readHashesV2(hashFilePath())[configRelative]).toBe( computeHash(updated), ); diff --git a/packages/cli/test/configurators/platforms.test.ts b/packages/cli/test/configurators/platforms.test.ts index 2601b8b..47b79f6 100644 --- a/packages/cli/test/configurators/platforms.test.ts +++ b/packages/cli/test/configurators/platforms.test.ts @@ -354,6 +354,7 @@ describe("configurePlatform", () => { const written = fs.readFileSync(configPath, "utf-8"); expect(written).toContain('model = "gpt-5.6-custom"'); expect(written).toContain("max_concurrent_threads_per_session = 3"); + expect(written).toContain("default_wait_timeout_ms = 120000"); }); it("configurePlatform('codex') adds managed settings to an unmarked user config", async () => { diff --git a/packages/cli/test/templates/codex.test.ts b/packages/cli/test/templates/codex.test.ts index 30c789c..9cbcdc4 100644 --- a/packages/cli/test/templates/codex.test.ts +++ b/packages/cli/test/templates/codex.test.ts @@ -123,6 +123,15 @@ describe("codex getConfigTemplate", () => { expect(config.content).toContain("# TRELLIS:CODEX_MODEL_DEFAULTS:END"); expect(config.content).toContain('native_authority = "protocol"'); expect(config.content).not.toContain("strict_authority"); + + const minimum = Number( + config.content.match(/min_wait_timeout_ms\s*=\s*(\d+)/)?.[1], + ); + const defaultWait = Number( + config.content.match(/default_wait_timeout_ms\s*=\s*(\d+)/)?.[1], + ); + expect(minimum).toBeGreaterThan(0); + expect(defaultWait).toBeGreaterThanOrEqual(minimum); }); }); From 7c0ffd15c364c7780c7aaee815d8177e228a3d71 Mon Sep 17 00:00:00 2001 From: Explero <502024240091@smail.nju.edu.cn> Date: Sat, 25 Jul 2026 21:51:46 +0800 Subject: [PATCH 2/2] test(closure): remove wall-clock timeline ordering --- packages/cli/test/scripts/closure.integration.test.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cli/test/scripts/closure.integration.test.ts b/packages/cli/test/scripts/closure.integration.test.ts index 55184d1..08a3d1c 100644 --- a/packages/cli/test/scripts/closure.integration.test.ts +++ b/packages/cli/test/scripts/closure.integration.test.ts @@ -1306,11 +1306,20 @@ describe.skipIf(!hasPython())("Lean Research Closure CLI", () => { it("shows a compact timeline without raw dispatch audit payloads", () => { expect(plan(root, ["Result A"]).status).toBe(0); expect(run(root, "validate").status).toBe(0); + const latestTaskEvent = JSON.parse( + fs.readFileSync(path.join(taskDir, "hermes", "task-events.jsonl"), "utf-8") + .trim() + .split("\n") + .at(-1) ?? "{}", + ) as { timestamp?: string }; + const dispatchTimestamp = new Date( + Date.parse(latestTaskEvent.timestamp ?? "1970-01-01T00:00:00Z") + 1_000, + ).toISOString(); fs.writeFileSync( path.join(taskDir, "hermes", "dispatch_audit.jsonl"), `${JSON.stringify({ type: "dispatch_audit", - timestamp: "2026-07-25T12:00:00+00:00", + timestamp: dispatchTimestamp, job_id: "job-7", event: "result_confirmed", decision: "RAW_DECISION_MUST_NOT_APPEAR\n+++ a/dispatch.log",