From 859dc0371d6212fff30d1acb32f876fd17a792a2 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 17:57:55 +0000 Subject: [PATCH 01/23] docs: record the direct-coverage wave in the audit delivery log Adds section 5.2 listing the eight independent test suites (#559-#567) that give the phase-3/phase-4 extracted login machinery, health check, and persistence helpers direct coverage. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index f8148b01..fc5a93cf 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -177,6 +177,26 @@ Remaining deferred: the mock-factory migration of the giant suites `index.test.ts`/`runtime-rotation-proxy.test.ts` (stacks on #537's helpers; 202 `vi.mock` call sites in `index.test.ts` alone, deferred for size). +### 5.2 Direct-coverage wave (added 2026-06-10, after the roadmap merge) + +The phase-3/phase-4 extractions (§4.1.1) left ~2,500 lines of login machinery, +health-check, and persistence helpers reachable only through the giant CLI +suites. Writing direct suites for extracted modules surfaced real bugs twice +earlier in this cycle, so the method was applied across the remaining gaps. +Every PR below is independent and based on `main`; each mocks only the +effectful seams and runs the real identity-matching / retry / parsing logic. + +| PR | Suite | Pins | +|----|-------|------| +| [#559](https://github.com/ndycode/codex-multi-auth/pull/559) | `test/login-oauth-selection.test.ts` | login-oauth `resolveAccountSelection` through the real candidate extraction (only `decodeJWT` mocked): #491/#512 workspaces persistence incl. the explicit `--org` path, org-override precedence, cancellation/abort predicates | +| [#560](https://github.com/ndycode/codex-multi-auth/pull/560) | `test/login-menu-actions.test.ts` | `handleManageAction` with the real `findMatchingAccountIndex`: delete/toggle re-resolve by identity under concurrent reorder, active-index rebalancing, refresh transports (cancel/manual via stubbed select), non-TTY prompt fallbacks | +| [#561](https://github.com/ndycode/codex-multi-auth/pull/561) | `test/login-flow.test.ts` | `runAuthLogin` with the real arg parser and cancellation predicate: explicit transports bypass the dashboard and exit on cancel, `--org` threads as an argument (no env mutation), inserted/updated/rebound messaging, MAX_ACCOUNTS cap, forced re-login on add-another | +| [#563](https://github.com/ndycode/codex-multi-auth/pull/563) | `test/login-menu-data.test.ts` | quota probe targeting (safe-storability gate), the dashboard row view model (status mapping, ready-first ordering, quick-switch numbering), runtime current-selection loading, Codex CLI drift sync incl. writer-false | +| [#564](https://github.com/ndycode/codex-multi-auth/pull/564) | `test/persist-selected-account.test.ts` | the shared switch/best/restore persistence helper: family-index bookkeeping, validation refresh (success/graceful failure), pinning, the #474 affinity bump on max(disk, memory), EBUSY retry | +| [#565](https://github.com/ndycode/codex-multi-auth/pull/565) | `test/health-check.test.ts` | `runHealthCheck` quick + live probe: fresh-session trust, rotated-credential write-back and CLI sync, refresh-then-probe with the rotated token, re-login vs still-works classification, cache-save failure tolerance | +| [#566](https://github.com/ndycode/codex-multi-auth/pull/566) | `test/forecast-report-shared.test.ts` | mock-free: `persistRefreshedAccountPatch` identity re-resolution incl. the patched-credentials fallback, `saveAccountsWithRetry` retry/give-up policy, forecast row serialization | +| [#567](https://github.com/ndycode/codex-multi-auth/pull/567) | `test/settings-write-queue.test.ts` | `withQueuedRetry` only (the helper exports are internal surface): retry schedule with injected sleep, 429 retry-after clamping, strict per-path ordering, failed predecessors not blocking, retries staying inside their queue slot | + --- ## 6. Findings investigated and REJECTED (do not re-report) From 53624378eefc4811ae8e468ea87b7106dfc2258e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:01:21 +0000 Subject: [PATCH 02/23] docs: note the issue-number gaps in the coverage-wave table #558 and #562 are issues (knip CI tracking; maintainer MCP-auth test), not PRs, so the wave numbering legitimately skips them. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index fc5a93cf..992db962 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -185,6 +185,8 @@ suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle, so the method was applied across the remaining gaps. Every PR below is independent and based on `main`; each mocks only the effectful seams and runs the real identity-matching / retry / parsing logic. +(The number sequence skips #558 and #562, which are issues — the knip CI +tracking issue and a maintainer MCP-auth test — not PRs.) | PR | Suite | Pins | |----|-------|------| From 75018b208abef5e6c6c8b7b04324abae557e1264 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:09:45 +0000 Subject: [PATCH 03/23] docs: cite the bugs the coverage method surfaced Inline the #544 isRecord and #546 stream-stall references so the 'surfaced real bugs twice' claim is verifiable without scrolling to section 5.1. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 992db962..b37c09bb 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -182,7 +182,8 @@ Remaining deferred: the mock-factory migration of the giant suites The phase-3/phase-4 extractions (§4.1.1) left ~2,500 lines of login machinery, health-check, and persistence helpers reachable only through the giant CLI suites. Writing direct suites for extracted modules surfaced real bugs twice -earlier in this cycle, so the method was applied across the remaining gaps. +earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall +fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`; each mocks only the effectful seams and runs the real identity-matching / retry / parsing logic. (The number sequence skips #558 and #562, which are issues — the knip CI From b32c72cb1911fa098a3323bae87654734efc8a57 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:19:57 +0000 Subject: [PATCH 04/23] docs: extend the coverage-wave table through #572 Adds the dashboard-settings-data, rotation-account-selection, rotation-token-refresh, and rotation-proxy-state suites delivered after the table was first written. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index b37c09bb..d4a417f6 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -199,6 +199,10 @@ tracking issue and a maintainer MCP-auth test — not PRs.) | [#565](https://github.com/ndycode/codex-multi-auth/pull/565) | `test/health-check.test.ts` | `runHealthCheck` quick + live probe: fresh-session trust, rotated-credential write-back and CLI sync, refresh-then-probe with the rotated token, re-login vs still-works classification, cache-save failure tolerance | | [#566](https://github.com/ndycode/codex-multi-auth/pull/566) | `test/forecast-report-shared.test.ts` | mock-free: `persistRefreshedAccountPatch` identity re-resolution incl. the patched-credentials fallback, `saveAccountsWithRetry` retry/give-up policy, forecast row serialization | | [#567](https://github.com/ndycode/codex-multi-auth/pull/567) | `test/settings-write-queue.test.ts` | `withQueuedRetry` only (the helper exports are internal surface): retry schedule with injected sleep, 429 retry-after clamping, strict per-path ordering, failed predecessors not blocking, retries staying inside their queue slot | +| [#569](https://github.com/ndycode/codex-multi-auth/pull/569) | `test/dashboard-settings-data.test.ts` | settings clone/equality contract with the real layout-mode resolver: sparse legacy objects clone to documented defaults, explicit layout mode beats the legacy boolean, equality sweeps every independent field comparison | +| [#570](https://github.com/ndycode/codex-multi-auth/pull/570) | `test/rotation-account-selection.test.ts` | `chooseAccount` through a real AccountManager: #474 pin discipline (wins without cursor commit, never falls back, full skip-reason taxonomy), affinity tier, hybrid + linear fallback cursor rules, #509 sequential mode never moving the drain-first primary on transient failure | +| [#571](https://github.com/ndycode/codex-multi-auth/pull/571) | `test/rotation-token-refresh.test.ts` | `ensureFreshAccessToken` with real cooldown bookkeeping: fresh-token short-circuit, rotate-and-commit, concurrent-commit dedup, the #495 invalidation cooldown + monotonic guard, commit-failure degradation | +| [#572](https://github.com/ndycode/codex-multi-auth/pull/572) | `test/rotation-proxy-state.test.ts` | proxy state init and pool-exhausted stale-state recovery: manager swap with the previous pool kept known, routing-mutex carry-over, 1s reload dedupe incl. concurrent sharing, failed-reload retry | --- From 78ee8ad76a3738786247915418bcff3b7c568b9b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:27:17 +0000 Subject: [PATCH 05/23] docs: add the auth-menu-builder suite to the coverage-wave table https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index d4a417f6..08d7908a 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -203,6 +203,7 @@ tracking issue and a maintainer MCP-auth test — not PRs.) | [#570](https://github.com/ndycode/codex-multi-auth/pull/570) | `test/rotation-account-selection.test.ts` | `chooseAccount` through a real AccountManager: #474 pin discipline (wins without cursor commit, never falls back, full skip-reason taxonomy), affinity tier, hybrid + linear fallback cursor rules, #509 sequential mode never moving the drain-first primary on transient failure | | [#571](https://github.com/ndycode/codex-multi-auth/pull/571) | `test/rotation-token-refresh.test.ts` | `ensureFreshAccessToken` with real cooldown bookkeeping: fresh-token short-circuit, rotate-and-commit, concurrent-commit dedup, the #495 invalidation cooldown + monotonic guard, commit-failure degradation | | [#572](https://github.com/ndycode/codex-multi-auth/pull/572) | `test/rotation-proxy-state.test.ts` | proxy state init and pool-exhausted stale-state recovery: manager swap with the previous pool kept known, routing-mutex carry-over, 1s reload dedupe incl. concurrent sharing, failed-reload retry | +| [#573](https://github.com/ndycode/codex-multi-auth/pull/573) | `test/auth-menu-builder.test.ts` | the auth dashboard view-model formatters, asserted with ANSI stripped so both UI palettes hold: identity precedence + ANSI/control-character stripping in row titles, status badges/colors, hint field ordering, focus keys on storage position | --- From 9e5df6adc895b126658f14b9b02a7572e50b1913 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:39:27 +0000 Subject: [PATCH 06/23] docs: record the property-suite companions in the coverage table https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 08d7908a..572cb957 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -204,6 +204,8 @@ tracking issue and a maintainer MCP-auth test — not PRs.) | [#571](https://github.com/ndycode/codex-multi-auth/pull/571) | `test/rotation-token-refresh.test.ts` | `ensureFreshAccessToken` with real cooldown bookkeeping: fresh-token short-circuit, rotate-and-commit, concurrent-commit dedup, the #495 invalidation cooldown + monotonic guard, commit-failure degradation | | [#572](https://github.com/ndycode/codex-multi-auth/pull/572) | `test/rotation-proxy-state.test.ts` | proxy state init and pool-exhausted stale-state recovery: manager swap with the previous pool kept known, routing-mutex carry-over, 1s reload dedupe incl. concurrent sharing, failed-reload retry | | [#573](https://github.com/ndycode/codex-multi-auth/pull/573) | `test/auth-menu-builder.test.ts` | the auth dashboard view-model formatters, asserted with ANSI stripped so both UI palettes hold: identity precedence + ANSI/control-character stripping in row titles, status badges/colors, hint field ordering, focus keys on storage position | +| [#574](https://github.com/ndycode/codex-multi-auth/pull/574) | `test/property/model-fallback.property.test.ts` | fast-check invariants for the unsupported-model fallback: any returned fallback is a chain member, never the current or an attempted model (under any prefix/suffix/casing spelling), legacy gpt-5.3 edge toggle respected, exhausted chains give up | +| [#575](https://github.com/ndycode/codex-multi-auth/pull/575) | `test/property/settings-write-queue.property.test.ts` | fast-check invariants for the write queue: per-key invocations stay contiguous and in submission order under any ok/flaky/fatal schedule, fatal tasks never block successors, 429 retry-after hints clamp into 10ms..30s | --- From e617f225923336a04c96738fa0b45a4aa264f431 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 18:58:47 +0000 Subject: [PATCH 07/23] docs: record the convention doc and beta.2 drift fix in the table https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 572cb957..f36a9761 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -206,6 +206,8 @@ tracking issue and a maintainer MCP-auth test — not PRs.) | [#573](https://github.com/ndycode/codex-multi-auth/pull/573) | `test/auth-menu-builder.test.ts` | the auth dashboard view-model formatters, asserted with ANSI stripped so both UI palettes hold: identity precedence + ANSI/control-character stripping in row titles, status badges/colors, hint field ordering, focus keys on storage position | | [#574](https://github.com/ndycode/codex-multi-auth/pull/574) | `test/property/model-fallback.property.test.ts` | fast-check invariants for the unsupported-model fallback: any returned fallback is a chain member, never the current or an attempted model (under any prefix/suffix/casing spelling), legacy gpt-5.3 edge toggle respected, exhausted chains give up | | [#575](https://github.com/ndycode/codex-multi-auth/pull/575) | `test/property/settings-write-queue.property.test.ts` | fast-check invariants for the write queue: per-key invocations stay contiguous and in submission order under any ok/flaky/fatal schedule, fatal tasks never block successors, 429 retry-after hints clamp into 10ms..30s | +| [#576](https://github.com/ndycode/codex-multi-auth/pull/576) | `lib/AGENTS.md` | closes audit L3: documents the class vs module-state convention (classes for multi-instance/injectable state and the error hierarchy; module-level state only for process-global concerns, always with a test reset helper) | +| [#577](https://github.com/ndycode/codex-multi-auth/pull/577) | `.codex-plugin/plugin.json`, `docs/README.md`, `AGENTS.md`, `test/documentation.test.ts` | live-regression fix found by a full-suite canary vs the §7 baseline: the 2.3.0-beta.2 bump left three stale beta.1 references (plugin manifest, docs-portal release table, AGENTS.md header); adds a doc-integrity guard pinning the AGENTS.md version to package.json | --- From 31b0891e68eeae42740c06ffcc5cd81028ddebd0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:03:52 +0000 Subject: [PATCH 08/23] =?UTF-8?q?docs:=20scope=20=C2=A75.2=20prose=20to=20?= =?UTF-8?q?test=20PRs,=20name=20#576/#577=20as=20non-test=20rows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit's description check flagged that the intro characterised every table row as a unit-test suite while #576 is a convention doc and #577 a version-drift fix; the prose now says so explicitly. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index f36a9761..38c84e02 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -184,8 +184,11 @@ health-check, and persistence helpers reachable only through the giant CLI suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. -Every PR below is independent and based on `main`; each mocks only the -effectful seams and runs the real identity-matching / retry / parsing logic. +Every PR below is independent and based on `main`. The test PRs +(#559–#575) each mock only the effectful seams and run the real +identity-matching / retry / parsing logic; the final two rows are +non-test follow-ups from the same wave — the L3 convention doc (#576) +and a version-drift fix the wave's full-suite canary caught (#577). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs.) From eb4553690c336515b69f4205528d764831615e3e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:10:28 +0000 Subject: [PATCH 09/23] =?UTF-8?q?docs:=20note=20that=20the=20=C2=A75.2=20s?= =?UTF-8?q?equence=20also=20skips=20#568=20(this=20PR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 38c84e02..219b2eed 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -190,7 +190,8 @@ identity-matching / retry / parsing logic; the final two rows are non-test follow-ups from the same wave — the L3 convention doc (#576) and a version-drift fix the wave's full-suite canary caught (#577). (The number sequence skips #558 and #562, which are issues — the knip CI -tracking issue and a maintainer MCP-auth test — not PRs.) +tracking issue and a maintainer MCP-auth test — not PRs; it also skips +#568, which is the PR delivering this very section.) | PR | Suite | Pins | |----|-------|------| From 6a859cda1cb91c321db929956e23ac5573f6951a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:11:35 +0000 Subject: [PATCH 10/23] =?UTF-8?q?docs:=20add=20the=20#578=20dead-code=20sw?= =?UTF-8?q?eep=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 219b2eed..ee3a988a 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -186,9 +186,10 @@ earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs (#559–#575) each mock only the effectful seams and run the real -identity-matching / retry / parsing logic; the final two rows are -non-test follow-ups from the same wave — the L3 convention doc (#576) -and a version-drift fix the wave's full-suite canary caught (#577). +identity-matching / retry / parsing logic; the final three rows are +non-test follow-ups from the same wave — the L3 convention doc (#576), +a version-drift fix the wave's full-suite canary caught (#577), and a +dead-code sweep the coverage scan surfaced (#578). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -212,6 +213,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#575](https://github.com/ndycode/codex-multi-auth/pull/575) | `test/property/settings-write-queue.property.test.ts` | fast-check invariants for the write queue: per-key invocations stay contiguous and in submission order under any ok/flaky/fatal schedule, fatal tasks never block successors, 429 retry-after hints clamp into 10ms..30s | | [#576](https://github.com/ndycode/codex-multi-auth/pull/576) | `lib/AGENTS.md` | closes audit L3: documents the class vs module-state convention (classes for multi-instance/injectable state and the error hierarchy; module-level state only for process-global concerns, always with a test reset helper) | | [#577](https://github.com/ndycode/codex-multi-auth/pull/577) | `.codex-plugin/plugin.json`, `docs/README.md`, `AGENTS.md`, `test/documentation.test.ts` | live-regression fix found by a full-suite canary vs the §7 baseline: the 2.3.0-beta.2 bump left three stale beta.1 references (plugin manifest, docs-portal release table, AGENTS.md header); adds a doc-integrity guard pinning the AGENTS.md version to package.json | +| [#578](https://github.com/ndycode/codex-multi-auth/pull/578) | five deleted modules + `lib/AGENTS.md` | dead-code sweep surfaced while verifying coverage convergence: removes 768 LOC of orphaned modules with zero importers repo-wide, incl. a 625-line forecast/report monolith superseded by `commands/forecast.ts`/`commands/report.ts` that was still being patched in parallel (#502, #506) | --- From cb3010a2263be57f2f0121ae6ab3efb4212132b2 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:24:51 +0000 Subject: [PATCH 11/23] =?UTF-8?q?docs:=20add=20the=20#579=20dedup-idempote?= =?UTF-8?q?nce=20fix=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index ee3a988a..76c075cd 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -186,10 +186,11 @@ earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs (#559–#575) each mock only the effectful seams and run the real -identity-matching / retry / parsing logic; the final three rows are -non-test follow-ups from the same wave — the L3 convention doc (#576), -a version-drift fix the wave's full-suite canary caught (#577), and a -dead-code sweep the coverage scan surfaced (#578). +identity-matching / retry / parsing logic; the final four rows are +follow-ups from the same wave — the L3 convention doc (#576), a +version-drift fix the wave's full-suite canary caught (#577), a +dead-code sweep the coverage scan surfaced (#578), and a dedup +idempotence fix found by a new identity property suite (#579). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -214,6 +215,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#576](https://github.com/ndycode/codex-multi-auth/pull/576) | `lib/AGENTS.md` | closes audit L3: documents the class vs module-state convention (classes for multi-instance/injectable state and the error hierarchy; module-level state only for process-global concerns, always with a test reset helper) | | [#577](https://github.com/ndycode/codex-multi-auth/pull/577) | `.codex-plugin/plugin.json`, `docs/README.md`, `AGENTS.md`, `test/documentation.test.ts` | live-regression fix found by a full-suite canary vs the §7 baseline: the 2.3.0-beta.2 bump left three stale beta.1 references (plugin manifest, docs-portal release table, AGENTS.md header); adds a doc-integrity guard pinning the AGENTS.md version to package.json | | [#578](https://github.com/ndycode/codex-multi-auth/pull/578) | five deleted modules + `lib/AGENTS.md` | dead-code sweep surfaced while verifying coverage convergence: removes 768 LOC of orphaned modules with zero importers repo-wide, incl. a 625-line forecast/report monolith superseded by `commands/forecast.ts`/`commands/report.ts` that was still being patched in parallel (#502, #506) | +| [#579](https://github.com/ndycode/codex-multi-auth/pull/579) | `lib/storage.ts` + `test/property/account-identity.property.test.ts` | third live bug found by the coverage method: fast-check proved `deduplicateAccounts` non-idempotent (a newest-wins merge in one matching tier can install an account that duplicates an earlier survivor through another tier); fixed with a fixpoint loop, pinned by 9 identity-matching properties incl. a deterministic counterexample replay | --- From 3bcb8cec38cacb43564a8176247f3daf98256d31 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:29:44 +0000 Subject: [PATCH 12/23] =?UTF-8?q?docs:=20add=20#580=20and=20#581=20to=20th?= =?UTF-8?q?e=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 76c075cd..81f3143d 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -185,12 +185,13 @@ suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs -(#559–#575) each mock only the effectful seams and run the real -identity-matching / retry / parsing logic; the final four rows are +(#559–#575, plus #580) each mock only the effectful seams and run the +real identity-matching / retry / parsing logic; the remaining rows are follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a -dead-code sweep the coverage scan surfaced (#578), and a dedup -idempotence fix found by a new identity property suite (#579). +dead-code sweep the coverage scan surfaced (#578), a dedup idempotence +fix found by a new identity property suite (#579), and an unused +devDependency removal (#581). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -216,6 +217,8 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#577](https://github.com/ndycode/codex-multi-auth/pull/577) | `.codex-plugin/plugin.json`, `docs/README.md`, `AGENTS.md`, `test/documentation.test.ts` | live-regression fix found by a full-suite canary vs the §7 baseline: the 2.3.0-beta.2 bump left three stale beta.1 references (plugin manifest, docs-portal release table, AGENTS.md header); adds a doc-integrity guard pinning the AGENTS.md version to package.json | | [#578](https://github.com/ndycode/codex-multi-auth/pull/578) | five deleted modules + `lib/AGENTS.md` | dead-code sweep surfaced while verifying coverage convergence: removes 768 LOC of orphaned modules with zero importers repo-wide, incl. a 625-line forecast/report monolith superseded by `commands/forecast.ts`/`commands/report.ts` that was still being patched in parallel (#502, #506) | | [#579](https://github.com/ndycode/codex-multi-auth/pull/579) | `lib/storage.ts` + `test/property/account-identity.property.test.ts` | third live bug found by the coverage method: fast-check proved `deduplicateAccounts` non-idempotent (a newest-wins merge in one matching tier can install an account that duplicates an earlier survivor through another tier); fixed with a fixpoint loop, pinned by 9 identity-matching properties incl. a deterministic counterexample replay | +| [#580](https://github.com/ndycode/codex-multi-auth/pull/580) | `test/account-rate-limits.test.ts` | the extracted per-account rate-limit helpers, previously reachable only via the `accounts.ts` facade: reason-code taxonomy incl. the generic-429 unknown bucket, family vs model-scoped quota keys, expiry-boundary semantics (`now >= reset` clears), model-key precedence, and the expired-entry pruning side effect | +| [#581](https://github.com/ndycode/codex-multi-auth/pull/581) | `package.json` | drops the unused `@fast-check/vitest` devDependency (the property suites deliberately use plain `fast-check`, so the `test.prop` wrapper has no consumers) | --- From b26a100e32ea7e268b24d1f55a1af6e3168ebedb Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:36:13 +0000 Subject: [PATCH 13/23] =?UTF-8?q?docs:=20add=20#582=20usage-redaction=20su?= =?UTF-8?q?ite=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 81f3143d..ef8502fa 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -185,7 +185,7 @@ suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs -(#559–#575, plus #580) each mock only the effectful seams and run the +(#559–#575, plus #580 and #582) each mock only the effectful seams and run the real identity-matching / retry / parsing logic; the remaining rows are follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a @@ -219,6 +219,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#579](https://github.com/ndycode/codex-multi-auth/pull/579) | `lib/storage.ts` + `test/property/account-identity.property.test.ts` | third live bug found by the coverage method: fast-check proved `deduplicateAccounts` non-idempotent (a newest-wins merge in one matching tier can install an account that duplicates an earlier survivor through another tier); fixed with a fixpoint loop, pinned by 9 identity-matching properties incl. a deterministic counterexample replay | | [#580](https://github.com/ndycode/codex-multi-auth/pull/580) | `test/account-rate-limits.test.ts` | the extracted per-account rate-limit helpers, previously reachable only via the `accounts.ts` facade: reason-code taxonomy incl. the generic-429 unknown bucket, family vs model-scoped quota keys, expiry-boundary semantics (`now >= reset` clears), model-key precedence, and the expired-entry pruning side effect | | [#581](https://github.com/ndycode/codex-multi-auth/pull/581) | `package.json` | drops the unused `@fast-check/vitest` devDependency (the property suites deliberately use plain `fast-check`, so the `test.prop` wrapper has no consumers) | +| [#582](https://github.com/ndycode/codex-multi-auth/pull/582) | `test/usage-redaction.test.ts` | the usage-ledger redaction/normalization contracts (previously reachable only via the `usage/index.js` facade): identifier hashing, account refs storing only hashes, the unknown-outcome -> `failure` fallback (never miscounted as success), token clamping/total recompute, the 100..599 status window, cost fallback to the pricing estimate, and the serialized JSONL line never containing raw account id or email | --- From f6406d7fbaa4ba19ba1766ba7793ece41c4cedf4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:43:25 +0000 Subject: [PATCH 14/23] =?UTF-8?q?docs:=20add=20#583=20settings-preview=20s?= =?UTF-8?q?uite=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index ef8502fa..6b1128f0 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -185,7 +185,7 @@ suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs -(#559–#575, plus #580 and #582) each mock only the effectful seams and run the +(#559–#575, plus #580, #582, and #583) each mock only the effectful seams and run the real identity-matching / retry / parsing logic; the remaining rows are follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a @@ -220,6 +220,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#580](https://github.com/ndycode/codex-multi-auth/pull/580) | `test/account-rate-limits.test.ts` | the extracted per-account rate-limit helpers, previously reachable only via the `accounts.ts` facade: reason-code taxonomy incl. the generic-429 unknown bucket, family vs model-scoped quota keys, expiry-boundary semantics (`now >= reset` clears), model-key precedence, and the expired-entry pruning side effect | | [#581](https://github.com/ndycode/codex-multi-auth/pull/581) | `package.json` | drops the unused `@fast-check/vitest` devDependency (the property suites deliberately use plain `fast-check`, so the `test.prop` wrapper has no consumers) | | [#582](https://github.com/ndycode/codex-multi-auth/pull/582) | `test/usage-redaction.test.ts` | the usage-ledger redaction/normalization contracts (previously reachable only via the `usage/index.js` facade): identifier hashing, account refs storing only hashes, the unknown-outcome -> `failure` fallback (never miscounted as success), token clamping/total recompute, the 100..599 status window, cost fallback to the pricing estimate, and the serialized JSONL line never containing raw account id or email | +| [#583](https://github.com/ndycode/codex-multi-auth/pull/583) | `test/settings-preview.test.ts` | the preview-first settings renderer (previously reachable only via the interactive settings-hub panels), using the real `resolveMenuLayoutMode`: statusline-field normalization incl. the defensive copy, summary composition with the inverted status-badge dependency and both nothing-visible explanations, badge toggles, and TTY-gated ANSI highlighting asserted by stripped equality | --- From 9b540aaafdf8b64d7359e1e2e001657b8f0e1b35 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:46:30 +0000 Subject: [PATCH 15/23] docs: record #578 as closed and folded into the pre-existing #554 https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 6b1128f0..c0facc7c 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -189,7 +189,8 @@ Every PR below is independent and based on `main`. The test PRs real identity-matching / retry / parsing logic; the remaining rows are follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a -dead-code sweep the coverage scan surfaced (#578), a dedup idempotence +dead-code sweep the coverage scan surfaced (#578, later folded into the +pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), and an unused devDependency removal (#581). (The number sequence skips #558 and #562, which are issues — the knip CI @@ -215,7 +216,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#575](https://github.com/ndycode/codex-multi-auth/pull/575) | `test/property/settings-write-queue.property.test.ts` | fast-check invariants for the write queue: per-key invocations stay contiguous and in submission order under any ok/flaky/fatal schedule, fatal tasks never block successors, 429 retry-after hints clamp into 10ms..30s | | [#576](https://github.com/ndycode/codex-multi-auth/pull/576) | `lib/AGENTS.md` | closes audit L3: documents the class vs module-state convention (classes for multi-instance/injectable state and the error hierarchy; module-level state only for process-global concerns, always with a test reset helper) | | [#577](https://github.com/ndycode/codex-multi-auth/pull/577) | `.codex-plugin/plugin.json`, `docs/README.md`, `AGENTS.md`, `test/documentation.test.ts` | live-regression fix found by a full-suite canary vs the §7 baseline: the 2.3.0-beta.2 bump left three stale beta.1 references (plugin manifest, docs-portal release table, AGENTS.md header); adds a doc-integrity guard pinning the AGENTS.md version to package.json | -| [#578](https://github.com/ndycode/codex-multi-auth/pull/578) | five deleted modules + `lib/AGENTS.md` | dead-code sweep surfaced while verifying coverage convergence: removes 768 LOC of orphaned modules with zero importers repo-wide, incl. a 625-line forecast/report monolith superseded by `commands/forecast.ts`/`commands/report.ts` that was still being patched in parallel (#502, #506) | +| [#578](https://github.com/ndycode/codex-multi-auth/pull/578) (closed, superseded by [#554](https://github.com/ndycode/codex-multi-auth/pull/554)) | five deleted modules + `lib/AGENTS.md` | dead-code sweep surfaced while verifying coverage convergence; an open-PR sweep then showed #554 already deletes the same five files plus two more (`recovery/index.ts`, `storage/restore.ts`) that this PR's reference search had false-matched as live — #578 was closed and its unique `lib/AGENTS.md` fix moved onto #554 | | [#579](https://github.com/ndycode/codex-multi-auth/pull/579) | `lib/storage.ts` + `test/property/account-identity.property.test.ts` | third live bug found by the coverage method: fast-check proved `deduplicateAccounts` non-idempotent (a newest-wins merge in one matching tier can install an account that duplicates an earlier survivor through another tier); fixed with a fixpoint loop, pinned by 9 identity-matching properties incl. a deterministic counterexample replay | | [#580](https://github.com/ndycode/codex-multi-auth/pull/580) | `test/account-rate-limits.test.ts` | the extracted per-account rate-limit helpers, previously reachable only via the `accounts.ts` facade: reason-code taxonomy incl. the generic-429 unknown bucket, family vs model-scoped quota keys, expiry-boundary semantics (`now >= reset` clears), model-key precedence, and the expired-entry pruning side effect | | [#581](https://github.com/ndycode/codex-multi-auth/pull/581) | `package.json` | drops the unused `@fast-check/vitest` devDependency (the property suites deliberately use plain `fast-check`, so the `test.prop` wrapper has no consumers) | From ec61cb2328e59db469c82c26145ad5e5a0f959c0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 19:51:40 +0000 Subject: [PATCH 16/23] =?UTF-8?q?docs:=20add=20#584=20settings-hub=20share?= =?UTF-8?q?d=20suite=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index c0facc7c..03bd67fe 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -185,7 +185,7 @@ suites. Writing direct suites for extracted modules surfaced real bugs twice earlier in this cycle (the `isRecord` guard fixed in #544 and the stream-stall fix in #546), so the method was applied across the remaining gaps. Every PR below is independent and based on `main`. The test PRs -(#559–#575, plus #580, #582, and #583) each mock only the effectful seams and run the +(#559–#575, plus #580 and #582–#584) each mock only the effectful seams and run the real identity-matching / retry / parsing logic; the remaining rows are follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a @@ -222,6 +222,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#581](https://github.com/ndycode/codex-multi-auth/pull/581) | `package.json` | drops the unused `@fast-check/vitest` devDependency (the property suites deliberately use plain `fast-check`, so the `test.prop` wrapper has no consumers) | | [#582](https://github.com/ndycode/codex-multi-auth/pull/582) | `test/usage-redaction.test.ts` | the usage-ledger redaction/normalization contracts (previously reachable only via the `usage/index.js` facade): identifier hashing, account refs storing only hashes, the unknown-outcome -> `failure` fallback (never miscounted as success), token clamping/total recompute, the 100..599 status window, cost fallback to the pricing estimate, and the serialized JSONL line never containing raw account id or email | | [#583](https://github.com/ndycode/codex-multi-auth/pull/583) | `test/settings-preview.test.ts` | the preview-first settings renderer (previously reachable only via the interactive settings-hub panels), using the real `resolveMenuLayoutMode`: statusline-field normalization incl. the defensive copy, summary composition with the inverted status-badge dependency and both nothing-visible explanations, badge toggles, and TTY-gated ANSI highlighting asserted by stripped equality | +| [#584](https://github.com/ndycode/codex-multi-auth/pull/584) | `test/settings-hub-shared.test.ts` | the settings-hub merge/persist layer (only the disk seams mocked; real queued-retry policy): array-clone copy semantics, key-scoped defaults/merge, the load-merge-save transaction preserving concurrent edits to unrelated keys, EBUSY retry without warning, warn + clone-normalized fallback on persistent failure, backend patch save with defensive clone, and `clampBackendNumber` | --- From 0bd0581abbab25fd24b907797610cbe817859841 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:35:28 +0000 Subject: [PATCH 17/23] docs: record #585 (retry consolidation closing batch) in the delivery log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also updates M7's status cell now that §4.2 is fully executed. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 03bd67fe..9bd485c4 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -53,7 +53,7 @@ The remaining structural debt — the three god-files and the test-mock monolith | M4 | Pre-commit hook used deprecated husky v9 bootstrap (hard failure in v10) and ran lint only — type errors reached CI undetected locally | `.husky/pre-commit` | Fixed in PR #521 | | M5 | `codex-multi-auth workspace` (issue #491) shipped undocumented in `docs/reference/commands.md` | `lib/codex-manager/commands/workspace.ts` | Fixed in PR #520 (incl. doc-integrity test) | | M6 | `AGENTS.md` claimed package version 2.2.0 vs actual 2.3.0-beta.1; `docs/README.md` duplicated 11 release rows inside the Reference table | `AGENTS.md:6`, `docs/README.md:101-112` | Fixed in PR #520 | -| M7 | Retry-with-backoff logic re-implemented with divergent semantics (attempt counts 4/5/6, different retryable-code sets, sleep vs no-sleep) across `lib/config.ts:57-86`, `lib/fs-retry.ts:28-40`, `lib/storage.ts` (BACKUP_COPY loops), `lib/quota-cache.ts:260`, `lib/recovery/storage.ts:188` | multiple | Roadmap §4.2 | +| M7 | Retry-with-backoff logic re-implemented with divergent semantics (attempt counts 4/5/6, different retryable-code sets, sleep vs no-sleep) across `lib/config.ts:57-86`, `lib/fs-retry.ts:28-40`, `lib/storage.ts` (BACKUP_COPY loops), `lib/quota-cache.ts:260`, `lib/recovery/storage.ts:188` | multiple | Roadmap §4.2 — first batch landed earlier in the cycle (`withRetry`/`withRetrySync` in `lib/fs-retry.ts` + config/quota-cache/recovery/uninstall call sites); closing batch in PR #585 (storage rename + config ESTALE CAS) | | M8 | `config/schema/config.schema.json` documents 3 fields; `lib/schemas.ts` `PluginConfigSchema` defines 75+ — IDE autocomplete and external validation see almost none of the config surface | `config/schema/config.schema.json` vs `lib/schemas.ts:30-83` | Roadmap §4.5 | | M9 | `@types/node ^25` against `engines >=18.17` — a **present** type-safety gap, not just polish: new code calling a Node 20+-only API (e.g. `fs.glob`) typechecks cleanly today but fails at runtime for Node 18.17 consumers | `package.json:159` | Open — needs a maintainer decision now (pin `@types/node` to `^20`, or raise engines and document the break); mechanics in §4.5 | | M10 | Shipping both `sourceMap` and `declarationMap` to npm: 532 `.map` files ≈ 1.9 MB (~39% of unpacked size) for a CLI-first package | `tsconfig.json:20-21` | Roadmap §4.5 | @@ -191,8 +191,9 @@ follow-ups from the same wave — the L3 convention doc (#576), a version-drift fix the wave's full-suite canary caught (#577), a dead-code sweep the coverage scan surfaced (#578, later folded into the pre-existing #554), a dedup idempotence -fix found by a new identity property suite (#579), and an unused -devDependency removal (#581). +fix found by a new identity property suite (#579), an unused +devDependency removal (#581), and the closing batch of the §4.2 retry +consolidation (#585). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -223,6 +224,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#582](https://github.com/ndycode/codex-multi-auth/pull/582) | `test/usage-redaction.test.ts` | the usage-ledger redaction/normalization contracts (previously reachable only via the `usage/index.js` facade): identifier hashing, account refs storing only hashes, the unknown-outcome -> `failure` fallback (never miscounted as success), token clamping/total recompute, the 100..599 status window, cost fallback to the pricing estimate, and the serialized JSONL line never containing raw account id or email | | [#583](https://github.com/ndycode/codex-multi-auth/pull/583) | `test/settings-preview.test.ts` | the preview-first settings renderer (previously reachable only via the interactive settings-hub panels), using the real `resolveMenuLayoutMode`: statusline-field normalization incl. the defensive copy, summary composition with the inverted status-badge dependency and both nothing-visible explanations, badge toggles, and TTY-gated ANSI highlighting asserted by stripped equality | | [#584](https://github.com/ndycode/codex-multi-auth/pull/584) | `test/settings-hub-shared.test.ts` | the settings-hub merge/persist layer (only the disk seams mocked; real queued-retry policy): array-clone copy semantics, key-scoped defaults/merge, the load-merge-save transaction preserving concurrent edits to unrelated keys, EBUSY retry without warning, warn + clone-normalized fallback on persistent failure, backend patch save with defensive clone, and `clampBackendNumber` | +| [#585](https://github.com/ndycode/codex-multi-auth/pull/585) | `lib/storage.ts`, `lib/config.ts` + storage rename-retry tests | closes the §4.2 retry consolidation (M7): migrates the last two hand-rolled loops — the temp→final rename (EPERM/EBUSY, 5 attempts, 10ms-doubling) and the config-save ESTALE mtime CAS (3 attempts, re-read/re-merge per try) — onto `withRetry`, with new tests pinning the rename policy through the real `saveAccounts` path | --- From d3a9ed4aa362b30aa8d1ab0e9b7a15b0e3ca5ec7 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:42:22 +0000 Subject: [PATCH 18/23] =?UTF-8?q?docs:=20add=20the=20#586=20typed-error=20?= =?UTF-8?q?slice=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 9bd485c4..459a0342 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -192,8 +192,8 @@ version-drift fix the wave's full-suite canary caught (#577), a dead-code sweep the coverage scan surfaced (#578, later folded into the pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), an unused -devDependency removal (#581), and the closing batch of the §4.2 retry -consolidation (#585). +devDependency removal (#581), the closing batch of the §4.2 retry +consolidation (#585), and the first §4.3 typed-error slice (#586). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -225,6 +225,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#583](https://github.com/ndycode/codex-multi-auth/pull/583) | `test/settings-preview.test.ts` | the preview-first settings renderer (previously reachable only via the interactive settings-hub panels), using the real `resolveMenuLayoutMode`: statusline-field normalization incl. the defensive copy, summary composition with the inverted status-badge dependency and both nothing-visible explanations, badge toggles, and TTY-gated ANSI highlighting asserted by stripped equality | | [#584](https://github.com/ndycode/codex-multi-auth/pull/584) | `test/settings-hub-shared.test.ts` | the settings-hub merge/persist layer (only the disk seams mocked; real queued-retry policy): array-clone copy semantics, key-scoped defaults/merge, the load-merge-save transaction preserving concurrent edits to unrelated keys, EBUSY retry without warning, warn + clone-normalized fallback on persistent failure, backend patch save with defensive clone, and `clampBackendNumber` | | [#585](https://github.com/ndycode/codex-multi-auth/pull/585) | `lib/storage.ts`, `lib/config.ts` + storage rename-retry tests | closes the §4.2 retry consolidation (M7): migrates the last two hand-rolled loops — the temp→final rename (EPERM/EBUSY, 5 attempts, 10ms-doubling) and the config-save ESTALE mtime CAS (3 attempts, re-read/re-merge per try) — onto `withRetry`, with new tests pinning the rename policy through the real `saveAccounts` path | +| [#586](https://github.com/ndycode/codex-multi-auth/pull/586) | `lib/runtime-rotation-proxy.ts`, `docs/reference/error-contracts.md` + proxy guard test | first §4.3 slice (M11): the rotation-proxy startup guards (loopback-only host refusal, missing clientApiKey) throw `CodexValidationError` with field/expected/context metadata, messages unchanged; adds the Typed Error Classes section to the error-contract reference (config.ts's three bare throws follow once #585 merges) | --- From 757c62a5cb03a6641f728d87252defb08a56c853 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:49:32 +0000 Subject: [PATCH 19/23] =?UTF-8?q?docs:=20add=20the=20#587=20config=20typed?= =?UTF-8?q?-error=20slice=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 459a0342..0c155839 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -193,7 +193,7 @@ dead-code sweep the coverage scan surfaced (#578, later folded into the pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), an unused devDependency removal (#581), the closing batch of the §4.2 retry -consolidation (#585), and the first §4.3 typed-error slice (#586). +consolidation (#585), and the two §4.3 typed-error slices (#586, #587). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -225,7 +225,8 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#583](https://github.com/ndycode/codex-multi-auth/pull/583) | `test/settings-preview.test.ts` | the preview-first settings renderer (previously reachable only via the interactive settings-hub panels), using the real `resolveMenuLayoutMode`: statusline-field normalization incl. the defensive copy, summary composition with the inverted status-badge dependency and both nothing-visible explanations, badge toggles, and TTY-gated ANSI highlighting asserted by stripped equality | | [#584](https://github.com/ndycode/codex-multi-auth/pull/584) | `test/settings-hub-shared.test.ts` | the settings-hub merge/persist layer (only the disk seams mocked; real queued-retry policy): array-clone copy semantics, key-scoped defaults/merge, the load-merge-save transaction preserving concurrent edits to unrelated keys, EBUSY retry without warning, warn + clone-normalized fallback on persistent failure, backend patch save with defensive clone, and `clampBackendNumber` | | [#585](https://github.com/ndycode/codex-multi-auth/pull/585) | `lib/storage.ts`, `lib/config.ts` + storage rename-retry tests | closes the §4.2 retry consolidation (M7): migrates the last two hand-rolled loops — the temp→final rename (EPERM/EBUSY, 5 attempts, 10ms-doubling) and the config-save ESTALE mtime CAS (3 attempts, re-read/re-merge per try) — onto `withRetry`, with new tests pinning the rename policy through the real `saveAccounts` path | -| [#586](https://github.com/ndycode/codex-multi-auth/pull/586) | `lib/runtime-rotation-proxy.ts`, `docs/reference/error-contracts.md` + proxy guard test | first §4.3 slice (M11): the rotation-proxy startup guards (loopback-only host refusal, missing clientApiKey) throw `CodexValidationError` with field/expected/context metadata, messages unchanged; adds the Typed Error Classes section to the error-contract reference (config.ts's three bare throws follow once #585 merges) | +| [#586](https://github.com/ndycode/codex-multi-auth/pull/586) | `lib/runtime-rotation-proxy.ts`, `docs/reference/error-contracts.md` + proxy guard test | first §4.3 slice (M11): the rotation-proxy startup guards (loopback-only host refusal, missing clientApiKey) throw `CodexValidationError` with field/expected/context metadata, messages unchanged; adds the Typed Error Classes section to the error-contract reference | +| [#587](https://github.com/ndycode/codex-multi-auth/pull/587) | `lib/config.ts` + config-save typed-abort test | second §4.3 slice (M11), unblocked by #585: the three unreadable-config save aborts in `savePluginConfig` throw `StorageError` (UNREADABLE code, config path, actionable hint, classifier cause) with byte-identical messages; with #586 this clears every bare throw from the files §4.3 names | --- From 71a8f7ad60ab1e22354fcef784090e15a2860f13 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:53:07 +0000 Subject: [PATCH 20/23] docs: record M11's execution (#586/#587) in the findings table https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 0c155839..f9edcaf6 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -57,7 +57,7 @@ The remaining structural debt — the three god-files and the test-mock monolith | M8 | `config/schema/config.schema.json` documents 3 fields; `lib/schemas.ts` `PluginConfigSchema` defines 75+ — IDE autocomplete and external validation see almost none of the config surface | `config/schema/config.schema.json` vs `lib/schemas.ts:30-83` | Roadmap §4.5 | | M9 | `@types/node ^25` against `engines >=18.17` — a **present** type-safety gap, not just polish: new code calling a Node 20+-only API (e.g. `fs.glob`) typechecks cleanly today but fails at runtime for Node 18.17 consumers | `package.json:159` | Open — needs a maintainer decision now (pin `@types/node` to `^20`, or raise engines and document the break); mechanics in §4.5 | | M10 | Shipping both `sourceMap` and `declarationMap` to npm: 532 `.map` files ≈ 1.9 MB (~39% of unpacked size) for a CLI-first package | `tsconfig.json:20-21` | Roadmap §4.5 | -| M11 | `lib/errors.ts` defines a clean `CodexError` hierarchy but only a handful of modules throw it; `runtime-rotation-proxy.ts` and `config.ts` mostly throw/log bare `Error`/strings, so callers cannot distinguish auth from network failures programmatically | `lib/errors.ts` (214 lines), few importers | Roadmap §4.3 | +| M11 | `lib/errors.ts` defines a clean `CodexError` hierarchy but only a handful of modules throw it; `runtime-rotation-proxy.ts` and `config.ts` mostly throw/log bare `Error`/strings, so callers cannot distinguish auth from network failures programmatically | `lib/errors.ts` (214 lines), few importers | Roadmap §4.3 — executed in PR #586 (rotation-proxy startup guards → `CodexValidationError` + error-contract doc section) and PR #587 (config-save unreadable aborts → `StorageError`); the earlier §4.1 extractions had already removed the other bare throws | | M12 | `test/codex-manager-cli.test.ts` carries 40+ module-level `vi.fn()` mocks (~12k LOC test file) — refactoring any mocked interface ripples through the whole file; no snapshot coverage for `--help`/`--json` output | `test/codex-manager-cli.test.ts` | Roadmap §4.4 | | M13 | `ci.yml` and `pr-ci.yml` duplicate typecheck/lint/coverage/build/audit step lists (143 + 112 lines) — drift hazard | `.github/workflows/` | Roadmap §4.4 | From 17c363ac2c005575516616fa8e91b2a2c25736fe Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:54:27 +0000 Subject: [PATCH 21/23] =?UTF-8?q?docs:=20add=20the=20#588=20test=20knowled?= =?UTF-8?q?ge-base=20refresh=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index f9edcaf6..c170ec92 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -193,7 +193,8 @@ dead-code sweep the coverage scan surfaced (#578, later folded into the pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), an unused devDependency removal (#581), the closing batch of the §4.2 retry -consolidation (#585), and the two §4.3 typed-error slices (#586, #587). +consolidation (#585), the two §4.3 typed-error slices (#586, #587), and +a test knowledge-base refresh (#588). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -227,6 +228,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#585](https://github.com/ndycode/codex-multi-auth/pull/585) | `lib/storage.ts`, `lib/config.ts` + storage rename-retry tests | closes the §4.2 retry consolidation (M7): migrates the last two hand-rolled loops — the temp→final rename (EPERM/EBUSY, 5 attempts, 10ms-doubling) and the config-save ESTALE mtime CAS (3 attempts, re-read/re-merge per try) — onto `withRetry`, with new tests pinning the rename policy through the real `saveAccounts` path | | [#586](https://github.com/ndycode/codex-multi-auth/pull/586) | `lib/runtime-rotation-proxy.ts`, `docs/reference/error-contracts.md` + proxy guard test | first §4.3 slice (M11): the rotation-proxy startup guards (loopback-only host refusal, missing clientApiKey) throw `CodexValidationError` with field/expected/context metadata, messages unchanged; adds the Typed Error Classes section to the error-contract reference | | [#587](https://github.com/ndycode/codex-multi-auth/pull/587) | `lib/config.ts` + config-save typed-abort test | second §4.3 slice (M11), unblocked by #585: the three unreadable-config save aborts in `savePluginConfig` throw `StorageError` (UNREADABLE code, config path, actionable hint, classifier cause) with byte-identical messages; with #586 this clears every bare throw from the files §4.3 names | +| [#588](https://github.com/ndycode/codex-multi-auth/pull/588) | `test/AGENTS.md`, `test/README.md` | refreshes the test knowledge bases the wave left stale: headline counts corrected (3847/257 and 2071/87 → the actual 4909 tests / 317 files) and the curated trees gain the wave's load-bearing new suites plus the three fast-check property suites | --- From fab67aa2d4aa4456d3905bc8c1ca6cb1481d3ba6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 07:57:44 +0000 Subject: [PATCH 22/23] =?UTF-8?q?docs:=20add=20the=20#589=20lib=20knowledg?= =?UTF-8?q?e-base=20refresh=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index c170ec92..71eecbed 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -194,7 +194,7 @@ pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), an unused devDependency removal (#581), the closing batch of the §4.2 retry consolidation (#585), the two §4.3 typed-error slices (#586, #587), and -a test knowledge-base refresh (#588). +the knowledge-base refreshes (#588 for test/, #589 for lib/). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -229,6 +229,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#586](https://github.com/ndycode/codex-multi-auth/pull/586) | `lib/runtime-rotation-proxy.ts`, `docs/reference/error-contracts.md` + proxy guard test | first §4.3 slice (M11): the rotation-proxy startup guards (loopback-only host refusal, missing clientApiKey) throw `CodexValidationError` with field/expected/context metadata, messages unchanged; adds the Typed Error Classes section to the error-contract reference | | [#587](https://github.com/ndycode/codex-multi-auth/pull/587) | `lib/config.ts` + config-save typed-abort test | second §4.3 slice (M11), unblocked by #585: the three unreadable-config save aborts in `savePluginConfig` throw `StorageError` (UNREADABLE code, config path, actionable hint, classifier cause) with byte-identical messages; with #586 this clears every bare throw from the files §4.3 names | | [#588](https://github.com/ndycode/codex-multi-auth/pull/588) | `test/AGENTS.md`, `test/README.md` | refreshes the test knowledge bases the wave left stale: headline counts corrected (3847/257 and 2071/87 → the actual 4909 tests / 317 files) and the curated trees gain the wave's load-bearing new suites plus the three fast-check property suites | +| [#589](https://github.com/ndycode/codex-multi-auth/pull/589) | `lib/AGENTS.md` | companion refresh for the lib knowledge base: the STRUCTURE tree gains the extraction-era clusters (`codex-manager/formatters/`, `request/helpers/` + decision/failover modules, `runtime/rotation-*`, `policy/`, `fs-retry`, `temp-path`, `budget-guard`, `local-bridge`) and WHERE TO LOOK points at the shared retry and temp-path helpers | --- From 0a6b2e974f35f09f88099cd9cd0d5dbe5692d6f9 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 08:02:15 +0000 Subject: [PATCH 23/23] =?UTF-8?q?docs:=20add=20the=20#590=20spy-cascade=20?= =?UTF-8?q?isolation=20fix=20to=20the=20=C2=A75.2=20delivery=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB --- docs/audits/AUDIT_2026-06-10.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/audits/AUDIT_2026-06-10.md b/docs/audits/AUDIT_2026-06-10.md index 71eecbed..d4413ec5 100644 --- a/docs/audits/AUDIT_2026-06-10.md +++ b/docs/audits/AUDIT_2026-06-10.md @@ -194,7 +194,8 @@ pre-existing #554), a dedup idempotence fix found by a new identity property suite (#579), an unused devDependency removal (#581), the closing batch of the §4.2 retry consolidation (#585), the two §4.3 typed-error slices (#586, #587), and -the knowledge-base refreshes (#588 for test/, #589 for lib/). +the knowledge-base refreshes (#588 for test/, #589 for lib/), and a +spy-cascade isolation fix in the storage suite (#590). (The number sequence skips #558 and #562, which are issues — the knip CI tracking issue and a maintainer MCP-auth test — not PRs; it also skips #568, which is the PR delivering this very section.) @@ -230,6 +231,7 @@ tracking issue and a maintainer MCP-auth test — not PRs; it also skips | [#587](https://github.com/ndycode/codex-multi-auth/pull/587) | `lib/config.ts` + config-save typed-abort test | second §4.3 slice (M11), unblocked by #585: the three unreadable-config save aborts in `savePluginConfig` throw `StorageError` (UNREADABLE code, config path, actionable hint, classifier cause) with byte-identical messages; with #586 this clears every bare throw from the files §4.3 names | | [#588](https://github.com/ndycode/codex-multi-auth/pull/588) | `test/AGENTS.md`, `test/README.md` | refreshes the test knowledge bases the wave left stale: headline counts corrected (3847/257 and 2071/87 → the actual 4909 tests / 317 files) and the curated trees gain the wave's load-bearing new suites plus the three fast-check property suites | | [#589](https://github.com/ndycode/codex-multi-auth/pull/589) | `lib/AGENTS.md` | companion refresh for the lib knowledge base: the STRUCTURE tree gains the extraction-era clusters (`codex-manager/formatters/`, `request/helpers/` + decision/failover modules, `runtime/rotation-*`, `policy/`, `fs-retry`, `temp-path`, `budget-guard`, `local-bridge`) and WHERE TO LOOK points at the shared retry and temp-path helpers | +| [#590](https://github.com/ndycode/codex-multi-auth/pull/590) | `test/storage.test.ts` | isolation hardening for a contamination class found while writing #585's tests: a test failing before its inline `mockRestore()` leaks its fs spy, and a later `vi.spyOn` returns the same leaked spy so passthrough bindings recurse into the new test's own mock; the suite's top-level afterEach now calls `vi.restoreAllMocks()` | ---