Skip to content

fix(codex): stop a stopped proxy from locking users out of Codex sign-in - #5267

Merged
lidge-jun merged 7 commits into
devfrom
codex/260920-lane-h-codex-signin-lockout
Sep 20, 2026
Merged

lidge-jun merged 7 commits into
devfrom
codex/260920-lane-h-codex-signin-lockout

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

A Windows 11 user on 2.59.0 was locked out of Codex sign-in after setting up opencodex (#5261). Their screenshots show why: the default loopback integration does not add a provider, it points Codex's own built-in openai provider at the proxy by writing the codex-rs root key openai_base_url = "http://127.0.0.1:10100/v1" into ~/.codex/config.toml. That file is on disk and survives a reboot, so once the proxy process was gone Codex had one endpoint, it answered nothing, and there was no fallback. The screen said nothing about opencodex.

Recovery already existed and already worked with the proxy down — ocx restore needs no proxy, no management API and no network. Nothing told the user it existed. The injected config named no command, ocx status on a dead proxy offered only ways to restart the proxy, and no troubleshooting page covered the state. The reporter's assistant read the config, found three unexplained lines, and hand-deleted them along with the catalog file — which is the one repair that makes things worse, because a model_catalog_json pointing at a file that no longer exists stops Codex loading its config at all.

This makes the failure detectable and the recovery discoverable. Excluding sign-in from the proxy path is not expressible: openai_base_url is a single key for a single built-in provider, and when the proxy is down no scoping of it helps.

  • The injected routing names its own undo. Markers become # Auto-injected by opencodex (undo: ocx restore). Every ownership predicate matches the marker as a substring rather than by equality, so configs written by earlier builds are still recognized, stripped and restored unchanged; an in-place rewrite refreshes the line, so an existing install gains the hint on its next ocx start. Scope is routing only — prompt layers keep the bare marker, because ocx restore is not what undoes those.
  • ocx status offers the other half of the choice. With the proxy down over routing opencodex owns, the report now says sign-in fails too and names the command that does not require the proxy to come back. Routing opencodex does not own is excluded, since ocx restore would not remove someone else's local gateway.
  • A troubleshooting page for the state, with both ways out, the manual edit for someone without the CLI, and an explicit warning against deleting the catalog pointer on its own.

Before / after, same file, proxy stopped:

-# Auto-injected by opencodex
+# Auto-injected by opencodex (undo: ocx restore)
 openai_base_url = "http://127.0.0.1:10100/v1"

Not closing #5261

This removes the lockout's dead end, not every path into it. Left open deliberately, each being a separate change with its own risk and none of them what traps the user on its own:

  • The Codex shim runs ocx ensure with output discarded and || true, then launches Codex regardless (src/codex/shim-templates.ts:134), so a failed auto-start is silent. It is also CLI-only, so it never covered the reporter, who was in the Codex app.
  • Nothing revalidates model_catalog_json after injection. The inject-time chooser refuses a missing owned catalog (src/codex/inject/config-toml.ts:597), but a file removed afterwards leaves a pointer that stops Codex loading.
  • The Windows scheduled task has a logon trigger and no boot trigger (src/service/windows-taskxml.ts:225), and applying the integration does not install a service at all, so injection present with nothing listening stays an ordinary post-reboot state.

The account-pool failures that opened the report are a second cause, documented rather than changed: the pool is served by the management API and so needs a live proxy (src/cli/runtime-api.ts:68), the browser flow needs the fixed callback port 1455 which cannot move (src/oauth/callback-server.ts:137), the Windows browser launch swallows its own failure (src/lib/open-url.ts:20), and the dashboard keeps last-good rows after a failed refresh (gui/src/hooks/useCodexAccountPool.ts:325), which is why a new account can be absent while older ones still show.

Verification

  • New tests/codex-integration/codex-signin-lockout.test.ts reconstructs the reported config — Windows catalog path, both root overrides, proxy gone — and runs recovery against it. Nothing in it starts a proxy or binds a port, because recovery has to work without one; a test that needed a live proxy would be exercising the wrong state. It holds that legacy and hinted markers are recognized identically and restore byte-identically, that removal clears the base URL, the realtime override and the catalog pointer together while keeping the user's own keys, that re-injection refreshes the marker in place without breaking idempotency, that a user-owned root override is still untouched, and that the advice appears only for routing we own.
  • The command named in the marker is derived from it and checked against findCommand in the CLI registry, so renaming the command in one place fails the test instead of shipping a config file that points at nothing.
  • Registered the new test file in both scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json.
  • File-size ratchet checked against tests/fixtures/file-size-baseline.json: no tracked file is over its cap, and none of the 20 files this PR touches is ratcheted.
  • Checked every marker consumer for equality comparisons before widening the written line. All twelve match with .includes(OCX_SECTION_MARKER), which is what makes older configs keep working.
  • Exact-head CI on the first push failed three cases in tests/codex-integration/codex-inject.test.ts that asserted an injection over routing we already own returns the file byte for byte apart from the URL. Refreshing our own ownership marker breaks that literal expectation while preserving the contract behind it, so those cases now expect the marker to refresh and assert everything else unchanged, including a malformed tail that must come back verbatim.
  • Swept every marker occurrence under tests/and classified each as routing output, prompt-layer output, or an input fixture, to close that class rather than its three instances. Routing-output assertions now derive from OCX_ROUTING_MARKER_LINE, and two that checked a substring now assert the whole line, since a substring check passes even when the wrong ownership line is written. The four prompt-layer files that kept a private literal copy now derive it from OCX_SECTION_MARKER. Input fixtures stay literal on purpose: a config from an older build is what those tests exist to exercise.
  • No local suite, typecheck, build, install, service action or ocx invocation was used to establish any claim here. This incident is a configuration change that locked a user out, so verification was static source review plus exact-head hosted CI on this branch.
  • No GUI change.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Security review

This touches the Codex auth/routing surface, so stating it explicitly: no credential, token or account identifier is read, written, logged or serialized by any line in this PR. The only values added to output are two fixed English sentences and one fixed TOML comment, none of which interpolate user data. No default changes: injection still writes the same base URL to the same key for the same users, and the added marker text is a TOML comment with no semantic effect. Recovery is not loosened — ocx restore behaviour is untouched, and marker ownership still requires our exact marker substring directly above the key, so a user-owned override remains unclaimable. The widened marker cannot cause a config to be misclassified as ours, since it is strictly longer than and contains the string every predicate already matched.

Summary by CodeRabbit

  • New Features

    • ocx status now provides recovery guidance when Codex routing points to a stopped local proxy.
    • Configuration markers identify ocx restore as the undo command.
    • Added troubleshooting guidance for Codex sign-in failures, proxy recovery, diagnostics, and account login alternatives.
  • Documentation

    • Updated Codex integration instructions with recovery hints across supported languages.
    • Added a dedicated “Codex Cannot Sign In or Load” troubleshooting page.
  • Bug Fixes

    • Improved recovery of injected Codex routing settings, including configurations created by earlier versions.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 20, 2026 05:34
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-20T05:39:18.441533Z ab48579 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5bb98889-55d1-4392-92db-5e3414f07506

📥 Commits

Reviewing files that changed from the base of the PR and between 702295a and e3f490a.

📒 Files selected for processing (8)
  • tests/codex-integration/codex-inject-integration.test.ts
  • tests/codex-integration/codex-inject.test.ts
  • tests/codex-integration/codex-prompt-adopt.test.ts
  • tests/codex-integration/codex-prompt-layers-read.test.ts
  • tests/codex-integration/codex-prompt-layers-write.test.ts
  • tests/codex-integration/codex-prompt-layers.test.ts
  • tests/codex-integration/codex-prompt-route.test.ts
  • tests/service/shutdown-launcher.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The change makes stale Codex routing identifiable and reversible. It adds an undo-aware routing marker, dead-proxy guidance in ocx status, troubleshooting documentation, localized documentation updates, and regression tests for offline recovery.

Changes

Codex routing recovery

Layer / File(s) Summary
Routing markers and offline recovery
src/codex/injected-marker.ts, src/codex/inject/config-toml.ts, tests/codex-integration/*, tests/service/shutdown-launcher.test.ts
Routing markers now include ocx restore. Existing markers remain recognized. Injection refreshes marker-owned entries and preserves user-owned overrides.
Dead-proxy status guidance
src/cli/status.ts, src/cli/index.ts, tests/codex-integration/codex-signin-lockout.test.ts
When opencodex-local routing points to a stopped proxy, ocx status reports sign-in and model request failures and recommends ocx restore.
Troubleshooting documentation and validation
docs-site/src/content/docs/troubleshooting/*, docs-site/src/content/docs/*/guides/codex-integration.md, docs-site/astro.config.mjs, scripts/test-layout/*, tests/codex-integration/*
The troubleshooting page documents recovery paths, manual cleanup, catalog-pointer handling, and account-pool limitations. Localized examples include the undo command. Tests use shared marker constants and cover legacy-marker migration and dead-proxy recovery.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant Codex
  participant ocx status
  participant RoutingAdvice
  participant Operator
  Codex->>ocx status: report startup routing and proxy state
  ocx status->>RoutingAdvice: evaluate proxyUp=false and routingKind=opencodex-local
  RoutingAdvice-->>ocx status: return sign-in failure and ocx restore guidance
  ocx status-->>Operator: print recovery instructions
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 14 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing a stopped opencodex proxy from locking users out of Codex sign-in.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Sep 20, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab485792da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/index.ts
Comment on lines +1591 to +1593
for (const line of deadProxyRoutingAdviceLines({
proxyUp: false,
routingKind: status.json.startup.routingKind,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Show recovery advice when a stale PID file remains

When the proxy crashes or the machine reboots without deleting ocx.pid, collectStatus() preserves that stale PID while health.ok and proxy.running are false. The surrounding if (!(status.json.proxy.pid || status.json.proxy.health.ok)) therefore skips this newly added advice entirely, even though this is a primary lockout scenario. Gate the not-running block on verified liveness such as proxy.running rather than PID-file presence, and cover the actual status output rather than only testing the helper directly.

Useful? React with 👍 / 👎.

Comment on lines +66 to +69
You can undo the routing by hand. Open `$CODEX_HOME/config.toml` and delete
each `# Auto-injected by opencodex` comment together with the single line
directly below it, plus any `model_catalog_json` line ending in
`opencodex-catalog.json`. Leave the rest of the file alone.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Handle provider-table routing in manual recovery

For a non-loopback installation, this marker is directly above [model_providers.opencodex]; following these instructions deletes only the marker and table header, leaving the root model_provider = "opencodex" without a provider definition and leaving the table fields misplaced, so Codex can remain unable to load. The same broad marker text can also match prompt-layer ownership comments. Limit the simple pair deletion to the two root routing keys and separately explain removal of the entire provider-table form and its root selector.

AGENTS.md reference: docs-site/AGENTS.md:L7-L10

Useful? React with 👍 / 👎.

*
* Scope is routing only. Prompt layers keep the bare marker: `ocx restore` is not their undo.
*/
export const OCX_ROUTING_MARKER_LINE = `${OCX_SECTION_MARKER} (undo: ocx restore)`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the owned structure documents

This changes persisted Codex routing configuration and CLI status behavior, but the commit updates no files under structure/. The source-area map assigns src/codex/ and src/cli/ to multiple architecture documents, and the scoped repository rule requires those documents to be updated in the same change; synchronize the applicable routing/configuration and runtime descriptions with the new marker and status behavior.

AGENTS.md reference: src/AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 61 / 80

이 PR은 #5261에서 나온 “프록시가 죽었는데 Codex 로그인까지 막힌” 상태를, 잠금 자체를 없애기보다 빠져나가는 길을 보이게 만드는 레인 H다. 베이스는 dev, 팁은 702295a8ac. 기본 loopback 통합은 Codex에 새 provider를 주지 않고, 내장 openai의 루트 키 openai_base_url(그리고 realtime 쪽 experimental_realtime_ws_base_url)을 127.0.0.1:10100으로 바꾼다. 그 줄은 디스크에 남아 재부팅 후에도 살아 있으니, 프록시 프로세스가 없으면 Codex는 한 주소만 보고 아무 응답도 못 받고, 화면에는 opencodex 이야기가 없다. 복구 명령 ocx restore는 원래부터 프록시·관리 API·네트워크 없이 동작하는데, 설정 파일·ocx status·문서 어디에도 그 이름이 안 보여서 사용자가 라우팅 줄과 카탈로그 파일을 손으로 지웠고, model_catalog_json만 남은 채 파일이 없으면 Codex가 설정을 아예 못 읽는 더 나쁜 상태가 됐다.

이번 변경은 세 갈래다. (1) 라우팅 소유 마커를 # Auto-injected by opencodex (undo: ocx restore)로 쓰고, 소유 판정은 여전히 OCX_SECTION_MARKER 부분문자열이라 옛 빌드 설정도 같은 방식으로 인식·제거·복구한다. 다음 ocx start 주입 때 마커만 in-place로 갱신한다. 프롬프트 레이어는 의도적으로 짧은 마커를 유지한다. (2) 프록시가 내려가 있고 라우팅이 opencodex-local일 때 ocx status가 로그인 실패까지 말하고 ocx restore를 적는다. 우리가 소유하지 않은 로컬 게이트웨이에는 거짓 약속을 안 한다. (3) 문제 해결 페이지를 추가하고, 수동 삭제는 키 이름 기준 세 줄(openai_base_url, realtime, catalog)로 좁혔으며 카탈로그만 지우지 말라고 경고한다. 계정 풀 실패는 같은 페이지에 다른 원인으로 분리해 적었다. #5261은 의도적으로 안 닫는다(shim 침묵, catalog 재검증, Windows 부팅 트리거 등). 새 잠금 회귀 테스트는 포트를 안 열고, 마커→CLI 레지스트리 명령 이름까지 묶는다. tip 커밋은 마커 갱신으로 깨진 기존 inject 기대·문서의 “마커마다 지우기” 안내·테스트의 과도한 migration 주장도 고쳤다.

라인 - src/cli/index.ts (프록시 not-running 블록, proxy.pid || health.ok 게이트): 새 deadProxyRoutingAdviceLines가 이 블록 안에만 들어 있다. collectStatus는 live가 없으면 PID 파일 숫자를 그대로 proxy.pid에 남긴다(resolveStatusPid). 재부팅·크래시 뒤 흔한 “죽은 PID 파일 + health 실패”에서는 pid가 truthy라 not-running 블록 전체가 건너뛰고, 복구 문장·staleProcessState 안내까지 같이 안 나온다. #5261이 재부팅 잠금인데, status 쪽 새 안내가 그 장면에서 가장 안 보일 수 있다. Codex 리뷰 P1과 같은 구멍이다. 헬퍼 단위 테스트만 있고, status 출력 게이트는 안 잡는다.

라인 - docs-site/.../troubleshooting/codex-cannot-sign-in.md 수동 복구: tip에서 “마커마다 지우기”는 키 기준으로 고쳤다. 다만 안내는 Design B 루트 키 세 개만 다룬다. non-loopback의 [model_providers.opencodex] + 루트 model_provider = "opencodex" 형태는 그대로 두면 Codex가 깨진 provider를 남을 수 있다. CLI 없이 손대는 사람용 문서 구멍이다.

라인 - tip 702295a8ac 호스티드 CI: changes/label/docker smoke 등은 통과했지만 test·gates·keyring·npm-global·docs site 등 핵심 잡은 리뷰 시점 기준 아직 pending이다. 본문대로 로컬 스위트는 안 돌렸으니 머지 판단은 exact-head CI에 달려 있다.

메인테이너의 판단이 필요한 지점

status 게이트를 proxy.running(또는 live/health) 기준으로 고치는 걸 이 PR에 넣을지, 후속으로 뺄지. 수동 문서에 provider-table 형태를 이 레인에서 이어서 쓸지. #5261을 잠금 “막다른 골목”만 해소했다고 두고 연 채로 둘지(본문 의도), 아니면 이 레인 merge 후 이슈 본문에 “남은 세 구멍”만 남기고 라벨을 정리할지.

너의 추천

방향은 맞고 범위도 잠금 발견 가능성에 잘 맞춰져 있다. 머지 전 status 게이트만 tip에 짧게 고치는 쪽을 권한다 — #5261 재부팅 장면과 정확히 겹치고, staleProcessState 문구가 이미 같은 블록에 있는데 그 블록에 못 들어가는 상태라 모순이다. 고친 뒤 헬퍼만이 아니라 “pid 파일만 남은 상태면 advice가 출력된다”는 한 케이스를 붙이면 된다. provider-table 수동 안내는 문서 한 절이면 충분하니 가능하면 같이, 아니면 follow-up 이슈로 명시. CI가 tip에서 초록이면 머지 후보. preview deploy 이야기는 하지 않았다. #5261은 본문대로 OPEN 유지가 맞다.

이 댓글은 grok-bot이 작성했습니다

A Windows user whose proxy had stopped was locked out of Codex sign-in
(#5261). The root openai_base_url opencodex writes keeps pointing Codex's
built-in openai provider at 127.0.0.1:10100 after the proxy is gone, and
the injection survives reboot, so the lockout persists.

The only surface such a user can still read is config.toml, and it named
no way out: the marker said "Auto-injected by opencodex" and nothing
else. The recovery they found was to hand-delete the routing lines and
the catalog file, which is worse than "ocx restore" -- a model_catalog_json
target that no longer exists makes Codex fail on a missing file.

Routing markers now read "# Auto-injected by opencodex (undo: ocx
restore)". Every ownership predicate matches OCX_SECTION_MARKER as a
substring rather than by equality, so both the new line and markers
written by earlier builds are still recognized, stripped and restored.
An in-place rewrite refreshes the marker, so an existing install gains
the hint on its next start instead of keeping a bare marker.

Scope is routing only. Prompt layers keep the bare marker, because
"ocx restore" is not what undoes them.
When the proxy is down, "ocx status" says Codex requests will fail and
then offers only ways to bring the proxy back: restart it, install the
service, repair the service. For the user in #5261 that was the wrong
half of the choice. Their injected routing points Codex's own built-in
openai provider at a dead loopback port, so they were stopped at Codex
sign-in, and every suggestion on screen asked them to fix opencodex
first.

Add the other half. When the proxy is down and the routing is one
opencodex owns, the report now says that sign-in fails too, and names
"ocx restore", which needs no proxy, no management API and no network.

The sentences live in a pure function beside unusedProxyWarningLines so
they are testable without spawning the CLI. Routing opencodex does not
own is excluded: "ocx restore" would not remove somebody else's local
gateway, so advertising it there would be a false promise.
Covers the state #5261 was actually reported in: routing on disk, proxy
gone, nothing listening on the loopback port Codex is pointed at. The
tests never start a proxy or bind a port, because recovery has to work
without one, and a test that needed a live proxy would be exercising the
wrong state.

What it holds:

- Routing written before the recovery hint existed is still recognized,
  and recovery from the old and new marker forms is byte-identical, so
  an install that upgrades mid-incident restores the same way.
- Removal clears the dead base URL, the realtime sideband override and
  the catalog pointer together, while leaving the user's own keys. The
  catalog pointer matters as much as the routing: left behind, it names
  a file only opencodex maintains and Codex fails on a missing target.
- An install that predates the hint gains it in place on the next
  injection, without adding an ownership line or breaking idempotency.
- A user-owned root override is still untouched and gains no hint.
- The dead-proxy advice appears only for routing opencodex owns.
- Both recovery surfaces name a command the CLI registry actually has.
  That one is derived from the marker rather than restated, so renaming
  the command in one place fails here instead of shipping a config file
  that points at nothing.
… proxy

There was no page for the state in #5261, and it is the one a user in it
can actually reach: Codex is unusable, so the docs site and the config
file are what is left.

The page names the mechanism, both ways out, and the manual edit for
someone without the CLI. It warns specifically against deleting the
catalog pointer on its own, which is the repair people reach for and
which produces the same symptom from a second cause.

Account-pool failures are covered separately on the same page rather
than folded into the lockout. They happened in the same session in the
report, but the pool needs a live management API and a fixed loopback
callback port, so they are a different problem with a different fix.
Names the mechanism, the four independent source reads that agreed on
it, and the three gaps this lane deliberately leaves open. Also records
that the account-pool failures which opened the report are a second
cause with a different fix, so a later reader does not merge them.
… steps

Three existing cases asserted that injecting over routing we already own
returns the file byte for byte apart from the URL. Refreshing the
ownership marker breaks that literal expectation, and hosted CI failed on
exactly those three. The contract they protect still holds -- injection
is idempotent and no unrelated value moves -- so they now expect our own
marker to refresh and assert everything else unchanged, including the
malformed tail that must be returned verbatim.

The troubleshooting page told a stuck user to delete every
"# Auto-injected by opencodex" comment and the line below it. That same
comment sits above other managed keys, such as an injected
developer_instructions, so following it would have cost configuration
that has nothing to do with sign-in. It now names the three keys to
remove and says to go by the key rather than the comment.

The lockout test claimed more migration than it exercised: the fixture
carries two markers and only the routing writer had run. It now asserts
the exact marker list at each step, which pins the real behaviour --
each writer refreshes only the marker it owns -- and covers the realtime
override as well. Dropped one assertion that restated how the constant
is defined rather than testing behaviour.
Swept every marker occurrence under tests/ and classified each one as
routing output, prompt-layer output, or an input fixture. The three
cases hosted CI failed on are already fixed; this closes the class that
produced them rather than the three instances.

Assertions on what the injector WRITES above a routing key now come from
OCX_ROUTING_MARKER_LINE, and the two that checked a substring now assert
the whole line. A substring check passes even when the wrong ownership
line is written above a routing key, which is exactly the defect that
would have to be caught here.

The four prompt-layer files kept a private literal copy of the bare
marker. They now derive it from OCX_SECTION_MARKER and say why: prompt
layers keep the short marker because "ocx restore" is not their undo, so
the two scopes cannot drift apart silently.

Input fixtures are deliberately left as literals. A hand-written config
or one from an older build is what those tests exist to exercise, and
rewriting them to the current constant would delete the backward
compatibility coverage instead of strengthening it.
@lidge-jun
lidge-jun force-pushed the codex/260920-lane-h-codex-signin-lockout branch from 702295a to e3f490a Compare September 20, 2026 06:02
@lidge-jun

Copy link
Copy Markdown
Owner Author

추가 리뷰 · 우선순위 56 / 80

이전 리뷰(head 702295a8ac) 이후 tip이 e3f490a04b6d로 바뀌었다. 이번에 새로 올라온 핵심은 test(codex): derive marker assertions from the constants they describe다. 호스티드 CI가 깨졌던 inject 기대 세 건은 이미 앞 커밋에서 고쳤고, tip은 그 “클래스”를 닫는다. 라우팅 출력 기대는 OCX_ROUTING_MARKER_LINE에서 가져오고, 부분문자열 검사는 통째 줄 비교로 바꿨다. 프롬프트 레이어 네 파일은 OCX_SECTION_MARKER에서 짧은 마커를 파생해 “restore가 undo가 아닌 범위”가 상수와 같이 움직이게 했다. 옛 빌드 입력 fixture는 일부러 리터럴로 남겨 하위 호환을 지킨다. 그 앞의 tip 수정(마커 갱신 기대·수동 삭제 키 기준·lockout 테스트의 마커 목록 핀)은 이전 리뷰에서 이미 본 내용이고 tip에 그대로 남아 있다. 베이스는 dev. 리눅스 test 1–4·gates·docs site·docker smoke는 tip에서 통과했고, macos shard·keyring·npm-global 일부는 리뷰 시점 기준 아직 pending이다. 실패는 없다.

라인 - src/cli/index.ts (proxy.pid || health.ok 게이트, not-running 블록): 이전 리뷰 P1이 그대로다. tip은 status 생산 코드를 안 고쳤다. resolveStatusPid는 live가 없으면 PID 파일 숫자를 남기고, proxy.running은 Boolean(live) || Boolean(pid && health.ok)라서 죽은 PID만 있으면 running === false인데, 사람 출력 게이트는 여전히 pid || health.ok라 not-running 블록(그리고 그 안의 deadProxyRoutingAdviceLines·staleProcessState 안내)을 건너뛴다. #5261 재부팅 장면에서 새 안내가 안 보이는 구멍이다. Codex 리뷰 P1과 같다.

라인 - docs-site/.../troubleshooting/codex-cannot-sign-in.md 수동 복구: tip에서 “마커마다 지우기”→키 기준 세 줄은 유지·개선됐다. 다만 Design B 루트 키만 다룬다. non-loopback의 [model_providers.opencodex] + 루트 model_provider = "opencodex" 형태는 여전히 비어 있다.

라인 - structure/: tip이 src/codex/injected-marker.ts·status 동작을 바꿨는데 structure 문서는 이 PR에 없다. Codex 리뷰 P1이 지적한 범위다. 레인 H가 “잠금 탈출 발견성”에 맞춰져 있어 의도적 생략일 수 있지만, 머지 전에 한 줄이라도 갱신할지 결정은 남는다.

라인 - status 출력 계약 테스트: tip의 lockout 테스트는 헬퍼·restore·마커 갱신을 잘 핀하지만, “PID 파일만 남은 collectStatus → 사람 출력에 advice가 나온다”는 경로는 여전히 없다. 게이트를 고치면 그 한 케이스가 회귀를 막는다.

메인테이너의 판단이 필요한 지점

status 게이트를 !proxy.running(또는 live/health)으로 고치는 걸 이 PR tip에 넣을지, 후속으로 뺄지. 수동 문서에 provider-table 절을 이 레인에서 이을지. structure 갱신을 블로커로 볼지. #5261은 본문대로 OPEN 유지가 맞는지(남은 세 구멍·계정 풀은 별 원인).

너의 추천

테스트 상수화는 방향이 맞고, 앞선 CI 실패 클래스를 잘 닫았다. 머지 전에는 status 게이트만 tip에 짧게 고치는 쪽을 다시 권한다 — 이전 추천과 같고, tip이 그 구멍을 안 건드렸기 때문이다. 고친 뒤 “pid 파일만 남은 상태면 advice가 출력된다” 한 케이스를 붙이면 된다. provider-table 수동 안내·structure 한 절은 가능하면 같이, 아니면 follow-up 이슈로 명시. 리눅스 CI가 이미 초록이니 macos pending만 기다리면 머지 후보다다. #5261은 OPEN 유지.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun
lidge-jun merged commit 9880c3c into dev Sep 20, 2026
38 of 43 checks passed
@lidge-jun
lidge-jun deleted the codex/260920-lane-h-codex-signin-lockout branch September 20, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant