diff --git a/devlog/_plan/260806_disposition_sweep/000_plan.md b/devlog/_plan/260806_disposition_sweep/000_plan.md new file mode 100644 index 000000000..5a5b79c36 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/000_plan.md @@ -0,0 +1,65 @@ +# 000 — Plan: 10-item disposition sweep (2026-08-06) + +## Objective + +Dispose of exactly the ten items surfaced in the 2026-08-06 triage report +(user steering: "모든 pr은 아니고 너가 제시한 것만 처리"), record every +action in this unit, and open the unit as a PR. **Nothing merges to dev in +this loop** — code changes and the devlog land via an open PR only. + +## Base + +| Fact | Value | +|------|-------| +| `origin/dev` | `b3a1d90a8` (bfbc9a405 + devlog-only ledger commits; re-frozen after audit finding 1) | +| Worktree | `/Users/jun/.codex/worktrees/37e6/opencodex`, branch `codex/260806-disposition-sweep` | +| Scope freeze | the 10 items below; later arrivals (e.g. #1092) are OUT | + +## Disposition rules (user authorization 2026-08-06) + +| Rule | Bucket | Action | +|------|--------|--------| +| R1 | INCOMPLETE | close with a detailed defect list + "complete and reopen" guidance | +| R2 | NON-BUG | comment evidence, close, invite reopen with repro | +| R3 | OWN-PR | rebase onto dev, terra-verify, push to the PR branch — **no merge** | +| R4 | ABSORBED | close with source-level evidence (file:line or merge SHA) | +| R5 | STALE-CLEAR | complete-quality code but undecided intent → stale-mark comment, keep open | +| R6 | SHELL | non-compiling / no-op / cosmetic-only → close | + +No merges this loop. Own-PR lanes end at "pushed, CI running, PR open". + +## The ten items + +| # | Item | Rule | Planned action | +|---|------|------|----------------| +| 1 | #1017 + PR #1036 (Cursor apply_patch) | R1-review | request-changes comment: synthetic-tool name provenance + final-catalog gaps; PR stays open (author active) | +| 2 | #919 (socket reset vs affinity) | R2 | close as intended-policy/enhancement with maintainer rationale; do NOT cite #914 as the successor (closed, pre-header scope only — audit finding 2); reopen path = concrete attribution-policy proposal or new repro | +| 3 | #1090 + #1091 (base_url injection) | R4-partial | #1090: regression test for the external-provider path on sweep branch + comment distinguishing attempt 1 (fixed, `inject.ts:74,636-658`) from attempt 3 (`model_provider="opencodex"` re-runs injection by design, `inject.ts:701-747`); close ONLY if attempt-3 scope proves by-design/resolved after full read — else keep open with status. #1091: status comment, keep open | +| 4 | #994 + PR #1068 (DeepSeek reasoning replay) | R1-review | comment: rebase required (CONFLICTING), Zen slice credible, Claude-path gap stays open | +| 5 | #936 (own, trust boundaries) | R3 | rebase onto dev, terra security audit, push — PR stays open for human security review | +| 6 | #1059 (Windows suite) | keep-open | status comment defining shard-by-shard burn-down expectation | +| 7 | #1008 (own, usage rollup) | R3 | rebase, triage 29 threads → fix-now vs redesign, implement fix-now, push — no merge | +| 8 | #1019 (account picker lifecycle, 106 files) | R5-adjacent | comment: split request into reviewable slices; hygiene gate noted; stays open | +| 9 | agentHits campaign: PRs #1084/#1083/#1081/#1079/#1077 | R6/R1 | close each with tailored, verified defect list + explicit "complete and reopen" guidance (user rule R1; author is active — audit finding 5 noted, tone must be respectful and specific). Linked issues #1062/#1063/#1060/#1058/#1076/#1082 are IN SCOPE as part of item 9: one policy comment each, stay open. Verified defects: #1084 cooldown no-op (`oauth-account-routes.ts:374` → `clearAnthropicAccountCooldown` Anthropic-only `anthropic-routing.ts:117`), #1081/#1079 invalid TS in six locales (bare string after value) | +| 10 | #1085 + #997 (easy rebases) | R5-adjacent | comment asking authors to rebase; note READY verdict; stay open | + +PR state re-verified post-audit: #936 CONFLICTING (rebase required), #1068 +CONFLICTING, #1036 now MERGEABLE/CLEAN. + +## Work-phase map + +| Phase | Doc | Content | +|-------|-----|---------| +| wp0 | 000-001 | this plan + per-item disposition matrix (docs-only cycle) | +| wp1 | 010 | GitHub dispositions for items 1,2,3(comment),4,6,8,9,10 | +| wp2 | 020 | #1090 regression test on sweep branch; close #1090 only if the attempt-3 scope proves by-design/resolved, else status comment + keep open | +| wp3 | 030 | #936 rebase + terra security audit + push (no merge) | +| wp4 | 040 | #1008 rebase + thread triage + bounded fixes + push (no merge) | +| wp5 | 050 | closeout ledger + open sweep PR + live end-state snapshot | + +## Out of scope + +Any merge into dev, main/preview promotion, releases, new feature +implementation, PRs/issues outside the ten items (incl. #1092, #557, +provider-preset drafts), the user's usage-log 500k cap edits, +account/identity actions. diff --git a/devlog/_plan/260806_disposition_sweep/001_disposition_matrix.md b/devlog/_plan/260806_disposition_sweep/001_disposition_matrix.md new file mode 100644 index 000000000..ccb4d9d98 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/001_disposition_matrix.md @@ -0,0 +1,47 @@ +# 001 — Disposition matrix (audited, terra PASS) + +Scope: exactly the ten items from the 2026-08-06 triage report. User rules: +incomplete → close + resubmit guidance; non-bug → close with evidence; own +PRs → rebase + terra audit + push (NO MERGE); absorbed → close with +evidence; complete-but-undecided → stale-mark; shell → close. + +Base: `origin/dev` = `b3a1d90a8`. Audit trail: initial terra audit FAIL +(7 findings), amended, FAIL (wp2 contradiction), amended, PASS. + +| # | Target | Bucket | Action | Executor phase | +|---|--------|--------|--------|----------------| +| 1 | PR #1036 (+#1017) | R1-review | request-changes: synthetic-tool provenance, final-catalog derivation; stays open | wp1 | +| 2 | issue #919 | R2 close | close as intended-policy/enhancement; no #914 citation; reopen = attribution proposal or new repro | wp1 | +| 3a | issue #1090 | R4-partial | wp2 test first; close only if attempt-3 (`model_provider="opencodex"`) proves by-design; else status comment | wp2 | +| 3b | issue #1091 | comment | status comment: legitimate ask, security-sensitive design (config.ts:1253 gate), keep open | wp1 | +| 4 | PR #1068 (+#994) | R1-review | comment: rebase required (CONFLICTING), Zen slice credible, Claude-path gap remains; stays open | wp1 | +| 5 | PR #936 (own) | R3 | rebase onto b3a1d90a8+, terra security audit, push; PR stays open, NO merge | wp3 | +| 6 | issue #1059 | keep-open | status comment: shard-by-shard burn-down plan expectation | wp1 | +| 7 | PR #1008 (own) | R3 | rebase, triage 29 threads fix-now/redesign, implement fix-now, terra audit, push; NO merge | wp4 | +| 8 | PR #1019 | R5-adjacent | comment: split into reviewable slices, hygiene gate noted; stays open | wp1 | +| 9 | PRs #1084/#1083/#1081/#1079/#1077 + issues #1062/#1063/#1060/#1058/#1076/#1082 | R1/R6 close (PRs) + comment (issues) | close each PR with verified defect list + reopen invitation; issues get policy comment, stay open | wp1 | +| 10 | PRs #1085, #997 | R5-adjacent | rebase-request comments, READY verdict noted; stay open | wp1 | + +## Verified defect evidence for item 9 closes + +- #1084: cooldown endpoint permits `google-antigravity` but calls + `clearAnthropicAccountCooldown` which only clears the Anthropic health map + (`src/server/management/oauth-account-routes.ts:374`, + `src/oauth/anthropic-routing.ts:117`) — functional no-op for the new + provider; no pool-routing consumer for the added config. +- #1083: selector changes a badge only; metrics remain provider-aggregated. +- #1081: six locale files contain a bare string literal after a value + (`"prov.expiresAt": "...", "Accounts ({n})",`) — invalid TS, does not + compile; token expiry mislabeled as subscription expiry. +- #1079: same six-locale breakage; promised daily breakdown absent; + "yesterday" is a rolling window. +- #1077: closest to viable, but accepts refresh tokens via argv (leaks into + shell history/process lists), missing required GUI evidence, credential + surface needs security review. + +## Constraints + +- NO merge into dev anywhere in this loop. +- All sweep-branch changes (devlog + #1090 test) land via an open PR only. +- #919 close and agentHits closes are owner-policy decisions recorded here; + comments must be respectful, specific, and carry explicit reopen paths. diff --git a/devlog/_plan/260806_disposition_sweep/010_github_dispositions.md b/devlog/_plan/260806_disposition_sweep/010_github_dispositions.md new file mode 100644 index 000000000..2596575d9 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/010_github_dispositions.md @@ -0,0 +1,55 @@ +# 010 — wp1: GitHub dispositions (items 1,2,3b,4,6,8,9,10) + +All writes are comments/closes/reviews; no code, no merges. Every action +records its comment id in the ledger table at the bottom. + +## Planned actions + +1. PR #1036: review comment (request changes): (a) conversion keys on bare + tool name — a client-owned `edit_file` would be mistranslated; needs a + per-request synthetic-name set; (b) structured-edit availability derived + from the original request instead of the final prompt-filtered catalog. + Approach endorsed; stays open. +2. Issue #919: close (not-planned) — behavior is intended account-health + policy; reclassified enhancement; reopen path: concrete attribution + policy proposal or new repro isolating non-network cause. +3. Issue #1091: status comment — valid request; blocked on security design + (pool-eligibility gate at `src/config.ts:1253` is deliberate); keep open. +4. PR #1068: comment — rebase onto dev required (CONFLICTING); Zen registry + slice credible with tests; end-to-end Claude Messages continuation + regression still missing; #994 stays open either way. +5. Issue #1059: status comment — dispatch-only stands; expectation: + shard-by-shard burn-down, gate restored only after full green run. +6. PR #1019: comment — split request into reviewable slices (settings + schema / selector init / catalog convergence / GUI), hygiene gate must + pass; stays open. +7. agentHits PR closes (verified defects in 001): #1084, #1083, #1081, + #1079, #1077 — each closed with its specific defect list + explicit + "complete and reopen" invitation. Linked issues #1062/#1063/#1060/ + #1058/#1076/#1082: one policy comment each (ideas retained; small + independently-testable slices invited), stay open. +8. PRs #1085/#997: rebase-request comments; READY verdicts noted. + +## Ledger (filled during execution) + +| Target | Action | Comment/close id | Verified | +|--------|--------|------------------|----------| +| PR #1036 | review REQUEST_CHANGES | posted 2026-08-06 (gh pr review) | pending C | +| issue #919 | closed not-planned + comment | close via gh issue close | pending C | +| issue #1091 | status comment, open | 5199487703 | pending C | +| PR #1068 | rebase-request comment, open | 5199487780 | pending C | +| issue #1059 | status comment, open | 5199487879 | pending C | +| PR #1019 | split-request comment, open | 5199488679 | pending C | +| PR #1085 | security-pass comment, open | 5199488762 | pending C | +| PR #997 | rebase-request comment, open | 5199488854 | pending C | +| PR #1084 | closed + defect comment | gh pr close | pending C | +| PR #1083 | closed + defect comment | gh pr close | pending C | +| PR #1081 | closed + defect comment | gh pr close | pending C | +| PR #1079 | closed + defect comment | gh pr close | pending C | +| PR #1077 | closed + defect comment | gh pr close | pending C | +| issue #1062 | policy comment, open | 5199492623 | pending C | +| issue #1063 | policy comment, open | 5199492696 | pending C | +| issue #1060 | policy comment, open | 5199492785 | pending C | +| issue #1058 | policy comment, open | 5199492864 | pending C | +| issue #1076 | policy comment, open | 5199492948 | pending C | +| issue #1082 | policy comment, open | 5199493056 | pending C | diff --git a/devlog/_plan/260806_disposition_sweep/011_comment_drafts.md b/devlog/_plan/260806_disposition_sweep/011_comment_drafts.md new file mode 100644 index 000000000..31f1ad295 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/011_comment_drafts.md @@ -0,0 +1,179 @@ +# 011 — wp1 comment drafts (to be audited before posting) + +All comments post as the maintainer. English, per repo review policy. + +## 1. PR #1036 — review (REQUEST_CHANGES) + +> Thanks — the structured `edit_file`/`multi_edit` + server-side translation +> approach is the right direction for #1017, and we want to land it. Two +> gaps block it today: +> +> 1. **Synthetic-tool provenance.** Conversion keys on the bare tool name. +> If a client already exposes its own `edit_file`, its calls would be +> translated too. Track the synthetic names injected for *this request* +> (a per-request set threaded from tool-catalog construction to the +> conversion site in `src/adapters/cursor/protobuf-events.ts` / +> `live-transport.ts`) and convert only those. +> 2. **Final-catalog derivation.** Structured-edit availability is derived +> from the original request rather than the final prompt-filtered tool +> catalog; when filtering drops the tools the flag is stale. +> +> A regression test for each (client-owned `edit_file` passes through +> untouched; filtered catalog disables translation) and we can re-review it. + +## 2. Issue #919 — close (not planned) + +> Closing after a policy review. What the report shows is real and was +> reproduced, but the behavior is the intended account-health policy: +> post-200 transport failures count against the account so that persistent +> upstream trouble rotates traffic away. Treating a mid-stream socket reset +> as never-account-attributable would mask genuinely unhealthy accounts, +> and `terminalSource="synthetic"` alone does not establish that the reset +> was network-local — especially on the eager relay path. +> +> The right evolution here is a transport-attribution policy (classifying +> post-200 failures before they touch affinity), which is an enhancement, +> not a defect fix. Happy to reopen against a concrete attribution +> proposal, or a repro isolating a non-network cause for the resets. + +## 3b. Issue #1091 — status comment (keep open) + +> This is a legitimate request and we want to support it; flagging why it +> is not a quick change. The pool-eligibility gate that rejects non-default +> base URLs (`src/config.ts` provider validation) is deliberate: OAuth +> tokens for chatgpt.com must not be sendable to an arbitrary URL by a +> config edit, so lifting the restriction needs an explicit trust design +> (allowlist semantics, SSRF/private-network policy, and tests for header +> and account-selection behavior against a custom upstream). Keeping this +> open as a design-needed enhancement. + +## 4. PR #1068 — comment (stays open) + +> The registry slice looks right: the missing `opencode-zen` metadata is +> exactly what breaks reasoning replay there, and the focused tests cover +> it. Two things before this can land: (1) the branch is currently +> conflicting with `dev` — please rebase; (2) the tests exercise a +> synthesized adapter context only — an end-to-end regression for a real +> Claude Messages continuation (thinking block replayed on the second +> request) would prove the fix where users hit it. Note #994 stays open +> either way: the Claude `/v1/messages` replay path dropping thinking is a +> separate gap from the Zen registry fix. + +## 6. Issue #1059 — status comment (keep open) + +> Status: the Windows leg stays dispatch-only. Plan of record: burn down +> the ~207 failures shard by shard (management/server fixtures first, then +> platform process semantics), restore the gate only after a full green +> Windows run on `dev`. Shard-scoped PRs welcome; each should name the +> shard and the failure class it eliminates. + +## 8. PR #1019 — comment (stays open) + +> Thanks for keeping this current against `dev`. As one PR this is not +> reviewable to the standard account-lifecycle code needs: 106 files / +> +4,786 lines touching account routing and credential lifecycle. Please +> split into slices, roughly: (1) settings schema + defaults, (2) selector +> initialization, (3) catalog convergence handling, (4) management API + +> GUI. Each slice with its own tests and green hygiene gate. The feature +> itself is wanted; the shape is the blocker. + +## 9. agentHits PR closes (5) + +### PR #1084 — close + +> Closing this draft for now — the direction (Antigravity account pool) is +> wanted, but the current cut implements configuration without the runtime +> that would use it: (1) no pool-routing consumer reads the added config; +> (2) the cooldown endpoint accepts `google-antigravity` but calls +> `clearAnthropicAccountCooldown`, which only clears the Anthropic health +> map (`src/server/management/oauth-account-routes.ts` → +> `src/oauth/anthropic-routing.ts`) — a functional no-op for the new +> provider; (3) quota parsing duplicates existing logic. Please reopen (or +> open fresh) with a slice that wires a real consumer first — a generic +> pool-routing path for Google accounts — and we will review it properly. + +### PR #1083 — close + +> Closing this draft — the account filter currently changes the badge +> only; every metric underneath remains provider-aggregated, so the +> feature it advertises (#1063, per-account usage) is not delivered by +> this diff. The missing piece is the data path: per-account usage +> attribution at write time, then a filtered read. Please reopen once the +> selector actually filters the aggregation; the UI shell here can come +> along with it. + +### PR #1081 — close + +> Closing this draft — it does not compile: all six locale files gained a +> bare string literal after a value (`"prov.expiresAt": "...", +> "Accounts ({n})",`), which is invalid TypeScript. Separately, the value +> shown is the OAuth token expiry, which renews — labeling it +> "subscription/plan expiration" (#1060) is misleading; plan expiry needs +> a real subscription source. Please reopen with compiling locales and a +> data source that actually reflects plan expiration. + +### PR #1079 — close + +> Closing this draft — the six locale files have the same invalid-syntax +> issue as #1081 (bare string after a value), so it does not compile. The +> server-side range extension is plausible and worth salvaging, but the +> promised daily model breakdown (#1058) is absent, and "yesterday" is a +> rolling 24h window rather than a calendar day. Please reopen with +> compiling locales, the breakdown implemented, and calendar-day +> semantics (or a documented choice). + +### PR #1077 — close + +> Closing this draft — closest of the batch to landing, and the token +> refresh validation is done right. Blockers: (1) refresh tokens are +> accepted via argv, which leaks into shell history and process listings — +> take them via file path or stdin only; (2) the GUI change ships without +> the required screenshot evidence; (3) credential import is a +> security-sensitive surface and needs a maintainer-sponsored review +> pass. Please reopen with file/stdin-only input and the GUI evidence; +> this one we would like to take. + +## 9b. agentHits issue comments (6 — same text, issue-adjusted) + +For #1062/#1063/#1060/#1058: + +> Keeping this open — the idea is wanted. The draft PR attached to this +> campaign was closed with specific technical feedback (see the PR +> thread); the ideas stay tracked here. What gets a fast review: small, +> rebased, independently testable slices that wire the runtime/data path +> first and the UI second, one concern per PR. + +For #1076: + +> Keeping this open — Cockpit Tools import is the piece of this campaign +> we most want to take. PR #1077 was closed with specific feedback: accept +> refresh tokens via file path or stdin only (argv leaks into shell +> history and process listings), include the required GUI screenshot +> evidence, and expect a maintainer-sponsored security review on the +> credential-import surface. A reopened PR addressing those three lands on +> a fast review track. + +For #1082: + +> Keeping this open — quota/reset-time display is a good fit once the +> per-account data path exists. The related campaign PRs were closed with +> technical feedback (see #1084/#1083 threads): the blocker is that +> current drafts render UI over provider-aggregated data with no +> per-account runtime consumer. A slice that wires the quota probe data +> path first, then the display, is welcome. + +## 10a. PR #1085 — comment + +> Verdict from triage: READY pending a credential-destination security +> pass, since the change affects which loopback destinations models stay +> visible for without an env export. No code defects found; the branch is +> current against `dev`, so after the security pass and a green rerun it +> is ready for final review. + +## 10b. PR #997 — comment + +> Still wanted — the fixture isolation is correct and the setup/teardown +> restores the environment properly. It has drifted far behind `dev` +> (~142 commits); please rebase so CI can rerun on current code. Low +> conflict risk expected; after a green run it is ready for maintainer +> review. diff --git a/devlog/_plan/260806_disposition_sweep/020_1090_regression_test.md b/devlog/_plan/260806_disposition_sweep/020_1090_regression_test.md new file mode 100644 index 000000000..96197b26f --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/020_1090_regression_test.md @@ -0,0 +1,59 @@ +# 020 — wp2: #1090 external-provider config preservation test (plan revised at P) + +## Finding (revised with new evidence) + +The "absorbed" hypothesis is NOT proven. The external-provider guard +(`externalCodexModelProvider`, `src/codex/inject.ts:74`; early return at +`inject.ts:636-658`) landed in `b3d1bc67f`, which IS an ancestor of +`v2.10.0` — the exact version the reporter ran. Yet the reporter observed +`model_provider = "deepseek"` being rewritten to `"openai"` by `ocx sync` +on Windows. So either (a) a path reachable from `ocx sync` +(`syncModelsToCodex` → `injectCodexConfig`, `src/codex/sync.ts:58,110`) +bypasses the guard under some input shape, or (b) the reporter's real +config differed from the redacted one (e.g. a `profile` key overriding the +root provider — `resolveEffectiveProjectModelProvider` prefers the profile +section), or (c) a Windows-specific parse issue (CRLF handled at +`dominantEol`, but the guard runs on `rawContent` BEFORE EOL +normalization — `parseTomlDocument` splits on `"\n"`, leaving `\r` at +value ends; the kv regex `[^\s#]+` excludes `\r` via `\s`, needs proof). + +Existing coverage: `tests/codex-inject-integration.test.ts:366` proves the +generic external-provider case byte-for-byte (LF, `custom` provider). It +does NOT cover: CRLF Windows files, the reporter's exact shape (deepseek + +`[model_providers.opencodex]` table coexisting), or a root provider with +quoted values and a `windows` table. + +Attempt 3 (`model_provider = "opencodex"`) re-runs injection by design +(`inject.ts:701-747`) — routed mode; not a defect, but the report's claim +"model and model_provider lines removed" during that path is expected +behavior that deserves explanation, not denial. + +## Work + +1. Add a reporter-shape regression test in + `tests/codex-inject-integration.test.ts`: CRLF Windows-style config with + `model_provider = "deepseek"`, `model = "deepseek-v4-flash"`, + `[model_providers.opencodex]` table, and `[windows]` section — must + survive `injectCodexConfig()` byte-for-byte (same assertion style as the + existing :366 test). +2. If the test PASSES: the guard holds for the reported shape on current + dev; disposition = status comment on #1090 (attempt 1 guarded since + v2.7.36 and covered by the new test; attempt 3 by-design with + explanation; ask reporter for their real config/profile lines if still + reproducible on ≥ current release) — keep OPEN pending reporter + confirmation, per audit rule (close only if fully proven). +3. If the test FAILS: real defect on dev; record RCA, fix in this sweep + branch is out of scope creep — file the failing test + status comment, + defer the fix decision to the user. +4. `bun run typecheck` + focused test file green (or red with RCA). + +## Ledger + +| Step | Evidence | +|------|----------| +| Regression test added | `tests/codex-inject-integration.test.ts` "#1090: CRLF Windows config..." — commit `b63e86a8b` | +| Test PASSES on dev | 23 pass / 0 fail (full file); guard holds for reporter shape | +| Red ablation | guard neutered locally → 1 fail; restored → pass (proves non-vacuous) | +| typecheck | `bun x tsc --noEmit` clean | +| Disposition | #1090 kept OPEN — status comment 5199554901: attempt-1 guarded + tested, profile-masking question to reporter, attempt-3 by-design, symptom tracked in #1091 | +| terra audit | PASS (reviewer 019fd4cd): CRLF cannot defeat guard; no sync bypass; profile masking plausible explanation | diff --git a/devlog/_plan/260806_disposition_sweep/030_936_rebase.md b/devlog/_plan/260806_disposition_sweep/030_936_rebase.md new file mode 100644 index 000000000..3142640f3 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/030_936_rebase.md @@ -0,0 +1,28 @@ +# 030 — wp3: PR #936 (own) rebase + terra security audit + push (NO MERGE) + +Head `codex/916-trust-boundaries`, CONFLICTING vs dev, ~696 commits behind. +Content: launcher provenance, Anthropic env/destination trust, local +management attestation, Vertex location validation. + +## Work + +1. Fetch branch; enumerate conflicts against `b3a1d90a8`+. +2. Rebase (or merge-dev, matching repo convention) resolving conflicts; + duplication check: any hardening already landed on dev since the PR was + cut must be dropped from the diff, not duplicated. +3. terra audit: regression + security review of the rebased diff + (credential paths, redaction boundaries, attestation semantics). +4. `bun run typecheck` + full `bun run test` on the branch. +5. Push to the PR branch (`--no-verify` per repo workflow if needed); + PR stays open/draft for human security review. NO merge. + +## Ledger + +| Step | Evidence | +|------|----------| +| Merge dev into branch | `a90981e67` (origin/dev `b3a1d90a8` → `codex/916-trust-boundaries`); conflicts: auth-cors.ts (redactSecretString + effectiveGoogleMode composed), server/index.ts (localAttestationSecret folded into StartServerDeps, CLI caller → object form) | +| Duplication check | terra: no equivalent hardening landed on dev since branch point `6a7351b4d` — nothing double-applies | +| terra security audit | FAIL(3 stale test call-sites for old positional secret) → fixed in `4874390dd` → PASS; four hardening claims verified on merged tree with file:line (Vertex location, Bun provenance, Claude ambient fail-closed, health attestation gate) | +| Tests | typecheck clean; full suite 9076 pass / 0 fail / 8 skip (579 files, 281s) | +| Push | `727722cba..4874390dd` on origin; PR #936 OPEN draft — NOT merged (human security review per MAINTAINERS.md still required) | +| PR comment | 5199634303 | diff --git a/devlog/_plan/260806_disposition_sweep/040_1008_rebase.md b/devlog/_plan/260806_disposition_sweep/040_1008_rebase.md new file mode 100644 index 000000000..f8f91f689 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/040_1008_rebase.md @@ -0,0 +1,55 @@ +# 040 — wp4: PR #1008 (own) rebase + thread triage + bounded fixes + push (NO MERGE) + +Head `codex/260804-usage-rollup`, MERGEABLE/clean vs dev `b3a1d90a8` +(4 ahead / 414 behind; dev has NOT touched the rollup/summary/api-key files +since the merge base, so conflict risk is low), 29 unresolved review +threads. CAUTION: the PR modifies `src/usage/log.ts` (+12/-6) — same file +as the user's uncommitted 500k-cap edits in the MAIN checkout. All work +happens in THIS worktree against `origin/dev`; never touch the dirty +checkout, and flag the overlap to the user before any future merge. + +## Work + +1. `git fetch origin dev`, then rebase the 4 branch commits onto the + fetched `origin/dev` in the sweep worktree (force-push with lease to the + own-PR branch afterwards). +2. Implement the REDUCED fix-now set (audit finding 4); each fix with a + focused test. +3. terra audit of the result; typecheck + full test; push; reply to + threads with resolution or defer rationale; PR stays open. NO merge. + +## Thread triage (29 unresolved, pulled 2026-08-06; revised per audit) + +Fix-now (reduced, audit-approved minimal honest set): + +- T0/T17 + T1: bound each fold segment by bytes/day (NOT a streaming + rewrite — cap `parseUsageRange` segment size, keep segment-chain + format) coupled with bounded/yielding cutline scan +- T2/T15: validate committed boundary (read-time + throttle validity) + after truncation/rewrite +- T3/T16: advance past complete malformed rows +- T4/T12: honor usageRollupEnabled in API-key summaries +- T28: isolate the rowCount check in test 2c (digest restore defect) +- T7/T10: docs exactness qualifiers (cheap wording, moved from defer) + +Defer-with-rationale (redesign-scale or judgment): + +- T14 compaction/rewrite analysis, T21 partial-range day boundary, + T22 overflow dedup — heavy lifts, explicit defer with rationale +- T5 timezone rebuild — document as known limitation +- T6 all-range oldest timestamp scope — judgment, defer +- T13/T18/T20 — valid but not required this phase; T20 needs an + observability contract, not a catch tweak; defer +- T8/T9/T11/T19/T23/T24/T25/T26/T27 minor/trivial — defer or batch later + +## Ledger + +| Step | Evidence | +|------|----------| +| Rebase | `codex/260804-usage-rollup` rebased onto `origin/dev` `b3a1d90a8` — clean, no conflicts (4 commits replayed) | +| Fix commits | `8e657f2a1` (segment cap + yield + malformed advance + read-time boundary + usageRollupEnabled + docs + test 2c), `49cb22c3d` (every-segment validation, id-less rows), `8d1eec899` (memoized validation per raw revision, documented digest-window contract) | +| terra audit rounds | FAIL(last-segment-only 4KB window, per-call cost) → fixed → FAIL(window scope, memoization) → fixed/rationale → PASS (finding 1 accepted as documented contract matching fold-time behavior) | +| Tests | focused 33 pass/0 fail; full suite 9088 pass / 0 fail / 8 skip (580 files); typecheck clean | +| Push | force-with-lease `b0d5417d8 → 8d1eec899`; PR #1008 OPEN, NOT merged | +| PR comment | 5199782814 (fixed list + deferred-with-rationale list) | +| log.ts overlap | PR touches `src/usage/log.ts`; user's uncommitted 500k-cap edits remain untouched in main checkout — flagged for pre-merge attention | diff --git a/devlog/_plan/260806_disposition_sweep/050_closeout.md b/devlog/_plan/260806_disposition_sweep/050_closeout.md new file mode 100644 index 000000000..afc68a705 --- /dev/null +++ b/devlog/_plan/260806_disposition_sweep/050_closeout.md @@ -0,0 +1,38 @@ +# 050 — wp5: closeout ledger + sweep PR + live end-state + +## Work + +1. Verify every 001-matrix row has a live GitHub disposition (comment id, + close state, or push SHA) — `gh` snapshot per item. +2. Complete all decade-doc ledgers. +3. Commit the devlog unit + #1090 test on `codex/260806-disposition-sweep`. +4. Push the branch and open a PR against dev (template fully filled). + **Leave it unmerged** — user constraint: 절대 dev에 머지하면 안돼. +5. Final snapshot table in this doc. + +## Final ledger + +| Item | Disposition | Live evidence | +|------|-------------|---------------| +| 1. PR #1036 (+#1017) | request-changes review posted; approach endorsed | OPEN / CHANGES_REQUESTED | +| 2. issue #919 | closed as intended-policy/enhancement, reopen path stated | CLOSED / NOT_PLANNED | +| 3a. issue #1090 | regression test landed on sweep branch (b63e86a8b, red-ablation proven); kept OPEN with status comment 5199554901 (absorption unproven for profile-masking shape) | OPEN | +| 3b. issue #1091 | status comment 5199487703 (design-needed, security-sensitive) | OPEN | +| 4. PR #1068 (+#994) | rebase-request + e2e-regression comment 5199487780 | OPEN | +| 5. PR #936 (own) | merged dev in (a90981e67), terra security audit PASS, fixes 4874390dd, full suite 9076/0, pushed; comment 5199634303 | OPEN draft, head 4874390dd, NOT merged | +| 6. issue #1059 | shard burn-down status comment 5199487879 | OPEN | +| 7. PR #1008 (own) | rebased onto dev, thread fixes 8e657f2a1/49cb22c3d/8d1eec899, terra 3-round PASS, 9088/0, lease-pushed; comment 5199782814 | OPEN, head 8d1eec899, NOT merged | +| 8. PR #1019 | split-request comment 5199488679 posted; author chrisae9 closed the PR himself at 02:03Z (his decision, not ours) | CLOSED by author | +| 9. PRs #1084/#1083/#1081/#1079/#1077 | closed with verified defect lists + reopen invitations; issues #1062/#1063/#1060/#1058/#1076/#1082 policy comments 5199492623-5199493056, kept open | all 5 PRs CLOSED, 6 issues OPEN | +| 10. PR #1085 / #997 | security-pass comment 5199488762 / rebase-request comment 5199488854 | both OPEN | + +Snapshot taken 2026-08-06 ~02:20Z via `gh` per-item queries. Constraint held: +no merges into dev anywhere in this loop; own-PR lanes ended at pushed+open. + +## Sweep PR + +Branch pushed and PR opened against dev, left unmerged per user constraint: +https://github.com/lidge-jun/opencodex/pull/1097 (head `99b3b2120` + this +commit). Final audit: terra PASS (finding on phantom production commit +retracted with ancestry evidence; sweep range = 7 devlog commits + the +#1090 test commit). diff --git a/tests/codex-inject-integration.test.ts b/tests/codex-inject-integration.test.ts index a65ad66c3..0b73f1e26 100644 --- a/tests/codex-inject-integration.test.ts +++ b/tests/codex-inject-integration.test.ts @@ -422,9 +422,40 @@ describe("injectCodexConfig integration (Design B)", () => { expect(readFileSync(join(codexHome, "config.toml"), "utf8")).toBe(original); expect(readFileSync(profilePath, "utf8")).toBe(profile); - expect(readFileSync(dbPath).equals(dbBefore)).toBe(true); - expect(readFileSync(rolloutPath, "utf8")).toBe(rollout); - expect(existsSync(journalPath)).toBe(false); + expect(readFileSync(dbPath).equals(dbBefore)).toBe(true); + expect(readFileSync(rolloutPath, "utf8")).toBe(rollout); + expect(existsSync(journalPath)).toBe(false); + }); + + // Regression for #1090: the reporter's Windows shape — CRLF line endings, an external + // root model_provider, a coexisting [model_providers.opencodex] table, and a [windows] + // section — must survive injectCodexConfig byte-for-byte. The external-provider guard + // runs on raw (pre-EOL-normalized) content, so CRLF parsing is part of what this proves. + test("#1090: CRLF Windows config with external deepseek provider and opencodex table stays byte-for-byte unchanged", () => { + const original = [ + 'model = "deepseek-v4-flash"', + 'model_provider = "deepseek"', + "", + "[model_providers.opencodex]", + 'name = "opencodex"', + 'base_url = "http://127.0.0.1:10100/v1"', + 'wire_api = "responses"', + 'env_key = "CODEX_DEEPSEEK_API_KEY"', + "", + "[windows]", + 'sandbox = "unelevated"', + "", + ].join("\r\n"); + writeFileSync(join(codexHome, "config.toml"), original, "utf8"); + + const r = runInject(codexHome, ocxHome); + expect(r.status).toBe(0); + const result = JSON.parse(r.stdout); + expect(result.success).toBe(true); + expect(result.message).toContain("routing NOT injected"); + expect(result.message).toContain('external model_provider "deepseek"'); + + expect(readFileSync(join(codexHome, "config.toml"), "utf8")).toBe(original); }); test("restoreNativeCodex removes a stale journal without changing external provider state", () => {