diff --git a/plugins/codex/scripts/lib/codex.mjs b/plugins/codex/scripts/lib/codex.mjs index fead00cc4..f573db3d4 100644 --- a/plugins/codex/scripts/lib/codex.mjs +++ b/plugins/codex/scripts/lib/codex.mjs @@ -104,8 +104,16 @@ function looksLikeVerificationCommand(command) { ); } +// Prompts shaped by the gpt-5-4-prompting skill carry the job in a `` block, +// often after other instructions, so name the thread after that block when present. +function taskThreadNameSource(prompt) { + const text = String(prompt ?? ""); + const taskBlock = /([\s\S]*?)(?:<\/task>|$)/.exec(text)?.[1]; + return taskBlock?.trim() ? taskBlock : text; +} + function buildTaskThreadName(prompt) { - const excerpt = shorten(prompt, 56); + const excerpt = shorten(taskThreadNameSource(prompt), 56); return excerpt ? `${TASK_THREAD_PREFIX}: ${excerpt}` : TASK_THREAD_PREFIX; } diff --git a/tests/runtime.test.mjs b/tests/runtime.test.mjs index 8f276835b..cd1417f8d 100644 --- a/tests/runtime.test.mjs +++ b/tests/runtime.test.mjs @@ -175,6 +175,54 @@ test("task runs when the active provider does not require OpenAI login", () => { assert.match(result.stdout, /Handled the requested task/); }); +test("task names the thread after the block of a structured prompt", () => { + const repo = makeTempDir(); + const binDir = makeTempDir(); + installFakeCodex(binDir); + initGitRepo(repo); + const promptPath = path.join(repo, "prompt.txt"); + fs.writeFileSync( + promptPath, + [ + "Stay read-only.", + "", + "Fix the flaky login test", + "", + "", + "Return a numbered list.", + "" + ].join("\n"), + "utf8" + ); + + const result = run("node", [SCRIPT, "task", "--prompt-file", promptPath], { + cwd: repo, + env: buildEnv(binDir) + }); + + assert.equal(result.status, 0, result.stderr); + const fakeState = JSON.parse(fs.readFileSync(path.join(binDir, "fake-codex-state.json"), "utf8")); + assert.equal(fakeState.threads[0].name, "Codex Companion Task: Fix the flaky login test"); +}); + +test("task names the thread after the prompt when it has no block", () => { + const repo = makeTempDir(); + const binDir = makeTempDir(); + installFakeCodex(binDir); + initGitRepo(repo); + const promptPath = path.join(repo, "prompt.txt"); + fs.writeFileSync(promptPath, "check Map typing in the auth module", "utf8"); + + const result = run("node", [SCRIPT, "task", "--prompt-file", promptPath], { + cwd: repo, + env: buildEnv(binDir) + }); + + assert.equal(result.status, 0, result.stderr); + const fakeState = JSON.parse(fs.readFileSync(path.join(binDir, "fake-codex-state.json"), "utf8")); + assert.equal(fakeState.threads[0].name, "Codex Companion Task: check Map typing in the auth module"); +}); + test("task runs without auth preflight so Codex can refresh an expired session", () => { const repo = makeTempDir(); const binDir = makeTempDir();