Skip to content

Add post-sync readiness endpoint and bounded ocx ready wait - #569

Merged
Wibias merged 11 commits into
lidge-jun:devfrom
diegocantarero:agent/macos-post-sync-readiness
Aug 6, 2026
Merged

Add post-sync readiness endpoint and bounded ocx ready wait#569
Wibias merged 11 commits into
lidge-jun:devfrom
diegocantarero:agent/macos-post-sync-readiness

Conversation

@diegocantarero

@diegocantarero diegocantarero commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • preserve GET /healthz as immediate process liveness
  • add exact unauthenticated GET /readyz for post-sync readiness
  • add ocx ready [--json] [--wait [--timeout <seconds>]]
  • document the liveness/readiness contract and embedding invariants

Problem

The listener can bind before startup catalog/config synchronization finishes. A consumer that treats /healthz as readiness can therefore connect to a live proxy before model catalog convergence.

This closes that portable startup race. It was observed while macOS restored a Codex client during login, but the implementation is platform-neutral and does not include macOS process-management policy.

Behavior

  • /healthz is unchanged.
  • /readyz returns 200 only for ready.
  • pending and failed return 503 with Retry-After: 1.
  • POST /readyz and GET /readyz/ return a JSON 404 (the endpoint matches exact pathname + GET only, regardless of whether the packaged dashboard build exists).
  • readiness is owned by a private one-shot gate per server instance
  • startup sync becomes ready only for ok: true with no nonempty warning
  • ocx ready validates service identity and HTTP/status consistency
  • --wait uses one hard deadline across discovery, probes, polling, and sleep
  • older proxies without /readyz fail closed as readiness unavailable
  • downstream startup watchers can use ocx ready --wait instead of guessing from liveness

/readyz unauthenticated response contract

Exactly these six fields, nothing else:

{
  "service": "opencodex",
  "version": "<string>",
  "uptime": "<number>",
  "pid": "<integer>",
  "port": "<integer>",
  "status": "pending | ready | failed"
}

Why this is safe for an unauthenticated caller: every field is already exposed by the existing unauthenticated /healthz (service, version, uptime, pid, port) or is the readiness state itself (status) that the endpoint exists to report. No sync message, warning text, catalog path, provider output, account data, or diagnostic text is included, and the strict /readyz probe treats any foreign or malformed body as unreachable.

Compatibility and privacy

  • existing /healthz clients retain their behavior
  • existing startServer(port) callers remain source-compatible and fail closed as pending unless they own and transition a supplied gate
  • responses expose only fixed readiness state and the existing identity metadata
  • no provider output, account data, paths, sync warnings, or diagnostic text are exposed

Merge-ready work (rebase + review fixes)

  • rebased onto current dev (fa51fce54), keeping both sides of the previously conflicting hunks: startServer(port, { readinessGate }) with scheduleCatalogPrewarm(), the management-auth imports, and deadlineAt discovery budgeting with the source discriminator
  • adopted dev's existing deadlineAt discovery budget instead of the duplicate deadlineMs/probeBudget mechanism
  • re-targeted the ready docs to docs-site/.../reference/cli/lifecycle.md in all locales and documented the 1-300 second --timeout range
  • fixed CodeRabbit findings: deadline test off-by-one (vacuous assertion) and AbortSignal.timeout stub ordering
  • made the exact-method /readyz contract deterministic (JSON 404 for non-GET/trailing-slash paths)

Validation

  • bun run typecheck: pass
  • focused readiness/liveness/CLI suite: 185 pass, 0 fail
  • full local suite: only pre-existing environment-limited failures remain (Windows symlink EPERM tests and a codex-v2-gate assertion that depends on an npm-style node_modules/.bin/codex.cmd shim; both reproduce outside this PR); the maintained GitHub CI matrix is the full-suite acceptance gate
  • bun run privacy:scan: pass
  • docs-site build (bun run build): pass
  • GitHub CI: pending on the rebased head

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • New Features

    • Added the ocx ready command for one-time or polling-based readiness checks.
    • Added JSON output, timeout controls, status reporting, and standardized exit codes.
    • Added the unauthenticated /readyz endpoint with pending, ready, and failed states.
    • Readiness now reflects startup synchronization outcomes, including failures.
    • Older proxies without /readyz fail closed safely.
  • Documentation

    • Documented readiness checks, polling, timeouts, responses, exit codes, and /healthz behavior across supported languages.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1b1f33b4-4aac-4e2d-9eb3-1214b8b0cf4f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds per-server readiness gates, a strict unauthenticated /readyz endpoint, deadline-aware probing, and the ocx ready CLI command. It wires startup synchronization into readiness state, adds tests, and documents the behavior.

Changes

Proxy readiness flow

Layer / File(s) Summary
Startup readiness gate
src/server/readiness.ts, src/server/index.ts, src/codex/desired-state.ts, src/cli/index.ts, tests/server-live.test.ts, tests/proxy-liveness.test.ts
Each server invocation uses an isolated one-shot gate. Startup synchronization marks it ready or failed. /readyz reports the state and bound port.
Readiness endpoint and strict probe
src/server/index.ts, src/server/proxy-liveness.ts, tests/proxy-liveness.test.ts
The server adds exact GET /readyz handling. Discovery and readiness probing enforce identity validation, HTTP/body consistency, probe timeouts, and shared deadlines.
Ready CLI parsing and polling
src/cli/ready.ts, src/cli/index.ts, src/cli/help.ts, tests/cli-ready.test.ts, tests/cli-ready-subprocess.test.ts, tests/cli-restart-health.test.ts
ocx ready validates arguments before preflight, supports single probes and bounded polling, emits human or JSON output, and returns exit codes 0, 1, or 64.
Readiness documentation and compatibility checks
README.md, structure/03_catalog-and-subagents.md, docs-site/src/content/docs/*/reference/cli/lifecycle.md, tests/cli-catalog-prewarm.test.ts, tests/update-notify.test.ts
Documentation defines readiness states, endpoint responses, polling, timeout rules, compatibility behavior, and exit codes. Existing source checks accept the updated startup syntax.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant findLiveProxy
  participant Proxy
  participant ReadinessGate
  participant StartupSync
  CLI->>findLiveProxy: Discover proxy
  findLiveProxy->>Proxy: Check identity
  CLI->>Proxy: GET /readyz
  Proxy->>ReadinessGate: Read status
  ReadinessGate-->>Proxy: pending, ready, or failed
  Proxy-->>CLI: Sanitized readiness response
  StartupSync->>ReadinessGate: Mark ready or failed
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: lidge-jun, ingwannu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. 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 summarizes the main changes: post-sync readiness signaling and the bounded ocx ready wait workflow.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@diegocantarero
diegocantarero marked this pull request as ready for review July 27, 2026 22:17
coderabbitai[bot]

This comment was marked as outdated.

@Wibias
Wibias marked this pull request as draft July 28, 2026 01:50
@Wibias

Wibias commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Please change the PR to ready for review once you are finished @diegocantarero

@lidge-jun

Copy link
Copy Markdown
Owner

NEEDS-SECURITY-REVIEW — the design is sound, the boundary is what needs a reviewer.

The separation is the right one. src/server/readiness.ts:23-93 keeps a one-shot per-server gate, and src/cli/index.ts:208-216 flips it only after syncModelsToCodex returns ok: true with no warning. That means the listener can be up while the gate is still pending, which is exactly the state the old /healthz-only contract could not express. Keeping /healthz as immediate liveness and adding /readyz on top is cleaner than overloading one endpoint.

The tests are unusually strong for a PR this size. tests/server-live.test.ts:823-1040 exercises the real endpoint — exact path and method, unauthenticated behaviour, response sanitization, per-server isolation. tests/cli-ready.test.ts covers the parser, terminal failure, malformed identity, and both sides of the deadline boundary, and tests/cli-ready-subprocess.test.ts:71-181 dispatches a real subprocess rather than mocking it. These bind the public contract instead of searching source.

Why it still needs security review. This deliberately adds a new unauthenticated endpoint. The response is narrowly sanitized to fixed identity and status fields, and 503 with Retry-After: 1 is a reasonable pending signal — but "we added an unauthenticated route and constrained its body carefully" is precisely the change MAINTAINERS.md:33-34 wants a second pair of eyes on. A reviewer should confirm the identity fields cannot become a fingerprinting surface and that the gate cannot be observed to leak startup timing about a private deployment.

The three conflicts all want both sides kept, not a choice:

  • src/cli/index.tsstartServer(port, { readinessGate }) versus current startServer(port) plus scheduleCatalogPrewarm(). Keep the gate and the prewarm.
  • src/server/index.ts — the import hunk, where dev adds management-auth session initialization. Both are needed.
  • src/server/proxy-liveness.ts — your deadline budgeting versus current dev's source: "config" discriminator on the configured-port fallback. Both.

What happens next: rebase keeping both sides of those three, mark it ready when you are satisfied, run fresh CI, then request security review. dev CI is fully green now, so checks will reflect this branch. I found no functional blocker in the readiness design.

@lidge-jun

Copy link
Copy Markdown
Owner

Thanks for putting this together. The separation between process liveness and post-sync readiness is the right design, and it addresses a real startup race.

Before maintainer review, please:

  1. Rebase this branch onto the current dev; the branch has drifted since the last CI run.
  2. Mark the PR ready for review so the full CI matrix and CodeRabbit run against the rebased head.
  3. Arrange an independent security review for the unauthenticated /readyz endpoint. Please document in the PR body exactly every field and state the endpoint exposes, and explain why none of that information is sensitive to an unauthenticated caller. If that cannot be established clearly, gate the endpoint instead.

The design direction is right and the startup race is real — we want this.

@Wibias
Wibias force-pushed the agent/macos-post-sync-readiness branch from 0a1b94f to 55f4937 Compare August 3, 2026 04:49
@Wibias
Wibias marked this pull request as ready for review August 3, 2026 04:49

@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: 55f493777a

ℹ️ 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/ready.ts
@Wibias

Wibias commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

[shipping-github] Addressed feedback

feedback: issue_comment:5154177408
commit: d54ceec

@Wibias

Wibias commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

[shipping-github] Security review requested

@lidge-jun — requesting the deliberate security review you asked for on the unauthenticated GET /readyz endpoint before merge.

Head: d54ceec8b (rebased on dev, required CI green, ready for review). The exact response contract — exactly {service, version, uptime, pid, port, status}, no diagnostics — and the sensitivity rationale are documented in the PR description. The endpoint is stricter than /healthz: non-GET and trailing-slash requests return JSON 404 regardless of gui/dist, and ocx ready probes fail closed as unreachable on foreign or malformed bodies.

This is the last open gate before merge; please review the boundary.

@Wibias

Wibias commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Please resolve conflicts.

@Wibias
Wibias marked this pull request as draft August 4, 2026 07:31
@diegocantarero
diegocantarero force-pushed the agent/macos-post-sync-readiness branch from d54ceec to 15613e6 Compare August 5, 2026 09:03
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@Wibias
Wibias force-pushed the agent/macos-post-sync-readiness branch 2 times, most recently from 4a4b5a3 to a3205ab Compare August 6, 2026 03:48
@Wibias
Wibias marked this pull request as ready for review August 6, 2026 03:50
@github-actions
github-actions Bot marked this pull request as draft August 6, 2026 03:50
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@github-actions
github-actions Bot marked this pull request as ready for review August 6, 2026 03:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/cli/lifecycle.md`:
- Line 151: Update the lifecycle documentation sentence around the `--wait`
behavior to replace “terminal `failed`” with “the terminal `failed` state,”
preserving the rest of the polling and timeout wording.

In `@src/server/index.ts`:
- Around line 591-620: Update the /readyz handling around
readinessGate.getStatus() to check isDraining() first and report a non-ready
status while the listener drains, without mutating readinessGate. Use "pending"
for draining so polling supervisors can continue, then preserve the existing 503
response and Retry-After behavior for non-ready statuses and the 200 response
for ready status.

In `@src/server/proxy-liveness.ts`:
- Around line 145-147: Remove the legacy deadlineMs fallback and type cast from
findLiveProxy. Use io.deadlineAt directly and pass the original io as probeIo,
preserving the existing LivenessIo contract without accepting an undocumented
alias.

In `@tests/cli-ready-subprocess.test.ts`:
- Around line 112-121: Adjust the subprocess timing test around runCli and its
elapsedMs assertion: increase the process kill budget and raise the elapsed-time
ceiling beyond 2,000 ms so CLI startup is not mistaken for readiness timeout
behavior. Keep the existing readiness-hit, timedOut, and exitCode assertions
unchanged.

In `@tests/cli-ready.test.ts`:
- Line 777: Update the assertion in the relevant describe block around
readySource to use a whitespace-tolerant regular expression for the remainingMs
=== undefined ternary and its verifyPidFn fallback, rather than matching a
newline and literal indentation. Preserve the existing non-wait contract while
allowing the source formatting to change.
- Around line 207-263: Correct the timing comments in the three tests around
runReady to reflect that each now stub increments before returning: the
effective deadlines are 5100ms, 1500ms, and 4000ms respectively. Keep the test
logic and assertions unchanged unless you instead offset each initial t value
consistently, as done in the existing deadline test.

In `@tests/proxy-liveness.test.ts`:
- Around line 449-459: Replace the vacuous JSON.stringify checks in the test
“the gate exposes only the fixed status enum (no reason/changedAt payload)” with
assertions that directly verify the gate object exposes only getStatus,
markReady, and markFailed. Preserve the existing failed-status assertion and
assert the actual public key set rather than closure state or serialized
function properties.

In `@tests/update-notify.test.ts`:
- Line 127: Add an explicit assertion immediately after computing serverIndex
from cli.search, requiring the result to be nonnegative before using it in the
startup ordering comparison. Keep the existing ordering assertion unchanged so a
missing startServer(port) match fails loudly instead of passing with -1.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 32cfee2b-72d9-4165-b80e-546078114862

📥 Commits

Reviewing files that changed from the base of the PR and between 791e0fb and a3205ab.

📒 Files selected for processing (21)
  • README.md
  • docs-site/src/content/docs/ja/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ko/reference/cli/lifecycle.md
  • docs-site/src/content/docs/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ru/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md
  • src/cli/help.ts
  • src/cli/index.ts
  • src/cli/ready.ts
  • src/codex/desired-state.ts
  • src/server/index.ts
  • src/server/proxy-liveness.ts
  • src/server/readiness.ts
  • structure/03_catalog-and-subagents.md
  • tests/cli-catalog-prewarm.test.ts
  • tests/cli-ready-subprocess.test.ts
  • tests/cli-ready.test.ts
  • tests/cli-restart-health.test.ts
  • tests/proxy-liveness.test.ts
  • tests/server-live.test.ts
  • tests/update-notify.test.ts

Comment thread docs-site/src/content/docs/reference/cli/lifecycle.md Outdated
Comment thread src/server/index.ts
Comment thread src/server/proxy-liveness.ts Outdated
Comment thread tests/cli-ready-subprocess.test.ts Outdated
Comment thread tests/cli-ready.test.ts
Comment thread tests/cli-ready.test.ts Outdated
Comment thread tests/proxy-liveness.test.ts
Comment thread tests/update-notify.test.ts
@github-actions
github-actions Bot marked this pull request as draft August 6, 2026 04:07
Wibias added 6 commits August 6, 2026 06:52
Extract the 750ms per-probe ceiling as DEFAULT_PROBE_TIMEOUT_MS in
proxy-liveness and import it from the ready CLI instead of redeclaring
IO_TIMEOUT_CAP_MS, so liveness and readiness defaults cannot diverge.
…tion

verifyPidIdentity spawns WMIC/PowerShell (up to seconds on Windows) and is
only needed for kill targets. runReady's production discovery now passes
verifyPidFn: () => null so no OS command-line check runs outside the wait
deadline; the /healthz identity marker and strict /readyz contract
validation are unchanged.
Rebase the readiness PR onto current dev and resolve the two conflict
surfaces against dev's modern startup path:

- src/cli/index.ts: keep syncCodexOnStartIfEnabled (Codex toggle + lidge-jun#1046
  stale app-server warning) and thread the readiness gate into it as the
  fourth argument, so /readyz reflects the real sync outcome without
  bypassing the toggle or the write-tracking contract.
- src/codex/desired-state.ts: accept an optional readiness gate; mark
  ready immediately when the Codex integration is explicitly OFF (nothing
  to sync), otherwise drive the gate via runStartupReadinessSync from the
  raw sync outcome (ready only on ok=true with no nonempty warning).
- src/server/readiness.ts: runStartupReadinessSync returns the raw sync
  outcome so callers keep the lidge-jun#1046 write flags without a second call.
- structure/03_catalog-and-subagents.md: un-indent the pre-existing cache
  paragraph and fix the Startup readiness heading to top-level markdown.
- tests/cli-ready.test.ts: update the source-level wiring guard to assert
  the new syncCodexOnStartIfEnabled(port, config, undefined, readinessGate)
  contract instead of the pre-rebase inline wiring.
- src/server/index.ts: /readyz reports pending (503) while the listener is
  draining instead of advertising ready; the one-shot readiness gate is not
  mutated on shutdown (startup-sync ownership preserved).
- src/server/proxy-liveness.ts: drop the untyped deadlineMs alias in
  findLiveProxy; no caller supplies it and LivenessIo only declares
  deadlineAt.
- tests/server-live.test.ts: add a draining /readyz regression test.
- tests/proxy-liveness.test.ts: replace the vacuous JSON.stringify privacy
  assertion with a direct own-property surface check.
- tests/cli-ready-subprocess.test.ts: raise the subprocess timing ceiling so
  cold Bun startup on CI is not mistaken for readiness timeout behavior.
- tests/cli-ready.test.ts: correct off-by-one-tick deadline comments and make
  the non-wait wiring assertion whitespace-tolerant.
- tests/update-notify.test.ts: fail loudly when startServer(port) is not
  found instead of silently passing via -1.
- docs-site/.../lifecycle.md: clarify the terminal failed wording.
… branch

The generic OPTIONS handler ran before the /readyz exact-GET route, so
OPTIONS /readyz (and /readyz/) answered 204 instead of the deterministic
JSON 404 the exact-method contract promises. Reject both paths in the
OPTIONS branch and add regression coverage.
…ontract

Compare the DECODED pathname for /readyz routing so an encoded variant
like /readyz%2F (which decodes to /readyz/) cannot bypass the exact-path
rejection and reach the GUI fallback (serveGuiFile decodes the pathname
and would serve index.html with 200). GET, POST, and OPTIONS on encoded
variants all answer the deterministic JSON 404.

Strengthen the OPTIONS regression test to assert the JSON 404 body
(content-type, error.type, and the path-specific error.message) and add
encoded-path coverage for GET, POST, and OPTIONS.
@Wibias
Wibias force-pushed the agent/macos-post-sync-readiness branch from 6d2a8ce to bb1aa2e Compare August 6, 2026 04:56
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request is already Ready for Review.
CodeRabbit/Codex review was requested via the review-ready label. If no review appears, comment @coderabbitai review to request one.
Maintainers: @lidge-jun @Ingwannu @Wibias

@Wibias
Wibias marked this pull request as ready for review August 6, 2026 04:56
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] Acknowledged. The PR readiness gate is complete, and the pull request is ready for review. I will review the current head.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness checklist is complete. I will review the current PR head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness checklist is complete. I will review the current pull request head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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: bb1aa2e358

ℹ️ 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/ready.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/cli/lifecycle.md`:
- Line 152: Update every readiness reference to document the complete --timeout
contract: in docs-site/src/content/docs/reference/cli/lifecycle.md lines
152-152, state that values are positive integers from 1 through 300; in
README.md lines 165-165, add the positive-integer constraint; in
docs-site/src/content/docs/ja/reference/cli/lifecycle.md lines 125-126,
docs-site/src/content/docs/ko/reference/cli/lifecycle.md lines 153-153,
docs-site/src/content/docs/ru/reference/cli/lifecycle.md lines 164-164, and
docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md lines 124-124, add
equivalent localized wording; and in structure/03_catalog-and-subagents.md lines
47-50, document that --timeout requires --wait and accepts positive integers
from 1 through 300.

In `@src/server/proxy-liveness.ts`:
- Around line 246-253: Update the ReadinessProbeResult interface to make status
non-nullable and require pid and port as valid numbers, matching the non-null
values emitted by validateReadyzBody. Keep null handling at the probe result
level for callers such as src/cli/ready.ts, including its optional chaining and
fallback behavior.

In `@tests/cli-ready-subprocess.test.ts`:
- Around line 164-171: Update the runCli invocation in this subprocess test to
pass the same 10,000 ms killAfterMs budget used by the sibling test, while
preserving the existing arguments and environment variables.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9f80db9f-877d-480f-9aa2-8f61f676c9d5

📥 Commits

Reviewing files that changed from the base of the PR and between 6865c00 and bb1aa2e.

📒 Files selected for processing (21)
  • README.md
  • docs-site/src/content/docs/ja/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ko/reference/cli/lifecycle.md
  • docs-site/src/content/docs/reference/cli/lifecycle.md
  • docs-site/src/content/docs/ru/reference/cli/lifecycle.md
  • docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md
  • src/cli/help.ts
  • src/cli/index.ts
  • src/cli/ready.ts
  • src/codex/desired-state.ts
  • src/server/index.ts
  • src/server/proxy-liveness.ts
  • src/server/readiness.ts
  • structure/03_catalog-and-subagents.md
  • tests/cli-catalog-prewarm.test.ts
  • tests/cli-ready-subprocess.test.ts
  • tests/cli-ready.test.ts
  • tests/cli-restart-health.test.ts
  • tests/proxy-liveness.test.ts
  • tests/server-live.test.ts
  • tests/update-notify.test.ts

Comment thread docs-site/src/content/docs/reference/cli/lifecycle.md Outdated
Comment thread src/server/proxy-liveness.ts
Comment thread tests/cli-ready-subprocess.test.ts
- src/cli/ready.ts: clear the cached status/pid/port when discovery stops
  finding the proxy, so a proxy that reported pending and then exited is
  reported as unreachable at timeout instead of stale pending (P2).
- src/server/proxy-liveness.ts: narrow ReadinessProbeResult to non-null
  members (a foreign/unreadable body yields a null RESULT, never a null
  member); the producers only ever emit valid values.
- tests/cli-ready.test.ts: regression test for the stale-pending fix.
- tests/cli-ready-subprocess.test.ts: enlarge the second subprocess kill
  budget to 10s (CI cold-start tolerance, matching the sibling test).
- README, lifecycle docs (en + 4 locales), structure doc: document that
  --timeout accepts positive integer seconds from 1-300.
@github-actions
github-actions Bot marked this pull request as draft August 6, 2026 05:15
@github-actions
github-actions Bot marked this pull request as ready for review August 6, 2026 05:16
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review the current PR head.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] Acknowledged. The PR is ready for review. I will review the current head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness checklist is complete. I will review the current pull request head.

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

[GD] Addressed feedback

feedbacks:

  • issue_comment:5131865870
  • issue_comment:5154177408

commit: a93fc4a

@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

[GD] Verdict: approve-comment

TLDR

  • PR: Add post-sync readiness endpoint and bounded ocx ready wait #569 — Add post-sync readiness endpoint and bounded ocx ready wait
  • Head: a93fc4ac8 on dev (mergeStateStatus: CLEAN, mergeable: MERGEABLE)
  • Decision: useful and ready — the readiness/liveness split closes a real startup race and the full CI matrix is green on the rebased head
  • Usefulness: high — /healthz liveness could not express "listener up but catalog not yet converged"; GET /readyz + ocx ready --wait give supervisors a fail-closed post-sync readiness signal
  • Bugs: none blocking — CodeRabbit/Codex findings (draining /readyz, OPTIONS/encoded-path 404 contract, stale unreachable on discovery loss) all fixed and regression-tested
  • Security: none — the unauthenticated /readyz exposes exactly the fields /healthz already exposes plus the fixed status enum; body is sanitized and the probe is fail-closed (see full verdict)
  • Spec / standards: clean — docs (README + all 5 locales), help text, and structure doc match the implemented contract
  • Reviews: humans none open; CodeRabbit + Codex threads all resolved; maintainer overtake completed the rebase and review fixes
  • Base / CI: green on a93fc4ac8 — all 22 required checks pass (4 test shards, macos, npm-global, gates, enforce-target, hygiene, label, CodeRabbit)
  • Gate: none — draft cleared, ready for review
  • Owner actions (foreign PR): none — the maintainer overtake rebased onto current dev, resolved conflicts, fixed all bot findings, and pushed; @diegocantarero only needs to confirm readiness for merge
  • Bottom line: ship — the readiness contract is sound, the endpoint is safely sanitized, CI is green on the current tip, and all review feedback is addressed in the rebased head
Full verdict

Semantic propagation

  • Concepts audited: readiness gate (pending|ready|failed), /readyz HTTP contract, ocx ready CLI contract, startup-sync outcome mapping
  • Authoritative sources: src/server/readiness.ts (gate), src/server/index.ts (/readyz handler), src/server/proxy-liveness.ts (strict probe), src/codex/desired-state.ts + src/codex/sync.ts (startup sync outcome)
  • Producers and consumers checked: handleStartsyncCodexOnStartIfEnabled → gate; startServer listener → /readyz; ocx readyfindLiveProxy/probeReadiness; all import/wiring paths traced
  • Public/derived representations checked: /readyz body ({service, version, uptime, pid, port, status}) matches the documented contract exactly; CLI --json ({ready, status, pid, port}) matches; exit codes 0/1/64 match docs
  • Material variant partitions checked: ready vs pending vs failed vs unreachable; 200 vs 503 (+Retry-After); exact-GET vs POST/OPTIONS/trailing-slash/encoded-slash; draining vs not; per-server gate isolation (two simultaneous servers, bind-failure isolation); Codex integration on vs off
  • Positive and negative assertions checked: positive (200+ready, 503+pending, 503+failed) and negative (503+ready, 200+pending, foreign body, malformed fields, wrong pid/port, encoded /readyz%2F, OPTIONS) all covered by tests
  • Unmapped surfaces: none
  • Unproven equivalence assumptions: none
  • Representation mismatches: none
  • Variant coverage gaps: none
  • Axis verdict: pass
    Linked: none

Usefulness

The PR addresses a genuine startup race: the proxy listener binds before the post-startup Codex catalog sync settles, so a consumer treating /healthz (immediate liveness) as readiness could connect to a live-but-half-synced proxy. The observed trigger (macOS restoring a Codex client during login) is one instance of a general problem. The split — /healthz stays liveness, /readyz becomes post-sync readiness, ocx ready --wait provides a bounded poll — is the standard liveness/readiness separation and is implemented cleanly.

Bugs / correctness

  • Method: bug-review.md — static analysis of the diff plus complementary edge-case review of the wait loop, probe validation, and HTTP contract
  • Findings fixed this session (all from CodeRabbit/Codex review on the rebased head):
    • src/server/index.ts: /readyz now reports pending (503) while the listener is draining instead of advertising ready
    • src/server/index.ts: OPTIONS and encoded (/readyz%2F) variants now answer the deterministic JSON 404 before the preflight/GUI-fallback paths
    • src/cli/ready.ts: a proxy that reported pending and then exited is reported unreachable at timeout (cleared stale status/identity)
    • src/server/proxy-liveness.ts: removed the untyped deadlineMs alias; narrowed ReadinessProbeResult to non-null members
  • No remaining blockers

Security

  • Scope reviewed: new unauthenticated GET /readyz; probe outbound fetch (loopback-bounded); credential transport; secrets/privacy scan
  • Findings: none. The endpoint exposes exactly {service, version, uptime, pid, port, status} — the same identity fields /healthz already exposes plus the fixed status enum. No sync message, warning, catalog path, provider output, or account data. The strict probe rejects any foreign/malformed/self-inconsistent body and fails closed as unreachable. The outbound probes target only the local proxy's own configured/runtime hostname and port.
  • bun run privacy:scan passes; probe coverage verified (credential-transport, secrets-scan).

Spec / standards

  • Spec source: PR body contract (six-field /readyz body, exit codes, --timeout 1–300 positive integer, --wait semantics)
  • Gaps: none — implementation matches the documented contract; README, help text, all 5 locale lifecycle pages, and the structure doc are consistent

Reviews

  • Owners/maintainers: lidge-jun's two review comments (rebase + security review + mark ready) addressed; [GD] Addressed feedback posted with head marker
  • Bots: CodeRabbit (4 rounds) + Codex P2 findings all fixed and resolved on-thread; 0 unresolved threads

Base / CI

  • Behind/conflicts: clean — rebased onto current dev (6865c005d); MERGEABLE, CLEAN
  • Required checks: green on a93fc4ac8 — all 22 checks pass (test 1-4/4, macos, npm-global x3, gates, keyring x3, enforce-target, hygiene, label, changes, ci, react-doctor, linux-systemd, macos-launchd, windows-schtasks, select-windows-runner, CodeRabbit)
  • Local tip compile/tests: bun run typecheck pass; focused readiness suite 265 pass / 0 fail; bun run privacy:scan pass; docs-site build pass
  • Full local suite on Windows: only pre-existing environment-limited failures (Windows effective-account lookup + Bun crash), reproduced identically on clean dev — not PR-caused

Simplification (for the PR owner)

Simplify was explicitly requested. Candidate pass on the rebased head: nothing worth simplifying. The ready.ts wait loop's verbosity is intentional (documents the deadline-wins semantics its 50+ tests pin), and the gate/probe/validation code is already tight. No behavior-preserving simplifications met the confidence bar; none were applied.

Gate

none — draft cleared, marked ready for review, review-ready label applied

Bottom line

Ship. The readiness contract is well-designed and safely sanitized, the maintainer overtake rebased it onto current dev and fixed every bot finding, and the full CI matrix is green on the exact head. @diegocantarero — please confirm the PR is ready and it can be merged.

@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

[GD] Merge ready

PR: #569 — Add post-sync readiness endpoint and bounded ocx ready wait
Head: a93fc4ac8dev (mergeStateStatus: CLEAN)

Reviews

  • Humans (owners first): lidge-jun's two review comments (rebase + security review + mark ready) addressed; [GD] Addressed feedback posted with head marker
  • Bots: 0 unresolved useful threads; CodeRabbit (4 rounds) + Codex P2 findings all fixed on-thread
  • Own bug + security + spec/standards: bug-review + security-review (incl. ai-agent-security surface check) + spec/standards done on tip; blockers fixed: none remaining

Tip freshness

  • Updated from dev: yes (a93fc4ac8, rebased onto 6865c005d)
  • Compiles/tests against tip: bun run typecheck pass; focused readiness suite 265 pass / 0 fail; privacy:scan pass; docs build pass
  • Conflicts: none

Checks

  • Local/CLI: typecheck + 265 focused tests + privacy:scan + docs build green
  • Required CI: green on a93fc4ac8 (all 22 checks pass)
  • Policy: code-owner enforcement advisory; stale approvals n/a; merge-queue n/a

Residual

none

Ready to merge.

@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Thanks @diegocantarero — merging this.

Why it helps: the liveness/readiness split closes a real startup race where a consumer could treat /healthz as readiness and connect to a proxy whose Codex catalog sync had not settled. GET /readyz plus ocx ready --wait give supervisors a fail-closed, bounded post-sync readiness signal with a strictly sanitized body, and the maintainer rebase + review fixes land it cleanly on dev.

Ship it.

@Wibias
Wibias merged commit e496e9b into lidge-jun:dev Aug 6, 2026
29 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants