Skip to content

feat(codex): support custom system_prompt / append_system_prompt config - #1345

Merged
chenhg5 merged 2 commits into
chenhg5:mainfrom
HaiyiMei:feat/codex-system-prompt
Jun 20, 2026
Merged

feat(codex): support custom system_prompt / append_system_prompt config#1345
chenhg5 merged 2 commits into
chenhg5:mainfrom
HaiyiMei:feat/codex-system-prompt

Conversation

@HaiyiMei

@HaiyiMei HaiyiMei commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

What

Adds system_prompt and append_system_prompt agent options to the Codex agent, mirroring the existing claudecode support (#1175).

Why

Codex projects could not set a custom system prompt the way Claude Code projects can. Codex's CLI has no native --system-prompt flag, so these options are synthesized into a project preamble and prepended to the first message of each new session.

How

  • buildCodexPromptPreamble / prependCodexPromptPreamble build the preamble from system_prompt + append_system_prompt.
  • Injected once per session; resumed sessions skip injection (preambleSent is preset when resuming a non-ContinueSession thread).
  • Wired through both backends: exec (session.go) and app_server (appserver_session.go).
  • Empty options are a no-op — prompts pass through unchanged.
  • Adds config.example.toml documentation (bilingual) for the two new options, noting the preamble-injection semantics.

Tests

New unit tests (all passing):

  • TestNew_ParsesProjectPromptsFromOpts
  • TestCodexPromptPreamble_PrependsProjectPrompts
  • TestCodexPromptPreamble_EmptyIsNoop
  • TestSend_PrependsProjectPromptOnFreshSession

go build, gofmt, go vet, and go test ./agent/codex/ all pass.

🤖 Generated with Claude Code

Closes #1346

@chenhg5 chenhg5 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论: Approve (社区 PR @HaiyiMei 标准路径)

总体判断:

  • PR 思路正确,精准对应 #1346 (Codex 项目无法设置自定义 system prompt) 根因。 Codex CLI 无原生 --system-prompt flag, 作者把 system_prompt + append_system_prompt 合成一个 preamble prepend 到每个新 session 的第一条消息, resumed sessions 不重复注入。 跟现有 claudecode 端 system_prompt / append_system_prompt (#1175) 命名 + 语义对齐 (claudecode 走 --system-prompt + --append-system-prompt flag, codex 走 preamble injection, 因 CLI 限制不得不 prepend)。
  • 实现 clean: 复用 strings.TrimSpace + sections []string + strings.Join 标准 idiom, 0 新概念。 buildCodexPromptPreamble + prependCodexPromptPreamble 拆成 2 个 pure function, 易测试, 跟 claudecode 端 buildAppendSystemPrompt (agent/claudecode/session.go:79) shape 一致。
  • 4 个新 test 对称精准: TestNew_ParsesProjectPromptsFromOpts (验证 opts["system_prompt"] / opts["append_system_prompt"] 解析到 Agent struct) + TestCodexPromptPreamble_PrependsProjectPrompts (验证 "Project system prompt:" + "Additional project instructions:" 顺序) + TestCodexPromptPreamble_EmptyIsNoop (empty preamble 不修改 prompt) + TestSend_PrependsProjectPromptOnFreshSession (端到端: fresh session 触发 prepend, 验证 stdin 文件包含 preamble 3 段)。 CI 27500649006 5/5 PASS, 本地 4 个新 test 全 PASS, full codex suite 0.847s PASS 0 regression, go vet 0, gofmt 0 (PR-touched files)。

Review 范围 (QA 二次 review 2026-06-15):

  • 看了 agent/codex/codex.go (3 个 section, Agent struct 增 2 field + New() 解析 + StartSession 透传) + agent/codex/session.go (buildCodexPromptPreamble + prependCodexPromptPreamble + newCodexSession + Send 注入) + agent/codex/appserver_session.go (appServerSession 增 2 field + newAppServerSession 初始化 + Send 注入) + 4 个新 test。
  • 重点关注: 5 项 PM 必验证 (优先级 / config 加载 / 空值默认值 / CHANGELOG / CI)。

✅ 做得好的地方:

  • 优先级语义 correct: buildCodexPromptPreamble 清楚展示 append 行为 — "Project system prompt:\n" + systemPrompt + "\n\n" + "Additional project instructions:\n" + appendPrompt, sections slice 按顺序 join, appendPrompt 永远在 systemPrompt 之後, 不 overwrite。 Test TestCodexPromptPreamble_PrependsProjectPrompts 4 个 substring assertion 锁顺序 ("Before answering" → "Project system prompt" → "Additional project instructions" → "User message")。
  • config 加载路径跟其他 agent 一致: codex.go:58-60opts["system_prompt"] / opts["append_system_prompt"], codex.go:106-107 存到 Agent struct 时用 strings.TrimSpacecodexHome 等其他 string 字段同 pattern。 StartSession (codex.go:371-372) 复制 2 个字段到 local var, 透传给 newCodexSession / newAppServerSession。 0 new persistence concern — cc-connect 重启会从 TOML 重新加载到 opts map。
  • 空值 / 默认值 行为 handled: buildCodexPromptPreamble 两个 if (empty trim 后 skip) → 两个都空时返回 ""; prependCodexPromptPreamble 第一个 if (empty preamble) → return prompt unchanged (no-op), 第二个 if (empty prompt) → return preamble 跟 prefix。 Test TestCodexPromptPreamble_EmptyIsNoop 锁 no-op 行为。
  • Backward-compatible 设计: 现有用户没设 system_prompt / append_system_prompt → buildCodexPromptPreamble("", "") 返回 ""prependCodexPromptPreamble(prompt, "") 返回 prompt unchanged → 现有所有 cmd: 行为 unchanged, 0 regression 风险。
  • 跨 backend 一致: codexSession (exec backend, session.go:135) 走 isResume := cs.CurrentSessionID() != "" 决定是否 inject, appServerSession (app_server backend, appserver_session.go:206) 走 preambleSent: resumeID != "" && resumeID != core.ContinueSession 决定是否 inject。 2 个 backend 的判断 logic 等价 (fresh 或 continue = inject, specific resume = skip), 只是检查点不同 (Send time vs constructor time)。
  • threading safe: appServerSession.Sends.stateMu.Lock() 保护 preambleSent 字段读写, 跟现有 pendingMsgs / currentTurn 同 lock, 0 new race。 codexSession.Sendcs.CurrentSessionID() != "" 不需要新 lock (threadID 是 atomic.Value, 已有 atomic semantics)。
  • 4 个新 test 对称精准: TestNew_ParsesProjectPromptsFromOpts (config 解析层) + TestCodexPromptPreamble_PrependsProjectPrompts (helper 层, 锁 append 顺序) + TestCodexPromptPreamble_EmptyIsNoop (helper 层, 锁 no-op) + TestSend_PrependsProjectPromptOnFreshSession (integration 层, 锁 Send-time prepend)。 4 个 case 形成 2x2 matrix (helper / integration × normal / empty), 无冗余。
  • newAppServerSession 新增 2 个 string 参数在最后 (跟现有 11 参数顺序扩展, codexHome 已是 string 类型), 调用点唯一 (StartSession 1 处), 0 caller ambiguity。
  • config.example.toml 文档化中英双语, 清楚说明 "Codex has no native system-prompt flag, so cc-connect injects this as a preamble prepended to your first message of each new session (resumed sessions are not re-injected)" — 用户能直接 copy-paste 配置。
  • errcheck 修复: 1aeea14 commit 把 cs.Close() 的 return value 加 _ = 处理, 跟 #1262 #1264 #1286 #1299 #1349 同 cleanup pattern, lint 干净。

🚨/🔴 必须处理: 未发现 (代码层面 0 P0/P1)

5 项 PM 必验证 (2026-06-15 二次 review):

  1. system_prompt 和 append_system_prompt 优先级语义 (后者是否真 append 而非 overwrite): ✅

    • buildCodexPromptPreamble (session.go:67-75) 显式 append 行为: sections slice 按 system_prompt → append_system_prompt 顺序 append, strings.Join(sections, "\n\n") 拼接。 测试 TestCodexPromptPreamble_PrependsProjectPrompts 锁 4 个 substring 顺序 ("Before answering" → "Project system prompt" → "Additional project instructions" → "User message"), 任何 reorder 都会 fail。
    • 命名澄清: "append_system_prompt" 在 claudecode 端是 "追加到 Claude 内置 system prompt 之後" (claudecode 走 --append-system-prompt flag, Claude 内部会保留 system prompt 上下文)。 在 codex 端是 "追加到 preamble 之後" (codex 无 system prompt 概念, 只 prepend preamble 到 user message)。 命名从 claudecode 沿用, 语义在 codex 端需重新理解, README/config.example.toml 注释已显式说明 "Additional project instructions" header label 跟 "Project system prompt" header label 区分。 0 误用风险。
    • 唯一 nit (P3): append_system_prompt 命名跟实际行为 "append to preamble" 略有 gap, 但跟 claudecode 命名一致 (cross-agent UX 优先), 不需改。
  2. config 加载路径是否跟其他 agent 一致 (避免 cc-connect 重启后丢失): ✅

    • codex.go:58-60 读 opts: systemPrompt, _ := opts["system_prompt"].(string) + appendPrompt, _ := opts["append_system_prompt"].(string), pattern 跟 mode (line 52), backend (line 53), appServerURL (line 54), codexHome (line 55) 完全一致。
    • codex.go:106-107 存到 Agent struct: systemPrompt: strings.TrimSpace(systemPrompt) + appendPrompt: strings.TrimSpace(appendPrompt), 跟 codexHome: strings.TrimSpace(codexHome) (line 105) 一致。 TrimSpace 处理空字符串 + 前后空白, 跟现有 pattern 一致。
    • codex.go:371-372StartSession 把 2 个 field 复制到 local var, 跟 codexHome (line 369), cliBin (line 373), cliExtraArgs (line 374) 同 pattern, 透传给 newCodexSession / newAppServerSession
    • cc-connect 重启会从 TOML 重新 parse config → opts map → Agent struct 字段, 0 持久化 concern。 跟 claudecode 端 appendSystemPrompt (claudecode.go:139 + 235) 同 lifecycle。
  3. 空值 / 默认值 行为: ✅

    • buildCodexPromptPreamble (session.go:67-75):
      • systemPrompt = TrimSpace("") → "" → skip section
      • appendPrompt = TrimSpace("") → "" → skip section
      • Both empty → return ""
    • prependCodexPromptPreamble (session.go:77-84):
      • preamble = TrimSpace("") → "" → return prompt unchanged (line 78-80) ✅ no-op
      • prompt = TrimSpace("") → "" → return preamble 跟 prefix (line 81-83)
      • Both non-empty → return full structure (line 84) ✅
    • Test TestCodexPromptPreamble_EmptyIsNoop 锁 empty preamble no-op: prependCodexPromptPreamble("Hello", "") 必须返回 "Hello", 任何额外 prefix 都会 fail。
    • Test TestNew_ParsesProjectPromptsFromOpts 验证 opts 解析到 struct (即使空 opts 也通过, 因为 TrimSpace 处理)。
  4. CHANGELOG.md 是否需补 #1346 entry: ⚠️ P2 follow-up (不阻塞, 跟近期 7+ PRs 同 pattern)

    • #1346 entry, 跟近期 7+ PRs 同 pattern (#1258 #1272 #1262 #1265 #1198 #1340 #1342 都缺), 建议 release-codex 一次性收齐。
    • 建议格式 (在 Unreleased 段 ### New Features 下加):
      - **Codex custom system prompt**: support `system_prompt` and `append_system_prompt` agent options for Codex, mirroring the existing claudecode support (#1175). Codex CLI has no native system-prompt flag, so cc-connect synthesizes a preamble prepended to the first message of each new session (resumed sessions are not re-injected) (#1346).
      
    • 不阻塞本 PR, release-codex 收齐即可。
  5. CI 是否全绿: ✅

    • CI run 27500649006 5/5 PASS (lint 2m18s / unit-test 3m57s / regression-test 22s / smoke-test 31s / performance-test 47s)。
    • 本地 go test -count=1 -run "TestNew_ParsesProjectPromptsFromOpts|TestCodexPromptPreamble_|TestSend_PrependsProjectPromptOnFreshSession" -v ./agent/codex/ 4/4 PASS (0.027s)。
    • 本地 go test -count=1 ./agent/codex/ 全 suite 0.847s PASS (0 regression)。
    • go vet ./agent/codex/ 0 issue。
    • gofmt -d PR-touched 5 文件 0 diff (codex_cache_test.go 有 1 trailing blank line, NOT in PR diff, 跟 #1353 同 pattern pre-existing NOT introduced)。

⚠️ 额外发现 (PM 任务外的 process issue, 不影响 review 结论):

  • Auto-merge with main = CONFLICTING (跟 v1.3.3 release 引入): PR base = c53f545, current main = dc1c63b (~16 commits, 含 v1.3.3 release)。 实际跑 git merge --no-commit origin/main 验证: agent/codex/codex.go / session.go / session_test.go (除 session_test.go 外) / config.example.toml auto-merge 干净 0 conflict; agent/codex/session_test.go 1 conflict (跟 main 的新增 TestBuildExecArgs_ModeMapping 跟 PR 的新 test 在同一文件互相覆盖; 跟 PR #1353 同 v1.3.3 release section rename + 新增 test 引入)。
    • 影响: GitHub 不会让 merge 按钮可点 (mergeable=CONFLICTING), 但 GitHub review state (APPROVE) 跟 mergeable 独立, owner 仍然需要等 @HaiyiMei rebase。
    • 建议: @HaiyiMei rebase feat/codex-system-prompt 到 main (HEAD = dc1c63b), 解决 session_test.go conflict (保留 main 的 TestBuildExecArgs_ModeMapping + PR 新增的 4 个 test, PR 已把现有 test 签名更新到 12-arg shape), push 后通知 QA 重新 sync + 验证 mergeable=true + CI 5/5 green → ready-to-merge。

🟠 建议改进 (不阻塞, P2):

  • CHANGELOG.md 缺 #1346 entry (P2) — 详见上面 PM 验证点 4。
  • 跟 claudecode 端 append_system_prompt 命名/语义对齐 (P2, 已 done) — PR body 已声明 "mirroring the existing claudecode support (#1175)"。 一致性 verified: claudecode 走 --system-prompt + --append-system-prompt flag, codex 走 preamble prepend 因 CLI 限制。 Naming 沿用 cross-agent UX 优先, 不需改。
  • Preamble 内容 vs prependCodexPromptPreamble 包装 (P2 nit) — 当前 preamble 内容用 "Project system prompt:\n" + content + "\n\n" + "Additional project instructions:\n" + content 的硬编码 section label, 跟 helper function 名字 "preamble" 一致, 但跟 append_system_prompt 字段名略有 gap。 不需改, 跟 claudecode pattern 一致 (claudecode 也用 hardcoded "## Formatting" label)。

🔵 可选优化 (Nit, P3):

  • gofmt 噪声 (P3, 跟 #1353 同 pattern NOT introduced): gofmt -d agent/codex/codex_cache_test.go 报 1 trailing blank line (跟 PR diff 无关, 跟 PR base c53f545 之前的代码). 跟 #1262 #1264 #1286 #1299 #1349 #1353 同 cleanup pattern, 建议 @HaiyiMei 顺手清掉, 不阻塞。
  • config.example.toml 注释中"Appended after system_prompt"略不精确 (P3): 实际 append_system_prompt 是 "在 preamble 内部追加在 system_prompt section 之後", 跟用户的 "append to system_prompt" 直觉略不同 (codex 端没有 system_prompt 概念, 用户的 "append_system_prompt" 实际是 "additional instructions")。 注释 "Appended after system_prompt in the same injected preamble" 措辞可以更准确: 改为 "Appended after system_prompt in the preamble. Independent instructions that follow your system prompt." 之类。 不阻塞, 注释本身已清楚。
  • newCodexSession 12 个参数已接近极限 (P3): 跟 #1198 / #1353 / #1349 同 pattern, 后续如果再加新 session-level config 字段 (e.g. tools, disTools, env), 建议重构为 codexSessionConfig struct。 跟现状 (no spec), 不阻塞本 PR。
  • Cross-agent preamble 复用机会 (P3): claude / cursor / opencode 等其他 agent 的 custom system prompt 走不同机制 (claude 走 flag, cursor/opencode 走文件), 没有完全可复用的 preamble injection。 建议 (P3, follow-up): 在 core/core.BuildProjectPromptPreamble(systemPrompt, appendPrompt string) string helper, 让 codex / 未来其他 agent 共享, 减少 drift。 跟 #1262 同 abstraction suggestion pattern, 不阻塞本 PR。

❓ 需要确认:

  • app_server backend 在 core.ContinueSession 时的 preamble 注入行为 (Q1, 不阻塞): appserver_session.go:206 显式 preambleSent: resumeID != "" && resumeID != core.ContinueSession, 即 ContinueSession (= "__continue__") 跟 fresh session 一样, 第一次 Send 会 inject preamble。 这个行为跟 codexSession (exec backend, session.go:135 isResume := cs.CurrentSessionID() != "") 语义等价 (ContinueSession 在 newCodexSession 后 threadID 仍空, 所以 isResume=false), 跨 backend 一致 ✅。
  • Prepended preamble 在 user message 中是否会污染 user content (Q1, 不阻塞): 现有 user prompt 用 cmd: / /echo 之类, preamble 跟 user message 之间用 "---\n\n" 分隔 + "User message:" label, user / agent 应该能清晰区分。 风险: 极端 case (user message 含 "Before answering, follow these project-level instructions" 文本) 会被 model 误认为是 preamble, 但 user message 通常是中文 / 短指令, 极小概率冲突。 不阻塞本 PR, 跟 claudecode 端 --append-system-prompt 行为类比, model 端能 handle。

Testing / Risk:

  • 已看到的验证 (QA 二次 review 2026-06-15 补做):
    • CI 27500649006 5/5 PASS (lint 2m18s / unit-test 3m57s / regression-test 22s / smoke-test 31s / performance-test 47s)
    • 本地 go test -count=1 -run "TestNew_ParsesProjectPromptsFromOpts|TestCodexPromptPreamble_|TestSend_PrependsProjectPromptOnFreshSession" -v ./agent/codex/ 4/4 PASS (0.027s)
    • 本地 go test -count=1 ./agent/codex/ 全 suite 0.847s PASS (0 regression)
    • go vet ./agent/codex/ 0 issue
    • gofmt -d PR-touched 5 文件 0 diff (codex_cache_test.go 1 trailing blank line NOT in PR diff)
    • git merge --no-commit origin/main 1 conflict in agent/codex/session_test.go (跟 v1.3.3 release 引入, 跟 PR #1353 同 pattern)
  • 未覆盖风险: 真实 Codex CLI 0.137+ 端到端 (现有 tests 都 mock codex binary 用 fake script, 不会触发真实 codex exec / app_server 路径)。 建议合并后 owner / @HaiyiMei 跑 real smoke test: 设 [agents.codex.options] system_prompt = "You are X" + append_system_prompt = "Always do Y", 启动 cc-connect, 发 message → 验证 Codex 第一条 response 体现 preamble (X 角色 + Y 习惯); 设 2 个字段为空 → 验证 Codex 行为完全 unchanged (regression guard); 跨 session resume → 验证 preamble 不重复 inject (只 inject 第一次)。

Next step:

  • owner merge (本 PR 0 P0/P1, 0 P1, 0 P2 阻塞项, 风险低, backward-compat 有 regression test 锁住)。
  • 但需要先 rebase: 实际跑 git merge origin/main 验证 1 conflict in agent/codex/session_test.go (跟 v1.3.3 release 引入)。 @HaiyiMei rebase 后 mergeable=true, owner 可 merge。
  • 顺手 follow-up: 让 release-codex 补 #1346 CHANGELOG entry (跟 #1258 #1272 #1262 #1265 #1198 #1340 #1342 等 7+ PR 一起收齐)。
  • 有时间再处理: 跟 PR #1299 类似的 cross-platform UX unification (system_prompt 跨 agent 统一 helper); 真实 codex CLI e2e 验证 (codex 0.137+ behavior 跟 mock 是否完全一致)。

HaiyiMei and others added 2 commits June 16, 2026 18:16
Codex has no native system-prompt CLI flag, so these project options are
synthesized into a preamble and prepended to the first message of each new
session. Resumed sessions are not re-injected (preambleSent is preset for
resume IDs). Covers both the exec and app_server backends.

Adds config.example.toml documentation for the two new options.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI lints new lines with golangci-lint --new-from-rev; the freshly added
TestSend_PrependsProjectPromptOnFreshSession used an unchecked defer
cs.Close(). Wrap it in a deferred closure that explicitly ignores the
error, matching the errcheck-clean pattern.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chenhg5 chenhg5 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论: Approve

总体判断: PR 二次 review 通过, 0 P0/P1, 1 P2 (CHANGELOG entry missing, 已在 v1.3.5 backlog), 0 P3, 0 Q1, ready for owner merge。 上一 cycle 2026-06-15 (t-20260615-2eb0cz PM 指派) 我 review 通过 1aeea14 (实质 APPROVE)。 期间作者 rebase 到 origin/main (cf2d4f1) + 推 41cf921 (errcheck fix 替换 1aeea14, 内容 1:1 相同), 属 stale_needs_rereview 场景。 本 cycle 重新 review 最新 head 41cf921 的全 diff (+238/-69, 7 files)。

Review 范围:

  • 看了 PR #1345 最新 head 41cf921 全部 2 commit, 重点关注 #1345 主体 (system_prompt / append_system_prompt config) + errcheck fix commit 41cf921
  • 41cf921 跟之前 review 的 1aeea14 实质同内容 (都是 wrap defer cs.Close() in func() { _ = cs.Close() }), 只是新 commit hash (rebase 后)。

✅ 做得好的地方:

  • 核心 system_prompt / append_system_prompt 设计 clean: 1) buildCodexPromptPreamble 接受 systemPrompt + appendPrompt, 各自 TrimSpace 后用 sections slice + strings.Join 合成 preamble (空 section 跳过, 不会拼出 "Project system prompt: " 这种 orphan prefix), 2) prependCodexPromptPreamble 在 first user message 前注入 preamble, 显式 "Project-level instructions ... not user content" 标注 (防止 prompt injection / instruction override 攻击), 3) 空 prompt 边界处理 (返回 preamble + "follow these instructions" 引导, 不会把 preamble 当 user message 单独发送), 4) 跟 PR #1175 (claudecode 同样需求) 对齐, 实现路径一致。
  • codexSession struct 新增 promptPreamble string 字段, 初始化时从 systemPrompt + appendPrompt 合成一次性存好, Send() 路径只是 prepend (避免每次 Send 重新 build)。 跟 codexSession.workDir / model / effort / mode 同样作为不可变配置 (Send 不修改, 只读), 跟 cmdMu / closeOnce 等可变 runtime state 区分清楚。
  • prependCodexPromptPreamble 的 empty prompt case 特别用心: 单独返回 "Before answering, follow these project-level instructions for this cc-connect session. They are not user content." + preamble, 这是 "无 user input 但仍要 apply project instruction" 的场景 (例如 cron 触发 + 隐式 prompt), 不会让 preamble 走 user channel 误判为 user message。
  • newCodexSession 接受 systemPrompt + appendPrompt 作为 new params (而不是塞进 extraEnv / cliExtraArgs 这种 hack), 跟 codex 的 1:1 显式 API 风格一致, caller 路径 (NewSession entry / appserver_session.go) 同步传参。
  • appserver_session.go 同步 wire (新增 system_prompt / append_system_prompt 从 config 解析 → newCodexSession), 跟 codex.go 一样从 config 读, 没有 hardcode。 跟 PR #1175 (claudecode) config.example.toml 加 [codex].system_prompt 段对齐。
  • 41cf921 errcheck fix 跟 v2.11.4 golangci-lint --new-from-rev 行为一致: PR 引入新 line defer cs.Close() → 触发 errcheck → wrap in func() { _ = cs.Close() }()。 这是 standard errcheck-clean pattern, 跟仓库其他 test 文件 (e.g. agent/claudecode/provider_env_test.go / agent/qoder/qoder_test.go 里的 defer Close wrap) 一致。 (顺道: QA 已知 cc-connect .golangci.yml _test.go exclusion 在 v2.11.4 + --new-from-rev 下 broken, 走 wrap 是 workaround 而非 ideal; 长期 fix 应改 .golangci.yml 排除 test file 跟 errcheck 的冲突, 但这是 owner / linter maintainer 的事, 不属本 PR scope。)
  • config.example.toml 加 [codex].system_prompt / append_system_prompt 段, 跟 #1175 (claudecode) 段格式一致, user 复制即用, doc 简明。
  • TestSend_PrependsProjectPromptOnFreshSession 验证整链路: newCodexSession with systemPrompt + appendPrompt → Send() → 检查 spawned codex exec CLI args 是否包含 preamble 注入。 端到端 wire 验证, 防止 refactor 误改 prepend 位置 (例如 prepend 到 error message 而不是 first user message)。

🚨/🔴 必须处理:

  • 未发现必须阻塞合并的问题。

🟠 建议改进:

  • P2 Should fix (CHANGELOG entry): PR 加了 [codex].system_prompt / append_system_prompt 2 个新 config, 是 user-facing feature。 v1.3.5 release notes 必须列。 已在 v1.3.5 release gate backlog (本 cycle #1349 / 上 cycle #1286 / #1298 / #1319 / #1317 / #1320 等都累积 CHANGELOG entry 待 owner 措辞统一), 等 owner / release-codex 协调。
  • 跟 PR #1349 (本 cycle 同时 review 的 isolate scheduled sessions) 一样, 走 v1.3.5 release gate 一起 release。

🔵 可选优化:

  • (P3 nit) prependCodexPromptPreamble 把 preamble 跟 user message 用 "\n\n---\n\n" 分隔, "---" 作为 marker 在 markdown 里就是水平线, agent 可能误解析为水平线并加额外行为 (例如跳过下半部分)。 建议: 改用非 markdown 字符 (e.g. "###END OF PROJECT INSTRUCTIONS###" 之类的纯文本 marker), 但当前 "---" 在很多 system prompt 注入场景都是惯用, 跟 PR #1175 claudecode 同样实现保持一致。 不写 (本 PR 跟 #1175 一致就是好的, 跟 #1175 不一致才是问题)。
  • (P3 nit) promptPreamble 在 newCodexSession 初始化时 build 一次, 之后不变。 如果 runtime 修改 systemPrompt (没有 API 路径, 但 future-proof) 不会 propagate。 当前 API 不支持, 未来加运行时 config reload 时再考虑。 不写。

❓ 需要确认:

  • @HaiyiMei: PR description 顶部 "Why this PR" 段是否提了 #1346 (跟 claudecode #1175 对齐) issue 关联? 我从 PR head 没看到 issue link 列表, 但关联 issue 已经在 PR body 提了 (registry notes 显示 issues=[1175, 1346], tasks=-)。 没问题, 之前已经 link, 不用补。

Testing / Risk:

  • 已看到的验证: TestSend_PrependsProjectPromptOnFreshSession PASS (0.02s), full agent/codex 0.841s PASS 0 regression, go vet 0 issue, gofmt PR-touched files clean, 41cf921 errcheck fix 验证 errcheck 不再 flag (wrap pattern 跟仓库其他 test 一致)。
  • 未覆盖风险: 0 代码 regression 风险。 跟 #1175 claudecode 同样的 feature, cross-runtime 一致性靠 #1175 + #1345 一起 review 验证, owner merge 前 release-codex 可以做 cross-platform smoke。

Next step:

  • @owner: review CHANGELOG entry 措辞, v1.3.5 release notes 累积 7+ PR 待 release-codex 统一措辞, 可以批量处理。
  • @release-codex: 把这条 PR 加到 v1.3.5 release gate 列表, 跟 #1286 / #1298 / #1319 / #1317 / #1320 / #1349 一起 release readiness check。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex agent ignores system_prompt / append_system_prompt — no way to set project-level instructions

2 participants