Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
201 commits
Select commit Hold shift + click to select a range
dffc4bf
[codex] preserve fsmonitor for worktree Git reads (#26880)
tamird Jun 9, 2026
14660c2
Use server app auth requirements for remote plugin install (#27085)
xl-openai Jun 9, 2026
a304569
[codex] Return workspace directory installed plugins (#27098)
xl-openai Jun 9, 2026
fae2709
multi-agent: add path-based v2 activity tracking (#27007)
jif-oai Jun 9, 2026
1547785
app-server: clear stale thread watches after v2 agent interruption (#…
jif-oai Jun 9, 2026
a770e5b
[codex] Ignore pending PR review comments (#27080)
anp-oai Jun 9, 2026
18ce671
Avoid no-op backfill state writes (#26420)
zanie-oai Jun 9, 2026
6a9a49b
Avoid rereading rollout history during cold resume (#27031)
zanie-oai Jun 9, 2026
8a299fb
fix: Prevent /review crash when entering Esc on steer message (#22879)
canvrno-oai Jun 9, 2026
1026e9d
app-server: reject direct input to multi-agent v2 sub-agents (#27173)
jif-oai Jun 9, 2026
89ac3ec
Load selected executor skills through extensions (#27184)
jif-oai Jun 9, 2026
99da697
[codex] Test extension API contracts (#26835)
anp-oai Jun 9, 2026
a71e040
[codex-analytics] add extensible feature thread sources (#27063)
marksteinbrick-oai Jun 9, 2026
6e7ab52
[codex] Speed up local nextest runs (#26479)
anp-oai Jun 9, 2026
7a7cee1
fix: use plugin service route for remote uninstall (#27223)
ericning-o Jun 9, 2026
472619f
Add SOCKS5 TCP MITM coverage (#22685)
winston-openai Jun 9, 2026
36bf63a
Allow creating a new goal after completion (#26681)
etraut-openai Jun 9, 2026
8e69d29
Reduce TUI legacy core dependencies (#26711)
etraut-openai Jun 9, 2026
5a0f913
[1/4] Add Python goal routing foundation (#27110)
aibrahim-oai Jun 9, 2026
4ec3b8e
Route hosted Apps MCP through extensions (#27191)
jif-oai Jun 9, 2026
9e3081b
[codex] Characterize global instruction lifecycle (#26830)
anp-oai Jun 9, 2026
f574946
[codex] Report unusable MCP OAuth credentials as logged out (#26713)
anp-oai Jun 9, 2026
f2969f3
[codex] Handle Ctrl-C for non-TTY unified exec (#26734)
pakrym-oai Jun 9, 2026
cc8325f
Stop mirroring Codex user input into realtime (#27116)
guinness-oai Jun 9, 2026
9316acf
[2/4] Add private Python goal operations (#27111)
aibrahim-oai Jun 9, 2026
490340f
[codex] Retry streamable HTTP initialize failures (#25147)
ssetty-oai Jun 9, 2026
51b3cd5
[codex] Tighten MCP connection manager API visibility and order (#27257)
aibrahim-oai Jun 9, 2026
fb8f1ea
TUI Plugin Sharing 1 - add remote plugin identity (#26701)
canvrno-oai Jun 9, 2026
51fc4b0
feat: use provider defaults for memory models (#27129)
celia-oai Jun 9, 2026
5ac640a
Add spans to build_tool_router (#27094)
mchen-oai Jun 10, 2026
4a3eac2
Add per-session realtime model and version overrides (#24999)
guinness-oai Jun 10, 2026
608b8b1
[codex-analytics] emit goal lifecycle analytics (#27078)
marksteinbrick-oai Jun 10, 2026
e0cb4ed
[codex] Fix post-merge analytics integration failures (#27285)
anp-oai Jun 10, 2026
00a25e1
Add spans to run_turn (#27107)
mchen-oai Jun 10, 2026
a7b6bae
[codex] Make MCP connection startup fallible (#27261)
aibrahim-oai Jun 10, 2026
0ffcefa
feat: keep child MCP warnings out of parent transcript (#27174)
jif-oai Jun 10, 2026
9cd11e9
Use plugin-service MCP as the hosted plugin runtime (#27198)
jif-oai Jun 10, 2026
ced1b8a
[codex] Tag multi-agent spawn metrics with version (#27375)
jif-oai Jun 10, 2026
d2f6d23
Remove async-trait from extension contributors (#27383)
jif-oai Jun 10, 2026
41b4fab
Use latest-wins MCP manager replacement (#27259)
charliemarsh-oai Jun 10, 2026
30ddb33
[codex] Store compact window id in rollout (#27264)
pakrym-oai Jun 10, 2026
0428e20
[codex] add io PathUri native conversion APIs (#27280)
anp-oai Jun 10, 2026
24aee3e
[codex] link Windows releases with LLD (#27315)
tamird Jun 10, 2026
c365b8a
Reduce archive rollout lookup CPU (#27276)
etraut-openai Jun 10, 2026
db531b4
[codex] Outline ToolExecutor handler bodies (#27299)
anp-oai Jun 10, 2026
2ef007d
Index visible thread list ordering (#27391)
zanie-oai Jun 10, 2026
d3abd87
Fix compressed rollout search path matching (#27407)
jif-oai Jun 10, 2026
2704ece
[codex] Remove async_trait from ToolExecutor (#27304)
anp-oai Jun 10, 2026
a1a8807
Add app-server background terminal process APIs (#26041)
etraut-openai Jun 10, 2026
a19d43a
Add app-server `thread/delete` API (#25018)
etraut-openai Jun 10, 2026
3691fe5
fix: Auto-recover from corrupted sqlite databases (#26859)
ddr-oai Jun 10, 2026
636cc11
[codex] remove blocking external agent migration flow (#27064)
stefanstokic-oai Jun 10, 2026
4241544
[codex] Raise app-server recursion limit (#27421)
anp-oai Jun 10, 2026
ccf1a18
[codex] Retry transient Guardian review failures (#27062)
kbazzi Jun 10, 2026
72667f4
[codex] extract external agent import picker renderer (#27065)
stefanstokic-oai Jun 10, 2026
020bf49
[plugins] Inject remote_plugin_id into install elicitations (#26409)
adaley-openai Jun 10, 2026
2e377ce
feat: make ThreadStore available on ThreadExtensionDependencies (#27439)
bolinfest Jun 10, 2026
1346811
Guard core test subprocess cleanup (#27343)
etraut-openai Jun 10, 2026
e352843
[codex] add external agent import picker UX (#27070)
stefanstokic-oai Jun 10, 2026
1deae7b
[codex] Move release platform rules into bazel package (#27321)
anp-oai Jun 10, 2026
b4445f2
[codex] add /import for external agents (#27071)
stefanstokic-oai Jun 10, 2026
7011044
[codex] Skip local curated discovery for remote plugins (#27311)
xl-openai Jun 10, 2026
980f60b
[codex] Preserve disabled MCP servers across runtime overlays (#27414)
provencher-oai Jun 10, 2026
387adc6
[codex] reuse release artifacts for npm staging (#27312)
tamird Jun 10, 2026
22dd6eb
Forward standalone assistant output to realtime (#27319)
guinness-oai Jun 10, 2026
7e5e41d
[codex] Add reusable OTEL gauge instruments (#27057)
richardopenai Jun 10, 2026
c722052
image: add shared data URL preparation utilities (#27245)
fjord-oai Jun 10, 2026
b39f943
[codex-analytics] emit internally started turn events (#27392)
marksteinbrick-oai Jun 10, 2026
ac9c534
[codex] Preserve build-script dependencies in rules_rs annotations (#…
anp-oai Jun 11, 2026
b389b95
core: cache turn diff rendering (#27489)
nornagon-openai Jun 11, 2026
1a9efd4
[codex] Remove redundant plugin app auth state (#27465)
xl-openai Jun 11, 2026
36fc79c
Remove TUI legacy core test_support dependencies (#27484)
etraut-openai Jun 11, 2026
9d87b77
Add session delete commands in CLI and TUI (#27476)
etraut-openai Jun 11, 2026
a6f435e
core: resize all history images behind a feature flag (#27247)
fjord-oai Jun 11, 2026
ab4ce40
Trim TUI legacy telemetry and migration dependencies (#27487)
etraut-openai Jun 11, 2026
658af93
[codex] Add token budget context feature (#27438)
pakrym-oai Jun 11, 2026
f1f9d0c
[codex] Expand hosted web search citation guidance (#27501)
yuning-oai Jun 11, 2026
728b824
tools: simplify default tool search text (#27526)
sayan-oai Jun 11, 2026
87ab018
[codex] Add new context window tool (#27488)
pakrym-oai Jun 11, 2026
06afd63
feat: add Bedrock API key as a managed auth mode (#27443)
celia-oai Jun 11, 2026
e614fad
[codex] Add comp_hash to model metadata (#27532)
aibrahim-oai Jun 11, 2026
4435ff2
core: strip image detail from Responses Lite requests (#27246)
fjord-oai Jun 11, 2026
8568559
[codex] Pass auth mode to plugin manager (#27517)
xl-openai Jun 11, 2026
ba4925b
[codex] Compact when comp_hash changes (#27520)
aibrahim-oai Jun 11, 2026
dac5f07
[codex] Add context remaining tool (#27518)
pakrym-oai Jun 11, 2026
5981251
image: preserve metadata when resizing prompt images (#27266)
fjord-oai Jun 11, 2026
383708e
[codex-analytics] report cached input tokens for v2 compaction (#27103)
rhan-oai Jun 11, 2026
b5a718e
Use generic search metadata for dynamic tools (#27356)
sayan-oai Jun 11, 2026
8d9f33c
[codex-analytics] Emit structured compaction codex errors (#27082)
rhan-oai Jun 11, 2026
53b5019
[codex] Tune cloud config cache intervals (#26513)
alexsong-oai Jun 11, 2026
a287c5d
skills: make backend plugin skills invocable without an executor (#27…
jif-oai Jun 11, 2026
6754e77
skills: cache remote catalog failures per thread (#27403)
jif-oai Jun 11, 2026
273a4aa
core: enable remote compaction v2 by default (#27573)
jif-oai Jun 11, 2026
7b3eb8e
skills: expose remote skill resource tools (#27388)
jif-oai Jun 11, 2026
0870352
multi-agent: move concurrency guidance into v2 usage hints (#27569)
jif-oai Jun 11, 2026
e6757bb
nit: cap error (#27585)
jif-oai Jun 11, 2026
dd46ef1
test: cover referenced backend skill reads without an executor (#27404)
jif-oai Jun 11, 2026
4322e01
skills: render catalog locators by authority (#27591)
jif-oai Jun 11, 2026
7c23948
skills: decouple the skills extension from core (#27413)
jif-oai Jun 11, 2026
5e50e7e
[codex] publish npm packages concurrently (#27527)
tamird Jun 11, 2026
9163c0a
[codex] publish DotSlash alongside npm (#27528)
tamird Jun 11, 2026
f427801
[codex] download only release artifacts (#27529)
tamird Jun 11, 2026
1e5b87b
Remove TUI legacy Windows sandbox dependency (#27490)
etraut-openai Jun 11, 2026
df9dd22
Emit plugin ID on MCP tool call analytics events (#27483)
chrisdong-oai Jun 11, 2026
9d88e29
Print TUI session info on fatal exits (#27417)
etraut-openai Jun 11, 2026
52db447
lint: allow self-documenting builder arguments (#27507)
anp-oai Jun 11, 2026
eb76336
[codex] Propagate plugin app categories (#27420)
charlesgong-openai Jun 11, 2026
cc97839
[codex] add cross-platform filesystem adapter coverage (#27454)
anp-oai Jun 11, 2026
7fbbc9f
[codex] Surface runtime warnings in codex exec (#27415)
anp-oai Jun 11, 2026
b42bff2
[codex] revert concurrent npm publishing (#27639)
tamird Jun 11, 2026
267232f
feat: disable orchestrator skills for now (#27646)
jif-oai Jun 11, 2026
0b08bbb
[codex] Provide ARM64 MinGW powl compatibility support (#27323)
anp-oai Jun 11, 2026
4a05d3b
[codex] remove EnvironmentPathRef (#27433)
anp-oai Jun 11, 2026
b2a4e3b
[codex] migrate ExecutorFileSystem paths to PathUri (#27424)
anp-oai Jun 11, 2026
236b501
[codex] Load user instructions through an injected provider (#27101)
anp-oai Jun 11, 2026
4a5a676
Resolve MCP server registrations through a catalog (#27634)
jif-oai Jun 11, 2026
14df0e8
core: Consolidate Responses API Codex metadata (#27122)
owenlin0 Jun 11, 2026
b5f1bb7
[codex-rs] enforce PAT workspace restrictions (#27450)
cooper-oai Jun 11, 2026
d23bb22
[codex] migrate exec-server filesystem protocol to PathUri (#27653)
anp-oai Jun 11, 2026
7516eb5
Include thread id in token budget context (#27663)
pakrym-oai Jun 11, 2026
0d8dee9
[codex] Avoid duplicate hooks.json discovery with profiles (#26418)
abhinav-oai Jun 11, 2026
b7a5d81
feat: prefer managed Bedrock auth in model provider (#27689)
celia-oai Jun 11, 2026
e069153
Remove fs/join and fs/parent from exec-server protocol (#27700)
anp-oai Jun 11, 2026
eddc5c7
Warn when hooks.json has unsupported top-level fields (#26426)
abhinav-oai Jun 11, 2026
b2cc01f
[codex] Move persistence policy application into ThreadStore (#27318)
wiltzius-openai Jun 11, 2026
19ce639
Route image extension reads through turn environments v2 (#27498)
won-openai Jun 11, 2026
92d9036
Add spans to turn lifecycle gaps (#27623)
mchen-oai Jun 11, 2026
44403dd
tui: clear stale hook row after turn completion (#27619)
kotakem-openai Jun 12, 2026
1829ed1
Fix image extension PathUri conversion (#27711)
anp-oai Jun 12, 2026
5a56caf
[codex] Remove async_trait from first-party code (#27475)
anp-oai Jun 12, 2026
69b0f52
fix: Recover from sqlite directory being a file (#27719)
ddr-oai Jun 12, 2026
16c7c79
ci(v8): gate Windows source builds on relevant changes (#27715)
cconger Jun 12, 2026
e23d4df
[codex] parallelize release code generation (#27702)
tamird Jun 12, 2026
be338ee
[codex] resolve environment shell metadata eagerly (#27709)
pakrym-oai Jun 12, 2026
d61dfeb
feat(app-server): persist remote-control desired state (#27445)
apanasenko-oai Jun 12, 2026
78bab04
[1 of 3] Support long raw TUI goal objectives (#27508)
etraut-openai Jun 12, 2026
216ce03
Add request_user_input auto-resolution window contract (#27256)
shijie-oai Jun 12, 2026
aa46f2d
code-mode standalone: extract protocol and add host crate (#27724)
cconger Jun 12, 2026
a94deb5
Translate non-English issues (#27778)
etraut-openai Jun 12, 2026
7a19b14
Keep request_user_input direct-model only (#27316)
shijie-oai Jun 12, 2026
bf667c7
[codex] Load AGENTS.md from all bound environments (#27696)
anp-oai Jun 12, 2026
693082f
Make MCP server contributions thread-scoped (#27670)
jif-oai Jun 12, 2026
c09df9e
[code-mode] Reject remote image URLs from output helpers (#27732)
rka-oai Jun 12, 2026
267eacf
Add executor-owned plugin resolution (#27692)
jif-oai Jun 12, 2026
17b9f48
Extract shared plugin MCP config parsing (#27863)
jif-oai Jun 12, 2026
743a414
[codex] restore source-specific import copy (#27703)
stefanstokic-oai Jun 12, 2026
b65fe3d
fix: serialize auth environment tests (#27879)
jif-oai Jun 12, 2026
5b8e3c6
Reject transcript backtrack in side conversations (#27791)
etraut-openai Jun 12, 2026
3cac2e0
[ez][codex-rs] Support approvals reviewer in app defaults (#27075)
zamoshchin-openai Jun 12, 2026
c375dea
Use dependency groups for Python SDK tooling (#27538)
charliemarsh-oai Jun 12, 2026
096e5e7
Persist update dismissal without cache (#27783)
etraut-openai Jun 12, 2026
d735ef1
tui: Allow extra o's in /goal command (#27814)
btraut-openai Jun 12, 2026
94427aa
Use uv as Python SDK build backend (#27901)
charliemarsh-oai Jun 12, 2026
6652e82
realtime: add AVAS architecture override (#27720)
bakks Jun 12, 2026
8452022
chore: prompt MAv2 (#27919)
jif-oai Jun 12, 2026
52a50ae
sandboxing: migrate cwd inputs to PathUri (#27816)
anp-oai Jun 12, 2026
9600afb
[codex] expose remote plugin share URL (#27890)
ericning-o Jun 12, 2026
e26f734
[codex] unify apply patch parsing (#27913)
pakrym-oai Jun 12, 2026
b6baa77
Handle standalone image generation failures as terminal items (#27920)
won-openai Jun 12, 2026
76d8f20
[codex] Add size to internal filesystem metadata (#27927)
pakrym-oai Jun 12, 2026
b724f59
feat: add secret auth storage configuration (#27504)
celia-oai Jun 12, 2026
d1aaf78
[login] revoke existing auth before starting login (#27674)
cooper-oai Jun 12, 2026
7cc80b3
feat: add auth-specific encrypted secret namespaces (#27535)
celia-oai Jun 12, 2026
2ee854e
[codex] Add crate API surface review rule (#27939)
pakrym-oai Jun 12, 2026
a57087a
[codex] Align implicit skill reads with parser (#27926)
alexsong-oai Jun 12, 2026
3e2ee1d
fix(plugins) rm plugin descriptions (#23254)
dylan-hurd-oai Jun 12, 2026
8f2d641
Support plaintext agent messages (#27830)
jif-oai Jun 12, 2026
576f603
Remove TUI realtime voice support (#27801)
etraut-openai Jun 12, 2026
56c97e3
feat: use encrypted local secrets for CLI auth (#27539)
celia-oai Jun 12, 2026
4d17025
Warn for structured feature toggles (#27076)
canvrno-oai Jun 12, 2026
9915d34
feat: use encrypted local secrets for MCP OAuth (#27541)
celia-oai Jun 12, 2026
216dee1
[codex] add roles to realtime append text (#27936)
agamble-oai Jun 12, 2026
c0f1ec5
[2 of 3] Support long pasted text in TUI goals (#27509)
etraut-openai Jun 12, 2026
0605f9c
Add Guardian catalog diagnostics metadata (#27109)
won-openai Jun 12, 2026
fdd72e9
Specify platform support in AGENTS.md (#27966)
anp-oai Jun 12, 2026
5c48e31
[codex] parallelize Windows compression (#27855)
tamird Jun 12, 2026
1bd6b4c
Promote TUI unified mentions in composer to default mentions feature …
canvrno-oai Jun 12, 2026
7ebd107
[codex] Let generic test turns inherit their environment (#27972)
pakrym-oai Jun 12, 2026
eb46984
[codex] package Windows symbols in parallel (#27856)
tamird Jun 12, 2026
968a3ac
[codex] make PathUri::from_abs_path infallible (#27976)
anp-oai Jun 12, 2026
51483bb
[codex] parallelize Windows package archives (#27854)
tamird Jun 13, 2026
1460b50
[codex] stage npm packages concurrently (#27853)
tamird Jun 13, 2026
bacfc5e
[codex] add latency tracing spans (#27710)
rphilizaire-openai Jun 13, 2026
9e07892
[3 of 3] Support images in TUI goals (#27510)
etraut-openai Jun 13, 2026
c884536
feat(tui): reland token activity command (#27925)
fcoury-oai Jun 13, 2026
044c142
[codex] Limit app-based plugin suggestions to remote catalogs (#27988)
xl-openai Jun 13, 2026
aef40ad
[codex] Add auth mode to plugin manager constructor (#27652)
felixxia-oai Jun 13, 2026
5c8136f
[codex] Add hermetic Wine test support (#27964)
anp-oai Jun 13, 2026
5d7db08
[codex] Gate plugin MCP servers by auth route (#27459)
felixxia-oai Jun 13, 2026
b9dc3b7
feat(app-server): enforce managed remote control disable (#27961)
apanasenko-oai Jun 13, 2026
9d938a4
[codex] Add hermetic Wine exec-server test (#27937)
anp-oai Jun 13, 2026
640d61b
[codex] Send request-scoped turn state over WebSocket (#27996)
aibrahim-oai Jun 13, 2026
f297b9f
[codex] Send turn state through compact requests (#28002)
aibrahim-oai Jun 13, 2026
6506579
## New Features
aibrahim-oai Jun 15, 2026
cb91a2f
Merge upstream rust-v0.140.0
dkropachev Jul 4, 2026
31ed9b7
Skip feature spec check for upstream sync PRs
dkropachev Jul 4, 2026
1d68306
Fix upstream sync fallout
dkropachev Jul 4, 2026
18e132f
Fix release update prompt wiring
dkropachev Jul 4, 2026
bbf1fd7
Fix command popup macOS test compile
dkropachev Jul 4, 2026
b6ccba6
Fix TUI dead code under Bazel clippy
dkropachev Jul 4, 2026
5b77f8e
Fix argument comment lint UI fixture
dkropachev Jul 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 6 additions & 2 deletions .codex/skills/babysit-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Accept any of the following:
3. Inspect the `actions` list in the JSON response.
4. If `diagnose_ci_failure` is present, inspect failed run logs and classify the failure.
5. If the failure is likely caused by the current branch, patch code locally, commit, and push. Do not patch random flaky tests, CI infrastructure, dependency outages, runner issues, or other failures that are unrelated to the branch.
6. If `process_review_comment` is present, inspect surfaced review items and decide whether to address them.
6. If `process_review_comment` is present, inspect surfaced published review items and decide whether to address them.
7. If a review item is actionable and correct, patch code locally, commit, push, and then resolve the associated review thread only when allowed by the GitHub state mutation policy below.
8. Do not post replies to human-authored review comments/threads unless the user explicitly confirms the exact response. If a human review item is non-actionable, already addressed, or not valid, surface the item and recommended response to the user instead of replying on GitHub.
9. If the failure is likely flaky/unrelated and `retry_failed_checks` is present, rerun failed jobs with `--retry-failed-now`.
Expand Down Expand Up @@ -92,9 +92,13 @@ The watcher surfaces review items from:
- Inline review comments
- Review submissions (COMMENT / APPROVED / CHANGES_REQUESTED)

Only act on published feedback. Ignore review submissions in GitHub's `PENDING` state and inline
comments attached to those pending reviews. Do not mark pending review feedback as seen; it should
be eligible to surface after the reviewer submits the review.

It intentionally surfaces Codex reviewer bot feedback (for example comments/reviews from `chatgpt-codex-connector[bot]`) in addition to human reviewer feedback. Most unrelated bot noise should still be ignored.
For safety, the watcher only auto-surfaces trusted human review authors (for example repo OWNER/MEMBER/COLLABORATOR, plus the authenticated operator) and approved review bots such as Codex.
On a fresh watcher state file, existing pending review feedback may be surfaced immediately (not only comments that arrive after monitoring starts). This is intentional so already-open review comments are not missed.
On a fresh watcher state file, existing unaddressed published review feedback may be surfaced immediately (not only comments that arrive after monitoring starts). This is intentional so already-open review comments are not missed.

When you agree with a comment and it is actionable:

Expand Down
2 changes: 1 addition & 1 deletion .codex/skills/babysit-pr/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface:
display_name: "PR Babysitter"
short_description: "Watch PR review comments, CI, and merge conflicts"
default_prompt: "Babysit the current PR: monitor reviewer comments, CI, and merge-conflict status (prefer the watcher’s --watch mode for live monitoring); surface new review feedback before acting on CI or mergeability work, fix valid issues, push updates, and rerun flaky failures up to 3 times. Do not post replies to human-authored review comments unless the user explicitly confirms the exact response. Do not patch unrelated flaky tests, CI infrastructure, dependency outages, runner issues, or other failures that are not caused by the branch. Keep exactly one watcher session active for the PR (do not leave duplicate --watch terminals running). If you pause monitoring to patch review/CI feedback, restart --watch yourself immediately after the push in the same turn. If a watcher is still running and no strict stop condition has been reached, the task is still in progress: keep consuming watcher output and sending progress updates instead of ending the turn. Do not treat a green + mergeable PR as a terminal stop while it is still open; continue polling autonomously after any push/rerun so newly posted review comments are surfaced until a strict terminal stop condition is reached or the user interrupts."
default_prompt: "Babysit the current PR: monitor published reviewer comments, CI, and merge-conflict status (prefer the watcher’s --watch mode for live monitoring); ignore unpublished comments in pending GitHub reviews; surface new published review feedback before acting on CI or mergeability work, fix valid issues, push updates, and rerun flaky failures up to 3 times. Do not post replies to human-authored review comments unless the user explicitly confirms the exact response. Do not patch unrelated flaky tests, CI infrastructure, dependency outages, runner issues, or other failures that are not caused by the branch. Keep exactly one watcher session active for the PR (do not leave duplicate --watch terminals running). If you pause monitoring to patch review/CI feedback, restart --watch yourself immediately after the push in the same turn. If a watcher is still running and no strict stop condition has been reached, the task is still in progress: keep consuming watcher output and sending progress updates instead of ending the turn. Do not treat a green + mergeable PR as a terminal stop while it is still open; continue polling autonomously after any push/rerun so newly posted review comments are surfaced until a strict terminal stop condition is reached or the user interrupts."
3 changes: 3 additions & 0 deletions .codex/skills/babysit-pr/references/github-api-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Reruns only failed jobs (and dependencies) for a workflow run.
- Review submissions:
- `gh api repos/{owner}/{repo}/pulls/<pr_number>/reviews?per_page=100`

Use each inline comment's `pull_request_review_id` to find its parent review. Ignore parent reviews
whose `state` is `PENDING`, along with their inline comments, until the review is submitted.

## JSON fields consumed by the watcher

### `gh pr view`
Expand Down
28 changes: 25 additions & 3 deletions .codex/skills/babysit-pr/scripts/gh_pr_watch.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,11 +452,14 @@ def normalize_issue_comments(items):
return out


def normalize_review_comments(items):
def normalize_review_comments(items, review_states):
out = []
for item in items:
if not isinstance(item, dict):
continue
review_id = str(item.get("pull_request_review_id") or "")
if review_states.get(review_id) == "PENDING":
continue
line = item.get("line")
if line is None:
line = item.get("original_line")
Expand All @@ -481,6 +484,8 @@ def normalize_reviews(items):
for item in items:
if not isinstance(item, dict):
continue
if str(item.get("state") or "").upper() == "PENDING":
continue
out.append(
{
"kind": "review",
Expand Down Expand Up @@ -534,16 +539,33 @@ def fetch_new_review_items(pr, state, fresh_state, authenticated_login=None):
review_payload = gh_api_list_paginated(endpoints["review"], repo=repo)

issue_items = normalize_issue_comments(issue_payload)
review_comment_items = normalize_review_comments(review_comment_payload)
review_states = {
str(item.get("id")): str(item.get("state") or "").upper()
for item in review_payload
if isinstance(item, dict) and item.get("id") not in (None, "")
}
pending_review_ids = {
review_id for review_id, review_state in review_states.items() if review_state == "PENDING"
}
pending_review_comment_ids = {
str(item.get("id"))
for item in review_comment_payload
if isinstance(item, dict)
and item.get("id") not in (None, "")
and str(item.get("pull_request_review_id") or "") in pending_review_ids
}
review_comment_items = normalize_review_comments(review_comment_payload, review_states)
review_items = normalize_reviews(review_payload)
all_items = issue_items + review_comment_items + review_items

seen_issue = {str(x) for x in state.get("seen_issue_comment_ids") or []}
seen_review_comment = {str(x) for x in state.get("seen_review_comment_ids") or []}
seen_review = {str(x) for x in state.get("seen_review_ids") or []}
seen_review_comment.difference_update(pending_review_comment_ids)
seen_review.difference_update(pending_review_ids)

# On a brand-new state file, surface existing review activity instead of
# silently treating it as seen. This avoids missing already-pending review
# silently treating it as seen. This avoids missing already-published review
# feedback when monitoring starts after comments were posted.

new_items = []
Expand Down
68 changes: 68 additions & 0 deletions .codex/skills/babysit-pr/scripts/test_gh_pr_watch.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,74 @@ def test_recommend_actions_prioritizes_review_comments():
]


def test_pending_review_feedback_surfaces_only_after_publication(monkeypatch):
state = {
"seen_review_comment_ids": ["20"],
"seen_review_ids": ["10"],
}
review = {
"id": 10,
"user": {"login": "octocat"},
"author_association": "MEMBER",
"state": "PENDING",
"body": "Please rename this.",
"created_at": "2026-06-08T10:00:00Z",
"submitted_at": None,
"html_url": "https://github.com/openai/codex/pull/123#pullrequestreview-10",
}
review_comment = {
"id": 20,
"pull_request_review_id": 10,
"user": {"login": "octocat"},
"author_association": "MEMBER",
"body": "Please rename this.",
"created_at": "2026-06-08T10:00:00Z",
"path": "src/example.rs",
"line": 7,
"html_url": "https://github.com/openai/codex/pull/123#discussion_r20",
}

def fake_list(endpoint, **kwargs):
if endpoint.endswith("/issues/123/comments"):
return []
if endpoint.endswith("/pulls/123/comments"):
return [review_comment]
if endpoint.endswith("/pulls/123/reviews"):
return [review]
raise AssertionError(f"unexpected endpoint: {endpoint}")

monkeypatch.setattr(gh_pr_watch, "gh_api_list_paginated", fake_list)

assert (
gh_pr_watch.fetch_new_review_items(
sample_pr(),
state,
fresh_state=True,
authenticated_login="octocat",
)
== []
)
assert state["seen_review_comment_ids"] == []
assert state["seen_review_ids"] == []

review["state"] = "COMMENTED"
review["submitted_at"] = "2026-06-08T10:05:00Z"

published_items = gh_pr_watch.fetch_new_review_items(
sample_pr(),
state,
fresh_state=False,
authenticated_login="octocat",
)

assert {(item["kind"], item["id"]) for item in published_items} == {
("review", "10"),
("review_comment", "20"),
}
assert state["seen_review_comment_ids"] == ["20"]
assert state["seen_review_ids"] == ["10"]


def test_run_watch_keeps_polling_open_ready_to_merge_pr(monkeypatch):
sleeps = []
events = []
Expand Down
98 changes: 98 additions & 0 deletions .github/scripts/test_v8_canary_changes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import subprocess
import tempfile
import unittest
from pathlib import Path

from v8_canary_changes import changed_files
from v8_canary_changes import merge_base
from v8_canary_changes import resolved_v8_version
from v8_canary_changes import windows_source_required


class V8CanaryChangesTest(unittest.TestCase):
def test_resolved_v8_version(self) -> None:
cargo_lock = b"""\
[[package]]
name = "other"
version = "1.0.0"

[[package]]
name = "v8"
version = "149.2.0"
"""

self.assertEqual(resolved_v8_version(cargo_lock), "149.2.0")

def test_unrelated_cargo_manifest_change_does_not_require_source_build(
self,
) -> None:
self.assertFalse(
windows_source_required(
{"codex-rs/Cargo.toml"},
"149.2.0",
"149.2.0",
)
)

def test_v8_version_change_requires_source_build(self) -> None:
self.assertTrue(windows_source_required(set(), "149.2.0", "150.0.0"))

def test_module_helper_change_requires_source_build(self) -> None:
self.assertTrue(
windows_source_required(
{".github/scripts/rusty_v8_module_bazel.py"},
"149.2.0",
"149.2.0",
)
)

def test_manual_dispatch_requires_source_build(self) -> None:
self.assertTrue(
windows_source_required(
set(),
"149.2.0",
"149.2.0",
force=True,
)
)

def test_changed_files_excludes_changes_made_only_on_base_branch(self) -> None:
with tempfile.TemporaryDirectory() as temp_dir:
root = Path(temp_dir)
self.run_git(root, "init", "--initial-branch=main")
self.run_git(root, "config", "user.name", "Test User")
self.run_git(root, "config", "user.email", "test@example.com")

self.write_and_commit(root, "initial", "initial.txt")
common = self.run_git(root, "rev-parse", "HEAD")
self.run_git(root, "switch", "-c", "feature")
self.run_git(root, "switch", "main")
self.write_and_commit(root, "base-only", "base-only.txt")
base = self.run_git(root, "rev-parse", "HEAD")

self.run_git(root, "switch", "feature")
self.write_and_commit(root, "feature-only", "feature-only.txt")
head = self.run_git(root, "rev-parse", "HEAD")

self.assertEqual(
changed_files(base, head, root=root),
{"feature-only.txt"},
)
self.assertEqual(merge_base(base, head, root=root), common)

def write_and_commit(self, root: Path, contents: str, path: str) -> None:
(root / path).write_text(contents)
self.run_git(root, "add", path)
self.run_git(root, "commit", "-m", contents)

def run_git(self, root: Path, *args: str) -> str:
return subprocess.check_output(
["git", *args],
cwd=root,
stderr=subprocess.PIPE,
text=True,
).strip()


if __name__ == "__main__":
unittest.main()
104 changes: 104 additions & 0 deletions .github/scripts/v8_canary_changes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env python3

import argparse
import subprocess
import tomllib
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
WINDOWS_SOURCE_BUILD_PATHS = {
".github/scripts/rusty_v8_bazel.py",
".github/scripts/rusty_v8_module_bazel.py",
".github/scripts/v8_canary_changes.py",
".github/workflows/rusty-v8-release.yml",
".github/workflows/v8-canary.yml",
}


def resolved_v8_version(cargo_lock: bytes) -> str:
versions = sorted(
{
package["version"]
for package in tomllib.loads(cargo_lock.decode())["package"]
if package["name"] == "v8"
}
)
if len(versions) != 1:
raise ValueError(f"expected exactly one resolved v8 version, found: {versions}")
return versions[0]


def windows_source_required(
changed_files: set[str],
base_v8_version: str,
head_v8_version: str,
*,
force: bool = False,
) -> bool:
return (
force
or base_v8_version != head_v8_version
or not changed_files.isdisjoint(WINDOWS_SOURCE_BUILD_PATHS)
)


def git_output(*args: str, root: Path = ROOT) -> bytes:
return subprocess.check_output(["git", *args], cwd=root)


def v8_version_at_revision(revision: str, *, root: Path = ROOT) -> str:
return resolved_v8_version(
git_output("show", f"{revision}:codex-rs/Cargo.lock", root=root)
)


def merge_base(base: str, head: str, *, root: Path = ROOT) -> str:
return git_output("merge-base", base, head, root=root).decode().strip()


def changed_files(base: str, head: str, *, root: Path = ROOT) -> set[str]:
output = git_output(
"diff",
"--name-only",
"--no-renames",
f"{base}...{head}",
root=root,
)
return set(output.decode().splitlines())


def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--base")
parser.add_argument("--head")
parser.add_argument("--force", action="store_true")
return parser.parse_args()


def main() -> None:
args = parse_args()
if args.force:
required = True
reason = "manual workflow dispatch"
elif not args.base or not args.head:
raise SystemExit("--base and --head are required unless --force is set")
else:
files = changed_files(args.base, args.head)
base_version = v8_version_at_revision(merge_base(args.base, args.head))
head_version = v8_version_at_revision(args.head)
required = windows_source_required(files, base_version, head_version)
if base_version != head_version:
reason = f"v8 version changed from {base_version} to {head_version}"
else:
matched_paths = sorted(files & WINDOWS_SOURCE_BUILD_PATHS)
reason = (
", ".join(matched_paths) if matched_paths else "no relevant changes"
)

print(f"windows_source_required={str(required).lower()}")
print(f"windows_source_reason={reason}")


if __name__ == "__main__":
main()
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ jobs:
- name: Verify feature specs
env:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
shell: bash
run: |
set -euo pipefail
if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
if [[ "${PR_HEAD_REF}" == sync/upstream-* ]]; then
echo "Skipping feature spec verification for upstream sync branch ${PR_HEAD_REF}."
exit 0
fi
git fetch --no-tags --depth=1 origin "+refs/heads/${PR_BASE_REF}:refs/remotes/origin/${PR_BASE_REF}"
python3 .github/scripts/verify_feature_specs.py --base "origin/${PR_BASE_REF}" --head HEAD
else
Expand Down
Loading
Loading