Conversation
The startup path turned a silent admission refusal into a bare /readyz failed with zero evidence; the refusal message is the operator's only path to the cause (9-day silent catalog-sync stall on this deployment). (cherry picked from commit 4bc1c67)
The bridge was written against the single-file config and provider registry. On dev those modules are split, so the wiring lands per-owner: schema and diagnostics for chatgptBridge, the adapter and provider rows, and the GUI provider-list authority pin. The preset-count guard is what makes the docs half of that change mandatory rather than optional. Drops the three live-probe fixtures from the original branch: they hardcoded a private devspace issuer and a user-temp token path, which privacy:scan rejects.
The recovery guardian only helps if a hand stop is distinguishable from a crash. Intent is now written by every actor that can stop the proxy, before it dispatches: the tray click handler, `ocx stop` (skipped for a guardian recovery child), and the receipt-less management API stop, which fails closed when an enabled marker cannot be persisted. The intent helper ships as an owned tray asset with rollback and uninstall coverage, and the detached recorder is finally started by the server it describes. The npm package does not ship scripts/, so installing the helper is conditional while the tray script keeps its runtime refusal for a marker with no helper beside it.
A guardian-driven recovery child must not be read as an operator's durable manual stop, and a stop that cannot write its intent must refuse loudly instead of leaving the proxy serving while the file claims `stopped`. - recovery-intent: fence `maintenance` with the shared `at < until <= at+180000` contract on every reader and writer (CLI, tray, launcher, action script), restore the durable intent verbatim when a later refusal rolls the stop back, and drop a re-affirmation of an intent that already reads `running`. - guardian: adopt the opening inspection instead of paying for a second ~5 s PowerShell spawn, decay launcher corroboration so a generation cannot freeze a stale pid+start pair in place, and re-inspect after a recover so the recovery path stops double-paying Inspect. - incidents: count only directories this process generated against the retention budget, and never walk a reparse point into `fs.rm(recursive)`. - gateway: hoist the per-request allowed-host set and local port out of the request path. - intent.ps1/launcher: parenthesise the reparse test (Windows PowerShell binds `-or` and `-and` left-to-right at equal precedence, so an unparenthesised guard lets a small symlink fail open) and refuse a malformed marker before dispatching any lifecycle action. Verification: focused Windows files re-run quiet and exclusive (recovery-main 18/0, recovery-intent green on a quiet box, policy, ownership, repair, tray), each new assertion mutation-proven to fail alone. `bun x tsc --noEmit` and `bun run privacy:scan` green.
… context Review fixes on the carried ChatGPT bridge, each with a mutation-proven test. - store: an idempotent replay must survive pruning, so `pruneOperations` now refuses to drop receipts inside the `OPERATION_REPLAY_MS` window it exists to answer (the row cap still binds outside it), and the host-target uniqueness guard moved into a partial unique index because a SELECT-then-INSERT only held within one process. A chat conversation keeps its one binding row for life by schema; the guard mirrors that instead of filtering by lifecycle. - dsh host: an unclaimed delivery no longer holds the TARGET_ACTIVE gate forever. It now releases once the claim is older than the same 120 s stale window the core store uses, while a claimed-but-unfinished turn still refuses. - mcp client: a DevSpace restart retires the minted session id, so a 404 drops it and the next call re-initializes instead of failing for the life of the client; a shared SSE frame is matched by request id, not by which frame arrives first. - contracts/provider: retire the codes and the `replace` action this module no longer emits, add `BINDING_EXISTS`, hoist `MAX_PROMPT_CHARS` into the shared contract, and drop `promptPreview` from the turn context — a serialized slice of the conversation is request content, and any transport that logs the context would then log the body. - tests: pin the chat-side uniqueness guard (it had no discriminating assertion), and make the runTurn-only skip list derived-and-checked instead of a hand-maintained allowlist over seven registry-wide loops. Verification: `chatgpt-bridge-core` 17/0, `chatgpt-bridge-codex-host` and `chatgpt-bridge-dsh-host` green, `adapter-tool-conformance` 9/0 with both mutation directions firing. `bun x tsc --noEmit` green.
…strument `beginRuntimeSyncOperation` was a second entry into the same instrumentation the start scope already owns, and it needed three module globals plus their teardown assignments to reach them. Nothing outside the module called it, and a second live diagnostics instance would have had those globals point at whichever child started last. Verification: `server-runtime-diagnostics` green; `bun x tsc --noEmit` green.
…ly 503 `src/adapters/registry.ts` does not construct the adapter with a browser transport yet, so every turn through a preset-selected chatgpt-web model answers CHATGPT_WEB_TRANSPORT_UNAVAILABLE. A published preset therefore promised a capability the shipped build cannot perform; the registry entry and its note stay, only the preset flag goes off until the transport is attached. Also register `src/chatgpt-bridge/` in the structure source-area map, which the manifest guard requires for a new production directory.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This pull request was already a draft. Its draft status will be preserved after every issue above is resolved. Hygiene
|
Brings the branch onto the current dev head so the Windows recovery chain and the carried ChatGPT bridge can be reviewed against what upstream now does in the same restart/stop area. 23 conflicts; how each was decided: - src/cli/index.ts: upstream routed `handleStop` through an approval gate. Kept the gate and kept the durable-intent fence around it, so an approval refusal rolls the `stopped` intent back through the same path as an ownership refusal instead of through a second copy of it. - src/tray/windows.ts: two independent additions landed at one spot (our `trayHomeRequiresRecoveryIntentHelper`, upstream's `windowsTrayRequiredFilesPresent` which fixes the dotted-icon stale-install bug). Both kept, and the ownership check now composes them: upstream's required-file rule AND the helper only where the home needs it. - src/tray/windows-tray.ps1: kept upstream's Update menu item and our write-intent-first ordering comment. - tests/fixtures/test-layout-expected.json: upstream had already relocated most of our entries; kept only the four chatgpt-bridge keys it lacks, so no duplicate property. - docs-site guides and quickstarts (8 locales) + structure/ops/docs-and-release.md: recount is derived by `docs-provider-preset-counts` — the merged registry is 99 total (81 key-based, 13 OAuth, four local, one default), so the +1 is applied to every locale rather than only to the English page. - structure/providers-and-adapters.md: kept upstream's mimo-free and command-code rows and our `src/chatgpt-bridge/` row. - tests/adapters/adapter-tool-conformance.test.ts: upstream added `claude-cli` to the tool-less set; unioned it. The derived-and-checked skip pin still holds against it. Verification: `bun x tsc --noEmit` clean; `test-layout`, `test-layout-tooling`, the three `docs-provider-*` guards and `adapter-tool-conformance` green together (146 pass / 1 fail, and that one — `move end to end` — passes alone, so it is coexistence noise from running four files in one process, not a merge defect).
|
Post-merge verification on
Why this pull request stays a draft: the review-readiness checklist asks for "local CI green", and I am not going to tick that without having run |
리뷰 · 우선순위 64 / 80이 PR은 초안입니다. 하는 일이 두 갈래입니다. 윈도우에서 사람이 프록시를 끈 것과, 프로그램이 혼자 죽은 것을 구분합니다. ChatGPT 웹 브리지는 대화 연결을 저장합니다. 같은 요청을 나중에 다시 물어봐도 "이미 처리했다"는 기록이 남고, 한 파일에 프로세스가 둘 붙어도 같은 대상을 두 번 연결하지 못하게 잠급니다. 브라우저로 대화를 보내는 기능은 아직 없습니다. 그래서 대시보드 타일은 꺼 두었습니다. 켜 두면 매 턴이 작은 변경도 같이 있습니다. Codex 쓰기가 거부되면 이유를 로그에 남깁니다. 안 쓰이던 베이스는 scripts/ocx-recovery-guardian/repair.cjs:17 - 수리 주소 허용 목록에 scripts/ocx-recovery-guardian/windows-action.ps1:243 - src/server/management-api.ts - 관리 화면의 끄기가 정지 메모를 먼저 씁니다. 이 파일은 인증과 작업 흐름이라 src/lib/recovery-intent.ts - 메인테이너의 판단이 필요한 지점 윈도우 복구와 ChatGPT 브리지를 한 PR로 머지할지도 정해야 합니다. 둘 다 크고, 실패 원인이 섞입니다. 안 쓰는 계측 삭제는 작성자가 이미 분리를 제안했습니다. 관리 API 정지에 너의 추천 이 댓글은 grok-bot이 작성했습니다 |
|
Maintainer triage: Criteria (P3): Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/roadmap, or long-stale branch. |
|
Release train 4 triage (reviewed against dev 24b2f39 at head 651ff2f; T4-P-5782): Hold; split. Windows durable-stop guardian and ChatGPT bridge/replay receipts are independent new subsystems, neither on Update (2026-09-28): a re-review found one narrow, independent bug fix in this PR, commit |
A service-home admission refusal in syncModelsToCodex returned without any log line. Startup then marked /readyz failed with no evidence and `ocx sync` only said the sync did not complete. Log one line naming the authority and pointing to POST /api/sync for the specific reason. The admission message can contain private home and service-definition paths, so it stays out of the log. Reimplements the diagnostic slice of #5782 without the raw message. Co-authored-by: tcflying <77509083+tcflying@users.noreply.github.com>
A service-home admission refusal in syncModelsToCodex returned without any log line. Startup then marked /readyz failed with no evidence and `ocx sync` only said the sync did not complete. Log one line naming the authority and pointing to POST /api/sync for the specific reason. The admission message can contain private home and service-definition paths, so it stays out of the log. Reimplements the diagnostic slice of #5782 without the raw message. Co-authored-by: tcflying <77509083+tcflying@users.noreply.github.com>
A service-home admission refusal in syncModelsToCodex returned without any log line. Startup then marked /readyz failed with no evidence and `ocx sync` only said the sync did not complete. Log one line naming the authority and pointing to POST /api/sync for the specific reason. The admission message can contain private home and service-definition paths, so it stays out of the log. Reimplements the diagnostic slice of #5782 without the raw message. Co-authored-by: tcflying <77509083+tcflying@users.noreply.github.com>
A service-home admission refusal in syncModelsToCodex now leaves one path-free log line pointing to POST /api/sync, instead of silently failing /readyz and ocx sync. Reimplements the diagnostic slice of #5782 without logging private paths. Co-authored-by: tcflying <77509083+tcflying@users.noreply.github.com>
* docs(devlog): plan release train 4 issue triage * docs(devlog): record issue triage roadmap gate * docs(devlog): record issue triage comments * docs(devlog): record large PR release decisions * docs(devlog): refine standalone carry verification * docs(devlog): hand off issue triage lane * docs(devlog): plan issue triage lane resume * docs(devlog): require Windows CI dispatch for carry * docs(devlog): record Sol re-verification, #6093 and #5782 slice * docs(devlog): record issue triage lane outcome
Summary
Read shape, so the diff is not a surprise: this branch carries two feature lines plus their review wave. Roughly 2.3k lines are the
src/chatgpt-bridge/module and its extension, roughly 5.6k are the Windows recovery subsystem (guardian scripts, tray, launcher) that this branch introduces relative to the merge base, and roughly 1.9k are the fixes that round of review produced on top of both. Seven commits, each scoped to one of those three.ocx stop,ocx start,ocx ensure, the visible launcher and the tray now share one durable recovery-intent contract: a manual stop survives a proxy that died before it could be restarted, a guardian-spawned recovery child is never mistaken for an operator stop (OPENCODEX_GUARDIAN_RECOVERY), and a stop whose intent cannot be written refuses loudly instead of leaving the proxy serving while the file claimsstopped.The Windows recovery guardian stops paying for its own work: the opening
Inspectis adopted instead of re-run ~5 s later, launcher corroboration now decays so a healthy generation cannot freeze a stale pid+boot pair, the recovery path no longer double-paysInspect, and incident retention counts only directories the guardian generated, so a stray file can no longer evict a real incident and a reparse point is never walked intofs.rm(recursive).ChatGPT bridge: idempotent replay receipts survive pruning (the row cap now binds only outside the replay window it exists to answer), host-target uniqueness moved into a partial unique index because SELECT-then-INSERT only held inside one process, an unclaimed delivery releases its
TARGET_ACTIVEgate once it is older than the same 120 s stale window, and a retired DevSpace session id is dropped on 404 so the next call re-initializes instead of failing for the life of the client.Privacy and honest-declaration fixes:
promptPreviewis gone from the browser turn context (a serialized slice of the conversation is request content, and a transport that logs the context would then log the body), and thechatgpt-webdashboard preset is off because the shipped build cannot construct a browser transport, so the tile no longer promises a turn that can only answerCHATGPT_WEB_TRANSPORT_UNAVAILABLE.One unrelated deletion is folded in: the unused module-level
beginRuntimeSyncOperationinstrument and the three module globals it needed (41 lines). Say the word and it moves to its own pull request.Verification
Ran, and green:
bun run typecheck(bun x tsc --noEmit) — no output.bun run privacy:scan—Privacy scan passed.tests/windows/windows-recovery-main.test.ts18/0,tests/windows/windows-recovery-policy.test.ts12/0,windows-recovery-ownership,windows-recovery-repair14/0,windows-tray26/1 (the one red reproduces onorigin/devtoo,EADDRINUSE),tests/chatgpt-bridge/chatgpt-bridge-core.test.ts17/0,chatgpt-bridge-codex-host,chatgpt-bridge-dsh-host,tests/adapters/adapter-tool-conformance.test.ts9/0 (246 expects),tests/server/server-runtime-diagnostics.test.ts.intent.ps1fails in 2.3 s when the parentheses are removed (Windows PowerShell binds-orand-andleft-to-right at equal precedence, so the unparenthesised form lets a small symlink fail open); the chat-side uniqueness guard, thehealthPidcorroboration term, the budget-file content compare, thechargedcounter in the gateway cancel proof and the runTurn-only skip list each go red alone under their own mutant, and every mutant was restored byte-exactly with a sha pair recorded.Not run, deliberately:
bun run test. The full suite is undecidable on this Windows box and this is a claim I want a maintainer to read as a limitation, not as a pass: both the branch tree and a cleanorigin/devworktree died on the runner's own 900 s ceiling with a rotating red set, andtests/windowsnever got scheduled. The Windows-facing gates above were therefore taken quiet, exclusive and with a same-windowgit show HEAD:control; a run of 4 reds inwindows-recovery-intentduring a period when the machine itself began reportingEACLIDENTITY(the effective account SID could not be resolved) was discarded rather than tuned around. CI on Linux, Windows and macOS is the gate for this pull request.Merge state: the branch is now 0 behind / 8 ahead of
dev—origin/devis merged in (651ff2f89), all 23 conflicts resolved and each decision recorded in that merge commit message. The two load-bearing ones: upstream routedhandleStopthrough an approval gate, so the durable-intent fence now wraps that gate (an approval refusal rolls the writtenstoppedback through the same path as an ownership refusal); andsrc/tray/windows.tsreceived two independent additions at the same spot, so both survive — upstream'swindowsTrayRequiredFilesPresent` (which fixes the dotted-icon stale-install bug) AND our per-home intent-helper requirement, composed rather than chosen.Security-sensitive surfaces, flagged rather than left to be found
Recovery marker and intent files are a trust boundary the guardian reads before it dispatches a lifecycle action (reparse point, size ceiling, maintenance-window contract);
readKey/capability handling in the bridge store touches credentials; the preset change alters what the dashboard declares it can do. The two known-unfixed items in this area are recorded instead of patched, so they are visible here:recovery-incidents/<ts>/receipt.jsonstores the model's own diagnosis text (bounded, keyword-scrubbed per line), and a repair origin pointed at a public third party would send up to 16 KiB of real source out of the machine, where scrubbing is a per-line keyword filter. Both hinge on whether remote self-repair ships publicly at all.Checklist