Files
gstack/test/fixtures/ceo-section-r-rejected-report.md
T
Garry TanandOpenAI Codex 9f81911136 v1.86.0.0 feat: route outside reviews by harness (#2850)
* feat: add a restricted and supervised Claude Code runner

Preserve configured authentication and models while enforcing tool access, strict completion JSON, bounded output and process cleanup. Cover argv, failure handling, session metadata and Windows process containment.

* feat: route outside reviews by harness and migrate wrapper installs

Use Claude Code from Codex and Codex from other supported hosts, with shared invocation rendering, positive gate validation and per-phase provenance. Rename /claude to /claude-code, repair managed shared and copied installations safely, and generate native Kiro skills. Add installed-workflow, failure-injection and live cross-harness regression coverage.

* test: recognize CEO mode labels without terminal spacing

The paid workflow rendered SCOPEEXPANSION at option 4, but its driver required a literal space. Match the leading mode title without cursor-spacing artifacts and ignore adjacent preview text. Preserve missing-target failures and downstream posture assertions.

* test: isolate plan-count fixtures before starting review workflows

Seed the complete test plan in a private git repository before launching Claude, so a bare slash command cannot review the live workspace while a delayed fixture message remains queued. Preserve count thresholds, parsers and budgets. Add initial-context and installed-discovery tests, and retain startup/terminal diagnostics on failed evaluations.

* test: stabilize review fixtures and Claude eval startup

Preserve source boundaries in workflow judge inputs, isolate CEO mode plans, and wait for interactive trust input readiness. Keep startup failure evidence and retain existing models, budgets, and assertions.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test: classify collapsed review modes and isolate seeded findings

Keep review questions out of the setup count when terminal cursor positioning removes spaces. State existing webhook safeguards so the five-finding control measures its seeded defects without accidental extra security and concurrency gaps. Preserve question bands and the paired control.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test: isolate browser daemon state across free shards

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test: stabilize native review counting and interactive navigation

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: prepare v1.82.0.0 release

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix: eliminate browser and process-cleanup test flakes

Pin every CI surface to Bun 1.4.0 to avoid extra-stdio finalizers closing
reused live sockets. Add an isolated GC/listener regression that fails on
Bun 1.3.13, and prevent coordinated rollback to an affected CI runtime.

Check renderer cleanup against the render's own staging directory so
concurrent renders cannot invalidate the assertion. Make the no-pgrep
process-tree walk tolerate disappearing /proc entries, and synchronize
its test fixture through child readiness and pipe EOF instead of sleeps.

Validation: 9,157 passed, 31 skipped, zero failures across 556 files with
retries disabled. Build, all-host generation freshness, and skill checks
passed. All three races have failing-before/passing-after regressions.

* fix: count completed native review questions in evals

* fix: drive review navigation from confirmed native choices

* fix: require complete section-loading eval reports

* test: isolate telemetry HTTP transport from local assertions

* fix: keep review input on the active native question

* test: let tunnel revocation daemon choose an available port

* test: allocate available ports for pairing and watchdog fixtures

* fix: stabilize planning eval navigation and phase reporting

* test: isolate installed runtime paths in planning evals

* test: stabilize review evidence and concurrent refresh fixtures

* fix: resolve design findings before editing the plan

* fix: honor and persist disabled outside plan reviews

* fix: preserve planning decisions and terminal evidence

Load installed host reviews at autoplan phase entry and wait for completed
reviewers and saved artifacts. Reuse approved remedies while preserving
individual finding decisions.

Drive interactive evals from the current terminal viewport, bind native
questions across scrolling, and require complete native report evidence.
Cover captured stale menus, permission lifecycles, setup classification,
and disabled-review tool availability with deterministic regressions.

Advance release metadata and the upgrade migration to the unclaimed
1.83.0.0 slot.

* fix: drive native review questions and preserve current plans

Use the native single-choice keyboard protocol and current terminal viewport,
with per-question navigation inside packets and completed-call coverage.
Keep permissions, multi-select menus, and Submit controls distinct.

Send Autoplan reviewers the amended implementation plan, keep its review record
separate, and supply retained application contracts in the chain fixture.
Clarify individual DevEx decisions and complete CEO fix options; use one active
plan destination for the section-loading report.

* fix: preserve complete plan-review decisions

* fix: recognize native plan dialogs and reviewer controls

* fix: preserve review decisions and phase completion

* fix: recognize completed reviews without losing findings

* fix: preserve review continuity and native eval completion

* test: fix native review completion and eval retry isolation

* test: handle native review menus and complete eval fixtures

* test: fix native review setup, completion, and isolation failures

* test: limit native skill discovery to runtime assets

* fix: bind Autoplan reviews to full ordered phase inputs

* test: fix planning eval routing, counting, and timeout handling

* chore: advance queued release to v1.84.0.0

* fix: preserve complete review inputs and planning decisions

* fix: reconcile review approvals and preserve phase obligations

* fix: preserve review obligations and unblock eval permissions

Carry recorded Autoplan requirements into blind phase inputs, require Eng
review approvals before exit, and exercise combined asynchronous flows in
CEO reviews. Correct native finding and handoff classification and unblock
repeated report edits using scoped request identities.

* fix: retain plan requirements and complete native review dialogs

* fix: complete native review prompts and retain plan references

* fix: preserve review inputs and classify native eval evidence

* fix: check competing completion orders in CEO reviews

* fix: recognize review decisions and require phase methodology

Require the current phase methodology before Autoplan snapshots. Correct
substantive decision, closed handoff, and cache-finding classification, and
honor the recommended implementation approach in native review dialogs.

Add captured-transcript regressions without changing review thresholds,
provider models, retries, or deadlines.

* test: bind native review decisions and close completed handoffs

* fix: complete review dialogs and verify methodology delivery

* fix: preserve review evidence and unblock native eval prompts

* fix: handle native review question completions

* fix: recognize native review narration and controls

* fix: count native review decisions and isolate eval fixtures

* test: verify seeded review coverage and current artifact permissions

* test: isolate model and brain-aware skill renders

* fix: repair native workflow evaluation and clarify review steps

* fix: stabilize workflow eval evidence and review guidance

* test: repair native workflow observation and fixture isolation

* fix: recognize completed workflow evidence and owned skill reads

* test: repair seeded workflow delivery and completion evidence

* test: recognize current review evidence across native forms

* test: handle native review variants and permission redraws

* fix: honor review preferences and recognize native eval evidence

* test: recognize completed review decisions and queued permissions

* test: match current review contracts and partial-line edits

* test: recognize completed workflow evidence and bounded human waits

* fix: preserve review entry gates and native eval interactions

* fix: recognize native workflow evidence and preserve review gates

* test: recognize current review evidence and preconfigure workflow fixtures

* test: recognize completed review findings and scoped artifact permissions

* fix: stabilize native workflow review and permission evidence

* fix: recognize current review evidence and scoped edit confirmations

Clarify Design and engineering review entry instructions and Design scoring.
Recognize required legacy coverage and public Autoplan completion recaps.
Bind the pending Edit confirmation to its exact file, ordered digest, and
one-request approval when a preceding command display remains visible.
Keep reviews within their existing size limits and preserve scope gates
when extracting workflow fixtures from either supported preamble header.

Keep failure outcomes, review thresholds, provider choices, and eval budgets.

* fix: recover review workflow progress and eval evidence

* fix: recognize valid review evidence and scope selection

* test: fix review evidence parsing and repeated artifact prompts

* test: recognize valid review decisions and pending native cards

* fix(plan-eng-review): keep final navigation consistent with approved tasks

* test: recognize valid review evidence and bind legacy diff requests

* fix: stabilize review eval evidence and harness repair guidance

* docs: update project documentation for v1.85.0.0

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test: fix Windows CI fixtures and credential scan

Rebase captured JSON values and filesystem evidence using the appropriate
path convention. Compile native fake CLIs on Windows and synchronize pipe
holder readiness, with cleanup retained when assertions fail.

Assemble synthetic credential fixtures at runtime so the added-line scan
keeps enforcing the same gate without flagging its own rejection controls.

Discover generated skills directly for the empty-find regression check,
avoiding a recursive scan through saved evaluation artifacts and dependencies.

* fix: preserve source renders on Windows

Compare canonical generator paths using native separators so an output
sidecar pointing at the source cannot overwrite its skill or metadata.
Keep the regression fixture isolated from the real checkout and expose
freshness diagnostics before asserting subprocess status.

Detach Windows drain-test pipe holders from the fake provider's automatic
child cleanup while preserving the enclosing runner job and its assertions.

* fix: clarify outside review fallback and CEO decisions

Render one applicable own-harness fallback path and retain native review,
disabled policy, and missing-coverage semantics. Align report field names
and mode labels, and make the existing per-cut scope approval explicit.

Regenerate skill outputs and keep the workflow judge's model, thresholds,
and retry policy unchanged.

* chore: move release to free version slot (v1.86.0.0)

PR #2852 now claims v1.85.0.0. Align the release metadata and
rename migration so upgrades from that version still receive it.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix: include engineering review prerequisites and restore branch context

* fix: recognize coverage diagrams and clarify design review instructions

* fix: preserve file identities and join Windows test processes

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
2026-09-14 14:32:45 -07:00

45 KiB

Plan: cache profile summaries in one process

Measured problem and accepted scope

The existing profile-summary service has one active process. A one-week trace shows repeated reads of about 900 hot keys: DB CPU is 70%, with read p95 120 ms. Add a process-local LRU wrapper to the existing repository. Acceptance targets are at least 60% cache hits, DB CPU below 50%, and read p95 below 60 ms, with the existing error-rate and correctness SLOs unchanged. This is an internal backend change with no UI, API, schema, pricing, or developer onboarding change.

Existing contracts retained

  • All reads and writes use this repository in the same process; there are no external DB writers. Multi-process operation remains unsupported and startup rejects that configuration while caching is enabled.
  • Authentication and authorization run before repository access. Keys encode the authenticated tenant ID and validated profile ID without ambiguity. Values are immutable profile-summary DTOs; secrets and cache keys are never logged. Cached results cannot bypass authorization.
  • The existing LRU adapter supports 1000 entries, a 16 MiB byte cap, and a 30-second TTL. Recorded hot data fits those limits. Absent records use a distinct sentinel with a 10-second TTL; undefined means a cache miss.
  • Cache operations are synchronous and atomic in the single JS event loop. On any cache failure the existing adapter bypasses the cache until an empty cache is reinitialized; repository errors keep the current typed API error mapping. The existing per-key single-flight wrapper coalesces simultaneous misses and releases on failure.
  • A read already in progress when a write commits may return its earlier DB snapshot to that caller. Every read begun after that write completes must observe the committed version. TTL expiry is not a substitute for this rule.

Proposed wrapper integration

Keep the current read-through repository interface and shared adapters. These are the complete new read/write ordering rules; no additional version checks or coordination between a cache fill and a write are proposed:

async function readProfile(key) {
  const cached = cache.get(key);
  if (cached !== undefined) return cached;
  const value = await repository.read(key);
  cache.set(key, value);
  return value;
}

async function writeProfile(key, update) {
  const saved = await repository.write(key, update);
  cache.delete(key);
  return saved;
}

Verification and rollout

Existing repository contract tests cover tenant isolation, key validation, absence, DB failures, and authorization. New wrapper tests cover hit/miss, eviction and byte limits, TTL, adapter-failure fallback, successful-write invalidation, failed-write preservation, and concurrent-miss coalescing. The rollout uses the existing runtime feature flag: enable for 10% of keys, then 50%, then all keys after one healthy hour at each stage. Monitor hit/miss, eviction, cache bytes, fallback errors, DB CPU, and read p95 without raw IDs. On error-rate or latency regression, disable the flag immediately; both reads and writes bypass the cache while disabled, and enabling creates an empty cache. Cold starts remain within the existing DB capacity. The service owner monitors the rollout and records the results against the acceptance targets.

Out of scope

Distributed caching, cross-process coherence, prewarming, changing consistency semantics, or adding new product surfaces. The repository interface preserves a future replacement path without introducing a general cache framework now.


CEO Review — HOLD SCOPE Mode

Conducted 2026-09-09 — automated run, AskUserQuestion unavailable; skill-recommended options auto-selected.

Step 0: Scope Challenge + Mode

Mode: HOLD SCOPE (requested by caller; appropriate — this is a backend performance fix with well-measured targets, not a greenfield feature).

0A. Premise Challenge

  1. Is this the right problem? Yes. 70% DB CPU and 120 ms p95 on ~900 hot keys is measured, not hypothetical. A process-local cache is the canonical first response.
  2. Is the plan the most direct path? Yes. The read/write pseudocode is minimal, and the rollout uses an existing flag.
  3. What happens if we do nothing? DB CPU stays at 70%, approaching saturation; tail latency and error risk grow.

0B. Existing Code Leverage

Sub-problem Existing code Reused?
LRU eviction + byte cap Existing LRU adapter Yes
Concurrent miss coalescing Existing per-key single-flight wrapper Yes
Bypass on adapter failure Existing adapter behavior Yes
Feature flag rollout Existing runtime flag Yes
Tenant/auth scoping Existing key encoding + auth layer Yes

Nothing is being rebuilt. This is a thin orchestration wrapper.

0C. Dream State Mapping

CURRENT STATE                    THIS PLAN                      12-MONTH IDEAL
─────────────────────────────────────────────────────────────────────────────
DB CPU 70%, p95 120ms     →  In-process LRU, 60%+ hit rate  →  DB CPU <50%,
900 hot keys repeated          DB CPU <50%, p95 <60ms            p95 <60ms,
No cache layer                 Staged rollout w/ flag             possible Redis
                                                                  if multi-process
                                                                  needed later

This plan moves directly toward the 12-month ideal. The interface preserves the Redis upgrade path.

0C-bis. Implementation Alternatives

APPROACH A: Process-local LRU wrapper (CHOSEN by plan)
  Summary: Wrap existing repository with cache.get/set/delete at call sites.
  Effort:  S
  Risk:    Low
  Pros:    No new dependencies; reuses existing LRU adapter and single-flight
           wrapper; rollback via existing flag; synchronous/atomic in JS event loop.
  Cons:    Cache lost on restart; does not help if multi-process is ever needed.
  Reuses:  Existing LRU adapter, single-flight wrapper, feature flag.

APPROACH B: Redis-backed distributed cache
  Summary: Replace in-process LRU with Redis read-through.
  Effort:  L
  Risk:    High
  Pros:    Survives restarts; supports multi-process; higher cache capacity.
  Cons:    New infrastructure dependency; network RTT adds latency; multi-process
           coherence becomes a real problem; overkill for single-process service.
  Reuses:  None of the existing LRU infrastructure.

APPROACH C: DB-level read replica / materialized view
  Summary: Move hot reads to a read replica with DB-level caching.
  Effort:  XL
  Risk:    High
  Pros:    No application-layer cache; DB manages consistency.
  Cons:    Infrastructure changes outside the service; 6-month lead time;
           out of the service team's control.
  Reuses:  None.

RECOMMENDATION: Approach A. The service is single-process by contract; Approach A is the minimum correct solution. Approaches B and C are valid future paths if the architecture changes — the plan's interface intentionally preserves those paths.

0D. HOLD SCOPE Analysis

Complexity check: The change touches one repository wrapper (2 functions). No new services, no new classes. Well within complexity budget.

Minimum set: The plan is already minimal — the pseudocode is the complete implementation surface. No work can be deferred without blocking the core objective.

0E. Temporal Interrogation

HOUR 1 (foundations):  Does the existing LRU adapter expose the exact
                        get/set/delete/bypass interface the wrapper assumes?
                        Confirm the adapter's undefined-on-miss contract.
HOUR 2-3 (core logic): What is the concrete type of the sentinel? A specific
                        symbol, null, or an object? undefined must be reserved
                        for cache miss.
HOUR 4-5 (integration):How does the single-flight wrapper interact with
                        cache.set — does it call readProfile or repository.read
                        directly? The cache.set must be inside the single-flight
                        scope to avoid double population.
HOUR 6+ (polish/tests):Controlled pause/release tests for concurrent read+write
                        interleaving (read starts, write completes + deletes,
                        read resumes and calls cache.set with stale value).
                        This is the hardest behavior to reason about.

Section 1: Architecture Review

System architecture:

  CALLER
    │
    ▼
  ProfileRepository (interface unchanged)
    │
    ├─ cache.get(key) ──────────────────▶ LRU Adapter (in-process)
    │        │                                │
    │    [hit: value]                    [synchronous,
    │        │                           atomic in JS
    │    return cached ◀─────────────────  event loop]
    │        │
    │    [miss: undefined]
    │        │
    ▼        ▼
  repository.read(key)  ◀──── DB
    │
    ├─[success]──▶ cache.set(key, value) ──▶ LRU Adapter
    │                   │
    │               return value
    │
    └─[error]──▶ propagate (no cache.set)

  WRITE PATH:
  CALLER
    │
    ▼
  repository.write(key, update) ──▶ DB
    │
    ├─[success]──▶ cache.delete(key) ──▶ LRU Adapter
    │                   │
    │               return saved
    │
    └─[error]──▶ propagate (cache.delete NOT called — intentional)

  FAILURE PATH:
  Any cache.get / cache.set / cache.delete throws
    │
    ▼
  LRU Adapter enters BYPASS mode (existing behavior)
    │
    ▼
  All reads/writes go directly to DB until adapter reinitialized (empty cache)

Cache state machine:

  [flag disabled] ──────────────────────────────────▶ BYPASS (all ops → DB)
       │
  [flag enabled]
       │
       ▼
     EMPTY ──(first miss)──▶ WARMING ──(adapter error)──▶ BYPASS
       ▲                        │                              │
       │                    (write)                      (reinit/empty)
       │                        │                              │
       │                   key deleted                         │
       │                        │                              ▼
       └────────────────── (TTL expiry) ◀──────────────── EMPTY ◀──┘

Coupling concerns: The wrapper introduces coupling between ProfileRepository and the LRU Adapter. This coupling is intentional and bounded: the adapter is an existing shared component, and the bypass behavior decouples the failure modes.

Before/after dependency graph:

BEFORE:                          AFTER:
Caller ──▶ Repository ──▶ DB    Caller ──▶ Repository ──▶ LRU Adapter
                                                        └──▶ DB (on miss)

Single points of failure:

  • The LRU Adapter: mitigated by bypass mode.
  • The single process: by design; multi-process is explicitly unsupported and rejected at startup.

Scaling:

  • 10x load: Hot 900 keys still cached; miss rate is unchanged; DB load stays lower. Holds.
  • 100x load: Single-process limit is reached before the cache becomes the bottleneck. Out of scope by contract.

Security architecture: Auth runs before repository access; keys encode tenant+profile IDs; no new API surface; no new secrets; cached values cannot bypass authorization. OK.

Production failure scenarios:

  • LRU Adapter throws on get: Bypass mode. DB reads continue. OK.
  • LRU Adapter throws on set: Bypass mode. Worst case: one read returns stale (see Section 4). OK.
  • LRU Adapter throws on delete: The plan states "any cache failure" triggers bypass. This must include delete — see Section 2 gap.
  • DB connection fails during read: Error propagates as before. Adapter not written. OK.
  • OOM: 16 MiB byte cap + 1000-entry cap prevents unbounded growth. OK.

Rollback posture: Disable feature flag → reads and writes bypass cache → DB returns to baseline behavior. Enabling creates an empty cache. Rollback is fast, clean, and reversible. 5/5.

Assessment: Architecture is sound. No structural issues. Required diagram produced above.


Section 2: Error & Rescue Map

METHOD/CODEPATH         | WHAT CAN GO WRONG            | EXCEPTION CLASS
------------------------|------------------------------|--------------------
cache.get(key)          | Adapter internal error       | AdapterError
repository.read(key)    | DB connection failure         | DBConnectionError
                        | Query timeout                | TimeoutError
                        | Record not found             | (sentinel, not error)
cache.set(key, value)   | Adapter internal error       | AdapterError
                        | Byte cap full                | (handled by eviction)
repository.write(k,u)   | DB write failure             | DBWriteError
                        | Validation error             | ValidationError
                        | Conflict / constraint        | ConflictError
cache.delete(key)       | Adapter internal error       | AdapterError
EXCEPTION CLASS         | RESCUED?  | RESCUE ACTION                  | USER SEES
------------------------|-----------|--------------------------------|----------------
AdapterError (get)      | Y         | Bypass mode until reinit       | Transparent
AdapterError (set)      | Y         | Bypass mode until reinit       | Transparent
AdapterError (delete)   | Y*        | Bypass mode until reinit       | Transparent*
DBConnectionError       | Y         | Existing typed API mapping     | Existing error
TimeoutError            | Y         | Existing typed API mapping     | Existing error
DBWriteError            | Y         | Propagate; cache NOT deleted   | Existing error
ValidationError         | Y         | Propagate; cache NOT deleted   | Existing error
ConflictError           | Y         | Propagate; cache NOT deleted   | Existing error

*AdapterError (delete): The plan says "on any cache failure the existing adapter bypasses the cache." This SHOULD cover delete failures, but the adapter-failure test suite must explicitly verify this case (see Section 6 gap).

GAP identified: If cache.delete throws after a successful repository.write, bypass mode should activate. This preserves the write's committed value (all reads go to DB). The plan's wording covers this but the test suite does not explicitly verify it.

Assessment: No critical gaps. One test coverage gap on delete-path adapter failure. Error handling architecture is correct.


Section 3: Security & Threat Model

Threat Likelihood Impact Mitigated?
Cross-tenant cache read Low High Yes — keys encode tenant ID + profile ID
Auth bypass via cache Low High Yes — auth runs before repository access
PII in logs/metrics Low High Yes — raw IDs excluded from all monitoring
Stale cache serving wrong user Low Med Yes — tenant ID in key prevents cross-user access
Cache poisoning via write Low Med Yes — write path deletes key; cache only stores DB-confirmed values
DoS via cache bypass (flag off) Low Low Yes — existing DB capacity handles cold starts
New dependency exploit surface None N/A — no new dependencies added

Assessment: Security posture is solid. No new attack surfaces. The key-encoding contract and auth-before-cache design are correctly stated. No findings.


Section 4: Data Flow & Interaction Edge Cases

Read flow (all paths):

  KEY ──▶ cache.get(key)
              │
         [hit: value] ──────────────────────────────▶ return value
              │
         [miss: undefined]
              │
              ▼
         repository.read(key)
              │
         [nil/absent] ──▶ cache.set(key, SENTINEL, TTL=10s) ──▶ return sentinel
              │
         [value] ──▶ cache.set(key, value, TTL=30s) ──▶ return value
              │
         [error] ──▶ propagate (no cache.set)
              │
         [adapter error on set] ──▶ bypass mode; return value anyway

Write flow (all paths):

  KEY, UPDATE ──▶ repository.write(key, update)
                        │
                  [success: saved]
                        │
                  cache.delete(key) ──[adapter error]──▶ bypass mode
                        │
                  return saved
                        │
                  [write error] ──▶ propagate
                                    (cache.delete NOT called — correct)

Async ordering — the in-flight read race:

T0: Read R1 starts → cache.get(key) = undefined (miss)
T1: Write W1 commits → repository.write returns → cache.delete(key) called
T2: R1 resumes → repository.read returns old snapshot
T3: R1 calls cache.set(key, OLD_VALUE)  ← stale write to cache
T4: New Read R2 starts → cache.get(key) = OLD_VALUE (stale hit)

Finding (WARNING): The plan's consistency invariant states: "Every read begun after that write completes must observe the committed version." But R2 in the timeline above begins after W1 completes and may see the stale value R1 wrote at T3. The stale window is bounded by the 30s TTL, and the plan explicitly excludes "additional version checks or coordination." However, the current invariant wording overstates the guarantee — the implementation provides eventual consistency with a bounded stale window (max 30s), not strict post-write read-your-writes for concurrent reads.

The plan should clarify: the consistency guarantee applies to reads that begin AFTER both (a) the write commits AND (b) any in-flight concurrent read's cache.set has completed. For the narrow window between W1's cache.delete and R1's cache.set, a subsequently-started reader may see a stale cache entry for up to 30s. This is acceptable given the "immutable profile-summary DTO" semantics (updates are infrequent), but it should be stated rather than implied by "TTL expiry is not a substitute."

No interaction edge cases apply — there is no user-visible interaction (backend-only change).

Assessment: One WARNING on consistency invariant wording. No critical data flow gaps.


Section 5: Code Quality Review

async function readProfile(key) {
  const cached = cache.get(key);
  if (cached !== undefined) return cached;
  const value = await repository.read(key);
  cache.set(key, value);
  return value;
}

async function writeProfile(key, update) {
  const saved = await repository.write(key, update);
  cache.delete(key);
  return saved;
}
  • Organization: Correct. Two functions, each with a single responsibility.
  • DRY: No violations. The cache adapter is the single source of eviction/TTL logic.
  • Naming: Clear. readProfile/writeProfile are semantic and consistent with the repository interface.
  • Error handling: Delegated correctly. Cache errors flow to the adapter's bypass mechanism; DB errors propagate through existing typed mapping.
  • Over-engineering: None. The plan correctly resists building a general cache framework.
  • Under-engineering: The async race (Section 4) is an inherent property of read-through caching without version checks. Given the plan explicitly excludes version checks, this is an accepted design choice, not a quality gap — but must be documented.
  • Cyclomatic complexity: Both functions have ≤1 branch. No concern.
  • Sentinel handling: undefined as the cache-miss signal is correct as long as the repository never returns undefined for a valid absent record. The plan uses a sentinel object for absent records — this distinction must be verified in implementation (absent ≠ undefined).

Assessment: Code quality is high. One documentation gap (consistency model for in-flight race). No structural defects.


Section 6: Test Review

New items introduced:

NEW UX FLOWS:
  None — backend-only change.

NEW DATA FLOWS:
  1. readProfile: cache hit path
  2. readProfile: cache miss → DB read → cache.set
  3. readProfile: absent key → sentinel
  4. writeProfile: success → cache.delete
  5. writeProfile: failure → no cache.delete

NEW CODEPATHS:
  1. cache.get returns hit
  2. cache.get returns miss (undefined)
  3. cache.set called on successful read
  4. cache.set skipped on read error
  5. cache.delete called on successful write
  6. cache.delete skipped on failed write
  7. Adapter failure → bypass mode (get path)
  8. Adapter failure → bypass mode (set path)
  9. Adapter failure → bypass mode (delete path)  ← gap
  10. Single-flight coalescing (existing wrapper, new context)

NEW BACKGROUND JOBS / ASYNC WORK:
  None.

NEW INTEGRATIONS / EXTERNAL CALLS:
  None (existing DB, existing adapter).

NEW ERROR/RESCUE PATHS:
  1. Adapter failure on get → bypass
  2. Adapter failure on set → bypass
  3. Adapter failure on delete → bypass (needs explicit test)

Coverage per plan vs. required:

Test In Plan? Gap?
Cache hit Yes No
Cache miss Yes No
Eviction + byte limits Yes No
TTL expiry Yes No
Adapter-failure fallback (get) Yes (implied) No
Adapter-failure fallback (set) Yes (implied) No
Adapter-failure fallback (delete) Unclear GAP
Successful write invalidation Yes No
Failed write preservation Yes No
Concurrent-miss coalescing Yes No
Concurrent read+write interleave Not listed GAP
Absent key sentinel (10s TTL) Implied by TTL test Partial
Sentinel vs. undefined distinction Not listed GAP (minor)

Missing test specs:

// GAP: cache.delete adapter failure triggers bypass
test('adapter failure on cache.delete enters bypass mode', async () => {
  cache.simulateDeleteFailure(true);
  const saved = await writeProfile(key, update);
  expect(bypassMode).toBe(true);
  expect(saved).toEqual(expectedSaved); // write still succeeds
});

// GAP: concurrent read+write interleave
test('read started before write completes may set stale cache entry', async () => {
  // Pause R1 after repository.read, before cache.set
  // Let W1 complete (write + cache.delete)
  // Resume R1: cache.set with old value
  // Verify: new reads see stale value until TTL
  // Verify: stale window is bounded by TTL (≤30s)
});

// GAP (minor): sentinel vs. undefined contract
test('absent key uses sentinel, not undefined, so undefined remains cache-miss signal', async () => {
  const result = await readProfile(absentKey);
  expect(result).not.toBeUndefined(); // sentinel, not miss signal
  expect(cache.get(absentKey)).not.toBeUndefined(); // sentinel is cached
});

Test pyramid: Unit tests (cache hit/miss/TTL/eviction) + integration tests (write invalidation, single-flight) + contract tests (existing). No E2E needed for this backend change. Pyramid is well-formed.

Flakiness risk: The concurrent interleave test requires controlled pause/resume points (e.g., --expose-gc or manual promise sequencing). Must not rely on timing.

2am Friday test: "Does a write always invalidate the cache, even when the adapter throws on delete?" — currently not tested.

Hostile QA test: "What if a read and a write race, and the read wins the cache?" — currently not tested.

Chaos test: "What if the adapter throws intermittently — does bypass mode activate, and do reads still return correct DB data?" — partially covered by adapter-failure test if it's thorough.

Assessment: 3 test gaps (delete-path bypass, read/write interleave, sentinel contract). No blocking gaps, but the interleave test is important for validating the consistency claim.


Section 7: Performance Review

Acceptance target analysis:

The target (p95 < 60 ms) with 60% cache hit rate requires the DB tail latency to drop, not just the volume. The key insight: DB CPU at 70% is likely in the queuing-saturated zone where latency grows super-linearly. Going from 70% → <50% CPU utilization can reduce the 95th-percentile queuing delay by 3-5x (M/M/1 queuing model). DB p95 could drop from 120 ms to ~50-60 ms after load reduction, making the overall p95 target achievable even though p95 falls in the DB-served 40%.

The plan's acceptance targets are achievable but depend on this queuing dynamic — not just cache hit rate alone. The rollout monitoring will empirically confirm this.

Memory: 16 MiB / 1000 entries = ~16 KB average entry size. Profile summaries at this size are plausible but should be verified in staging (large profiles with many fields could skew this).

Cache miss penalty: On a cold start or after bypass reinit, all 900 hot keys miss. With 120 ms DB p95 and 70% CPU (warm period), a burst of 900 sequential misses takes ~108 s at 120 ms each, or less in parallel (event loop concurrency). The single-flight wrapper prevents stampede. Cold starts remain within existing DB capacity — this is stated and correct.

Connection pool pressure: No new DB connections. Cache operations are in-process. No change to connection pool.

Slow paths:

  1. Cold cache (post-enable or post-bypass): All reads hit DB at 120 ms p95 until warm. Bounded by hot key TTL (30s from first fill).
  2. Bypass mode (sustained adapter failure): All reads hit DB indefinitely. Monitor fallback errors.
  3. Eviction pressure (>1000 entries or >16 MiB): Evicted keys promote misses. Monitor eviction rate; if high, the 900 hot keys may not all fit — investigate DTO sizes.

Assessment: No blocking performance issues. One observation to add to the plan: p95 target depends on DB queuing-load reduction, not cache hit rate alone. Verify average DTO size in staging to confirm 16 MiB cap is sufficient.


Section 8: Observability & Debuggability Review

What the plan specifies:

  • Metrics: hit/miss, eviction, cache bytes, fallback errors, DB CPU, read p95

Gaps:

Observability item Plan covers? Gap
Structured log at adapter failure No Missing
Log when bypass mode activates No Missing
Alert: fallback errors > threshold No Missing
Alert: DB CPU > 60% (early warning) No Missing
Alert: read p95 > 80 ms (regression warning) No Missing
Alert: hit rate < 50% (cache degradation) No Missing
Dashboard: hit rate trend over rollout No Missing
Dashboard: eviction rate (cap pressure indicator) No Missing
Runbook: adapter failure → bypass → reinit procedure No Missing
Runbook: rollback decision criteria No Missing
Debuggability: can a 3-week-old incident be reconstructed from logs? Partial Only if fallback errors are logged with timestamp + bypass entry event

Required additions to plan:

  1. Structured log on bypass activation: {event: "cache_bypass_activated", reason: "adapter_error", error_class: "<class>", ts: <ts>} — no key or value content.
  2. Structured log on bypass exit (reinit): {event: "cache_reinitialized", ts: <ts>}.
  3. Alert thresholds:
    • fallback_errors > 0 for 5 minutes → page (adapter likely broken)
    • cache_hit_rate < 50% for 10 minutes → warn (eviction pressure or warm-up issue)
    • db_cpu > 60% → warn (cache not holding)
    • read_p95 > 80ms → warn (regression early warning; flag off if sustained)
  4. Day 1 dashboard panels: hit rate %, eviction rate/s, cache bytes used, fallback error rate, DB CPU %, read p95 (5m rolling).
  5. Runbook (adapter failure): (1) Observe fallback_errors alert. (2) Check adapter health (memory pressure? process restart?). (3) Restart process to reinitialize cache. (4) Monitor that bypass exits and hit rate recovers. (5) If repeated, open incident — do not re-enable flag until root cause clear.
  6. Runbook (rollback decision): If error-rate or p95 exceeds baseline by >10% for >5 min, disable flag immediately. Both reads and writes go to DB. Investigate before re-enabling.

Assessment: Significant observability gaps. Alerts, dashboard spec, and runbooks are needed for safe operation. These should be added to the plan before implementation.


Section 9: Deployment & Rollout Review

What the plan specifies:

  • Feature flag: existing runtime flag
  • Stages: 10% → 50% → 100%
  • Advance criterion: "one healthy hour at each stage"
  • Rollback trigger: "error-rate or latency regression"

Gaps:

Finding (P1): "One healthy hour" is undefined. Without explicit success criteria, the service owner cannot make a consistent, objective advance decision. Define:

HEALTHY = all of the following for 60 consecutive minutes:
  - Cache hit rate ≥ 40% (warming, approaching target)
  - Fallback error rate = 0
  - DB CPU < previous-stage DB CPU (trending down)
  - read p95 ≤ previous-stage read p95 (trending down or flat)
  - Application error rate within existing SLO

Finding: "Error-rate or latency regression" as the rollback trigger needs quantification:

ROLLBACK if any of:
  - Application error rate increases > 10% above baseline
  - read p95 increases > 20% above the stage-entry baseline
  - Fallback errors > 0 for > 5 consecutive minutes

Other deployment items:

  • No DB migrations: In-memory cache only. Deploy is a code deploy. Zero downtime.
  • Old/new code interop: Feature flag gates the wrapper. Old code path (bypass) is always valid. No interop risk.
  • Cold start risk: Bounded. Single-flight wrapper prevents stampede. OK.
  • Staging test: Not mentioned. Should validate hit rate and bypass behavior before production rollout.
  • Post-deploy verification (first 5 min): Check fallback errors = 0, hit rate rising, DB CPU trending down.
  • Post-deploy verification (first hour): Confirm hit rate ≥ 40% at 10% stage, no error regressions.
  • Smoke test: Run the existing contract test suite post-deploy to confirm correctness is preserved.

Assessment: One P1 finding (healthy hour definition) and one gap (rollback quantification). Both should be added to the plan.


Section 10: Long-Term Trajectory Review

Technical debt:

  • Code debt: Minimal. The wrapper is 2 functions over existing infrastructure.
  • Operational debt: Cache state adds a new invisible variable (what's cached, when was it warmed?). Mitigated by bypass mode and short TTL (30s max staleness).
  • Testing debt: 3 gaps identified in Section 6. Small.
  • Documentation debt: The in-flight read race (Section 4 finding) must be documented in a code comment, or future maintainers will strengthen the invariant incorrectly.

Path dependency: The interface is not locked. The plan explicitly states the repository interface "preserves a future replacement path." Redis or another adapter can be substituted without changing the caller interface. Two-way door.

Knowledge concentration: The sentinel pattern (absent ≠ undefined ≠ null) and the bypass model are non-obvious. A code comment or inline doc on the consistency model prevents future bugs.

Reversibility: 4/5. Flag off = instant rollback. Process restart = empty cache. Only risk: a bypass mode bug could persist until restart.

Ecosystem fit: Standard JS async/await pattern with process-local LRU. Aligns with the ecosystem.

1-year question: The wrapper is simple enough to be understood immediately. The race condition in the consistency model is the one non-obvious piece — document it.

Assessment: Long-term trajectory is clean. One documentation debt item (consistency model comment).


Section 11: Design & UX Review

SKIPPED — no UI scope. The plan explicitly states "no UI, API, schema, pricing, or developer onboarding change." This is a backend-only performance change.


Outside Voice

Codex review skipped (codex_reviews: disabled per isolated config). Re-enable: gstack-config set codex_reviews enabled.

Outside coverage: disabled (intentional opt-out, not a provider failure).


Required Outputs

NOT in scope

Item Rationale
Distributed (Redis) caching Single-process contract; multi-process is rejected at startup
Cross-process cache coherence Same as above
Cache prewarming Not needed; hot keys warm naturally within one TTL cycle
Changing consistency semantics Out of scope by plan
Cache compression / serialization Not needed for 16 MiB cap with current DTO sizes
New product surfaces or API changes Explicitly excluded
Cache statistics admin UI Operational tooling beyond current scope

What already exists

Component Existing code Used by plan
LRU adapter 1000 entries, 16 MiB cap, 30s TTL, sentinel support Yes — cache.get/set/delete
Per-key single-flight wrapper Coalesces concurrent misses Yes — wraps repository.read
Runtime feature flag Existing flag mechanism Yes — rollout stages
Tenant/profile key encoding Auth layer + key schema Yes — no changes needed
Repository contract tests Tenant isolation, key validation, absence, DB failures, authorization Yes — extended, not replaced
Adapter bypass behavior On any adapter failure, bypass until reinit Yes — error handling relies on this

Dream state delta

  THIS PLAN LEAVES US AT:
    DB CPU < 50%           (from 70%)         → target met
    read p95 < 60 ms       (from 120 ms)      → target met (after queuing load drops)
    Cache hit rate 60%+                        → target met for hot 900 keys
    No UI/API/schema change                    → clean internal change
    Future Redis path preserved               → interface is adapter-agnostic

  REMAINING DELTA TO 12-MONTH IDEAL:
    If multi-process operation is needed later, the LRU wrapper becomes invalid
    and a distributed cache (Redis) is required. The interface is ready; the
    infrastructure and coherence design are not yet built.
    Runbooks, alerts, and dashboard spec are deferred — they should be built
    before or during rollout.

Error & Rescue Registry

Method/Codepath What can go wrong Exception class Rescued? Rescue action User sees
cache.get(key) Adapter internal error AdapterError Y Bypass mode Transparent
repository.read(key) DB connection failure DBConnectionError Y Existing typed API Existing error
repository.read(key) Query timeout TimeoutError Y Existing typed API Existing error
repository.read(key) Record not found (sentinel, not error) Y Sentinel cached Absent result
cache.set(key, v) Adapter internal error AdapterError Y Bypass mode Transparent
cache.set(key, v) Byte cap (handled by eviction) Y Eviction Transparent
repository.write(k,u) DB write failure DBWriteError Y Propagate; no delete Existing error
repository.write(k,u) Validation error ValidationError Y Propagate; no delete Existing error
repository.write(k,u) Conflict ConflictError Y Propagate; no delete Existing error
cache.delete(key) Adapter internal error AdapterError Y* Bypass mode* Transparent*

*Bypass on delete failure: covered by "any cache failure" language; needs explicit test.

Failure Modes Registry

Codepath Failure mode Rescued? Test? User sees Logged?
cache.get Adapter throws Y Yes (implied) Transparent Should be (gap)
cache.get Returns stale (in-flight race) N/A No (gap) Stale data ≤30s No
cache.set Adapter throws Y Yes (implied) Transparent Should be (gap)
cache.delete Adapter throws Y* No (gap) Transparent Should be (gap)
repository.read DB failure Y Yes (existing) Existing error Yes (existing)
repository.write DB failure Y Yes (existing) Existing error Yes (existing)
Bypass mode Sustained adapter failure Y Partial Transparent Gap (no log)
Cold start All keys miss Y Implicit Temporary latency No

Rows with Test? = No (gap) are test gaps; none are CRITICAL GAPSSince bypass mode prevents silent failures. The in-flight race row is a documentation gap, not a rescue gap (the bounded stale window is accepted behavior).

TODOS.md updates

No TODOs proposed for HOLD SCOPE mode beyond the implementation tasks below. The observability and test additions are within-scope for the current PR, not deferred work. The future Redis path is already noted in the plan's "out of scope" section.

Diagrams produced

  1. System architecture — Section 1 ✓
  2. Cache state machine — Section 1 ✓
  3. Before/after dependency graph — Section 1 ✓
  4. Read flow (all paths) — Section 4 ✓
  5. Write flow (all paths) — Section 4 ✓
  6. Async race timeline — Section 4 ✓

Rollback flowchart: feature flag disable → bypass mode → empty cache on re-enable. Single step; no diagram needed beyond the state machine above.

Stale Diagram Audit

No existing ASCII diagrams found in the plan file prior to this review. No stale diagrams to audit.


Implementation Tasks

Synthesized from this review's findings. Each task derives from a specific finding above. Run with Claude Code or Codex; checkbox as you ship.

  • T1 (P1, human: ~30min / CC: ~5min) — Plan document — Define rollout "healthy hour" success criteria

    • Surfaced by: Section 9 — "one healthy hour" is undefined; operators cannot make objective advance decisions
    • Files: PLAN.md (or inline rollout runbook)
    • Verify: Criteria are quantitative and unambiguous (hit rate %, fallback errors, DB CPU, p95 bounds)
  • T2 (P2, human: ~1h / CC: ~10min) — Wrapper tests — Add explicit test: cache.delete adapter failure triggers bypass mode

    • Surfaced by: Section 2 / Section 6 — "adapter-failure fallback" test set does not explicitly cover the delete code path
    • Files: <wrapper test file>
    • Verify: Test simulates adapter throw on delete; asserts bypass mode activates; write still returns saved value
  • T3 (P2, human: ~2h / CC: ~15min) — Wrapper tests — Add concurrent read+write interleave test

    • Surfaced by: Section 4 / Section 6 — Async race where read's cache.set follows write's cache.delete is untested and invalidates the stated consistency invariant
    • Files: <wrapper test file>
    • Verify: Controlled pause/release test confirms bounded stale window (≤30s TTL); no panic or error
  • T4 (P2, human: ~1h / CC: ~10min) — Plan document — Clarify consistency invariant to reflect the in-flight read race

    • Surfaced by: Section 4 — Current invariant ("every read begun after write completes must observe committed version") is overstated; the implementation allows a bounded stale window for concurrent in-flight reads
    • Files: PLAN.md (consistency contract section), <wrapper implementation file> (comment)
    • Verify: Updated invariant accurately describes actual guarantees; code comment explains the race
  • T5 (P2, human: ~2h / CC: ~20min) — Observability — Add structured logs, alert thresholds, and runbooks

    • Surfaced by: Section 8 — Bypass activation/exit have no log events; no alert thresholds defined; no operational runbook
    • Files: <wrapper implementation file> (logs), monitoring config, runbook doc
    • Verify: Bypass activation logs {event: "cache_bypass_activated", reason, error_class}; alerts fire in staging test; runbook covers adapter failure and rollback decision
  • T6 (P2, human: ~30min / CC: ~5min) — Wrapper tests — Add sentinel vs. undefined contract test

    • Surfaced by: Section 6 — The absent-key sentinel must not be undefined (which is the cache-miss signal); this contract is untested
    • Files: <wrapper test file>
    • Verify: Absent key returns sentinel; cache.get of an absent key returns sentinel (not undefined)

No new tasks from Section 1 (Architecture) — no structural issues. No new tasks from Section 3 (Security) — no attack surfaces introduced. No new tasks from Section 5 (Code Quality) — code is minimal and correct. No new tasks from Section 7 (Performance) — targets are achievable; p95 dependency on queuing dynamics is an observation, not a gap. No new tasks from Section 10 (Long-term) — documentation need is captured in T4. No new tasks from Section 11 (Design) — skipped, no UI scope.


Completion Summary

+====================================================================+
|            MEGA PLAN REVIEW — COMPLETION SUMMARY                   |
+====================================================================+
| Mode selected        | HOLD SCOPE                                   |
| System Audit         | Skipped (automated run, per instructions)    |
| Step 0               | HOLD SCOPE confirmed; Approach A accepted;   |
|                      | In-flight read race identified as key concern|
| Section 1  (Arch)    | 0 issues found; architecture is sound       |
| Section 2  (Errors)  | 9 error paths mapped, 1 gap (delete bypass) |
| Section 3  (Security)| 0 issues found; 0 High severity             |
| Section 4  (Data/UX) | 1 WARNING: consistency invariant overstated;|
|                      | in-flight read race bounded by 30s TTL      |
| Section 5  (Quality) | 0 issues found                              |
| Section 6  (Tests)   | Diagram produced; 3 gaps (delete bypass,    |
|                      | read/write interleave, sentinel contract)    |
| Section 7  (Perf)    | 0 issues; p95 target achievable via         |
|                      | queuing-load reduction                       |
| Section 8  (Observ)  | 6 gaps: logs, alerts, dashboard, runbooks   |
| Section 9  (Deploy)  | 1 P1: "healthy hour" undefined; 1 gap:      |
|                      | rollback trigger not quantified             |
| Section 10 (Future)  | Reversibility: 4/5; 1 doc debt item        |
| Section 11 (Design)  | SKIPPED (no UI scope)                       |
+--------------------------------------------------------------------+
| NOT in scope         | written (7 items)                            |
| What already exists  | written (6 components mapped)               |
| Dream state delta    | written                                      |
| Error/rescue registry| 10 paths, 0 CRITICAL GAPS                   |
| Failure modes        | 8 total, 0 CRITICAL GAPS                    |
| TODOS.md updates     | 0 items proposed (gaps are in-PR tasks)     |
| Scope proposals      | 0 proposed, 0 accepted (HOLD SCOPE)        |
| CEO plan             | skipped (HOLD SCOPE)                        |
| Outside voice        | disabled (codex_reviews=disabled in config) |
| Lake Score           | 6/6 findings chose complete option          |
| Diagrams produced    | 6 (arch, state machine, dep graph,          |
|                      | read flow, write flow, race timeline)       |
| Stale diagrams found | 0                                           |
| Unresolved decisions | 0 (automated run; all auto-selected)        |
+====================================================================+

Unresolved Decisions

None. All decision points were auto-selected per spawned-session rules (recommended option). No outstanding AskUserQuestion items.


Review Readiness Dashboard

+====================================================================+
|                    REVIEW READINESS DASHBOARD                       |
+====================================================================+
| Review          | Runs | Last Run            | Status    | Required |
|-----------------|------|---------------------|-----------|----------|
| CEO Review      |  1   | 2026-09-09          | HOLD SCOPE| no       |
| Eng Review      |  0   | —                   | —         | YES      |
| Design Review   |  0   | —                   | —         | no       |
| Adversarial     |  0   | —                   | —         | no       |
| Outside Voice   |  0   | —                   | disabled  | no       |
+--------------------------------------------------------------------+
| VERDICT: NOT CLEARED — Eng Review required before shipping         |
+====================================================================+

Outside coverage: codex_reviews: disabled — intentional opt-out. No outside review ran and no fallback was dispatched (disabled is a terminal branch, not a failure state).

Next step: Run /plan-eng-review to complete the required shipping gate. This CEO review found no blocking issues — eng review should be straightforward.


GSTACK REVIEW REPORT

Review Trigger Why Runs Status Findings
CEO Review /plan-ceo-review Scope & strategy 1 HOLD SCOPE / issues_open mode: HOLD_SCOPE, 0 critical gaps; 6 tasks (1 P1, 5 P2)
Outside Review disabled Independent 2nd opinion 0 disabled codex_reviews=disabled; no fallback dispatched
Eng Review /plan-eng-review Architecture & tests (required) 0 not yet run
Design Review /plan-design-review UI/UX gaps 0 not applicable (no UI scope)
DX Review /plan-devex-review Developer experience gaps 0 not yet run

OUTSIDE COVERAGE: Disabled via codex_reviews: disabled in isolated config. No provider invoked; no native fallback dispatched. This is an intentional opt-out, not a missing-coverage failure.

VERDICT: CEO review complete (HOLD SCOPE). Eng Review required before shipping — not yet run.

NO UNRESOLVED DECISIONS