mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-16 09:55:29 +02:00
* 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>
29 lines
36 KiB
JSON
29 lines
36 KiB
JSON
{
|
|
"provenance": {
|
|
"sourceHead": "ca16058341c2e073051340d9653bbbc900f3ca36",
|
|
"sourceProof": ".context/ship-source-af-delta-paid-20260909-v1/sdk-reports-ledger-v1/proof-v1.json",
|
|
"sourceProofSHA256": "20169897aa7a4a4434c4bcc67d4fdca3f8b13d572400c513b8741bc4c5fab42c",
|
|
"sourceReports": [
|
|
{
|
|
"path": ".context/ship-source-af-delta-paid-20260909-v1/sdk-reports-ledger-v1/4d0b8839-feed-4fbc-b612-f7531c13d6c2-report.md",
|
|
"sha256": "26c82847fb02ecdd2d8d452b6be569e0eff6028bfe50da639c7961f297a6c07b",
|
|
"bytes": 29481
|
|
},
|
|
{
|
|
"path": ".context/ship-source-af-delta-paid-20260909-v1/sdk-reports-ledger-v1/cf44b2fe-0639-4970-81ba-016494739ee7-report.md",
|
|
"sha256": "1c23d482482f44de9878a15daff13fdc6ff05a7cae1e64782de01c43000b664f",
|
|
"bytes": 30690
|
|
}
|
|
],
|
|
"actualTestOutcomes": [
|
|
"failed",
|
|
"failed"
|
|
],
|
|
"paidCoverageCredit": false
|
|
},
|
|
"retryReport": "# Plan: cache profile summaries in one process\n\n## Measured problem and accepted scope\nThe existing profile-summary service has one active process. A one-week trace\nshows repeated reads of about 900 hot keys: DB CPU is 70%, with read p95 120 ms.\nAdd a process-local LRU wrapper to the existing repository. Acceptance targets\nare at least 60% cache hits, DB CPU below 50%, and read p95 below 60 ms, with the\nexisting error-rate and correctness SLOs unchanged. This is an internal backend\nchange with no UI, API, schema, pricing, or developer onboarding change.\n\n## Existing contracts retained\n- All reads and writes use this repository in the same process; there are no\n external DB writers. Multi-process operation remains unsupported and startup\n rejects that configuration while caching is enabled.\n- Authentication and authorization run before repository access. Keys encode\n the authenticated tenant ID and validated profile ID without ambiguity.\n Values are immutable profile-summary DTOs; secrets and cache keys are never\n logged. Cached results cannot bypass authorization.\n- The existing LRU adapter supports 1000 entries, a 16 MiB byte cap, and a\n 30-second TTL. Recorded hot data fits those limits. Absent records use a\n distinct sentinel with a 10-second TTL; undefined means a cache miss.\n- Cache operations are synchronous and atomic in the single JS event loop.\n On any cache failure the existing adapter bypasses the cache until an empty\n cache is reinitialized; repository errors keep the current typed API error\n mapping. The existing per-key\n single-flight wrapper coalesces simultaneous misses and releases on failure.\n- A read already in progress when a write commits may return its earlier DB\n snapshot to that caller. Every read begun after that write completes must\n observe the committed version. TTL expiry is not a substitute for this rule.\n\n## Proposed wrapper integration (amended by CEO review, 2026-09-09)\nKeep the current read-through repository interface and shared adapters. The\noriginal sketch (read: get, miss, DB read, set; write: DB write, delete) had no\ncoordination between a cache fill and a write. Review finding F1 showed that\nviolates the read-after-write contract above, so the ordering rules now include\na per-key fill-generation guard. These are the complete read/write ordering\nrules:\n\n```javascript\n// F1: fill-generation guard. singleFlight is the existing per-key coalescer,\n// extended (or wrapped) with a per-key generation and an invalidate(key) call.\nasync function readProfile(key) {\n if (!cacheEnabledFor(key)) return repository.read(key); // F3: one shared flag evaluation\n const cached = cache.get(key); // F4: adapter decodes the absent sentinel\n if (cached !== undefined) return cached;\n return singleFlight.run(key, async (gen) => {\n const value = await repository.read(key); // absent -> adapter stores sentinel (F4)\n if (singleFlight.generation(key) === gen) cache.set(key, value); // stale fill after a write is dropped\n return value;\n });\n}\n\nasync function writeProfile(key, update) {\n if (!cacheEnabledFor(key)) return repository.write(key, update);\n const saved = await repository.write(key, update);\n singleFlight.invalidate(key); // bump generation, drop the in-flight entry so later readers refill\n cache.delete(key); // same tick as invalidate: atomic relative to other tasks\n return saved;\n}\n```\n\nAccepted amendments (details in the review record below):\n- F1: `singleFlight.invalidate(key)` on successful write; fill only stores when\n its captured generation is still current. Generation state lives only for\n keys with an in-flight fill, so it is bounded by concurrent misses.\n- F3: `cacheEnabledFor(key)` is one deterministic function used by both paths.\n Any flag-state change (off/on or any percentage change in either direction)\n reinitializes both the cache and the single-flight state as empty.\n- F4: the adapter owns sentinel encode/decode. A cached absence must produce\n the identical result the repository produces for an uncached absence. If the\n repository signals absence by throwing its typed not-found error, the wrapper\n catches only that class, stores the sentinel, and rethrows.\n\n## Verification and rollout (amended by CEO review, 2026-09-09)\nExisting repository contract tests cover tenant isolation, key validation,\nabsence, DB failures, and authorization. New wrapper tests cover hit/miss,\neviction and byte limits, TTL, adapter-failure fallback, successful-write\ninvalidation, failed-write preservation, and concurrent-miss coalescing.\n\nAdded by review (see Implementation Tasks T1-T4):\n- Controlled-schedule ordering tests for the fill/write race, both the\n late-set variant and the single-flight-join variant (F1).\n- Absent-sentinel wrapper tests: sentinel hit serves no DB read, expires at\n 10 s, is invalidated by a create, and is indistinguishable from an uncached\n absence (F4).\n- Flag-transition tests: every percentage change flushes; read and write\n evaluate the flag identically for the same key (F3).\n- Bypass observability: `profile_cache_bypass_active` gauge, one structured\n log line on entering bypass naming the adapter error class and no key, alert\n when the gauge stays 1 for 5 minutes or hit ratio is below 0.6 for 15 minutes\n at 100% rollout, runbook step \"flag off then on reinitializes\" (F2).\n\nThe rollout uses the existing runtime feature flag: enable for 10% of keys,\nthen 50%, then all keys after one healthy hour at each stage. Monitor hit/miss,\neviction, cache bytes, fallback errors, bypass gauge, DB CPU, and read p95\nwithout raw IDs. On error-rate or latency regression, disable the flag\nimmediately; both reads and writes bypass the cache while disabled, and any\nflag-state change creates an empty cache. Cold starts remain within the\nexisting DB capacity. The service owner monitors the rollout and records the\nresults against the acceptance targets.\n\n## Out of scope\nDistributed caching, cross-process coherence, prewarming, changing consistency\nsemantics, or adding new product surfaces. The repository interface preserves a\nfuture replacement path without introducing a general cache framework now.\n\n## CEO Review Record (HOLD SCOPE, 2026-09-09)\n\nRun conditions: automated run, no human present. System audit, environment\nsetup, telemetry, codebase exploration, and all shell commands (review-log,\ndecision-log, tasks JSONL, review-read) were skipped per run rules. Every\ndecision point that would call AskUserQuestion was auto-decided to the skill's\nrecommended option and is recorded here. `codex_reviews: disabled` in the\nrun config: the outside-voice step was skipped in full, no native fallback.\n\n### Step 0 outcomes\n- **0A Premise:** Right problem. The trace quantifies the pain (70% DB CPU,\n p95 120 ms on ~900 hot keys). Doing nothing leaves DB headroom at 30% with\n no lever. A process-local cache is the most direct path given one process\n and no external writers. Not a proxy problem.\n- **0B Existing leverage:** Reuses the LRU adapter (limits, TTL, sentinel,\n failure bypass), the per-key single-flight wrapper, the typed API error\n mapping, the runtime flag, and the repository contract tests. Nothing is\n rebuilt. Gap: the single-flight wrapper needs a generation/invalidate\n extension (F1); no existing mechanism covers it.\n- **0C Dream state:**\n ```\n CURRENT STATE THIS PLAN 12-MONTH IDEAL\n every read hits DB ---> read-through LRU behind the ---> same repository interface,\n 1 process, 70% CPU same interface, flagged, cache backend swappable\n coherent with writes (local or shared) if a\n second process is ever needed\n ```\n Moves toward the ideal: the interface is unchanged and the wrapper is the\n seam a future backend would replace.\n- **0C-bis Alternatives (D1, auto-decided):**\n ```\n APPROACH A: Inline wrapper functions in the repository module (plan's structure)\n Effort S | Risk Low | Reuses adapter, single-flight, flag\n + smallest diff, interface unchanged - flag/cache/repo logic share one module\n APPROACH B: Decorator class implementing the repository interface\n Effort M | Risk Low | Reuses the same pieces\n + clean bypass (return raw repo when off), isolated tests - new class, more files, same behavior\n APPROACH C: Cache at the DB query layer\n Effort L | Risk Med\n + transparent to callers - loses the DTO-level sentinel and key contract; wrong layer\n RECOMMENDATION: A. Note: options differ in kind, not coverage. Smallest diff that\n cleanly expresses the change; B is a taste call with no behavioral gain in this scope.\n ```\n Decision: A (recommended, auto-chosen).\n- **0F Mode:** HOLD SCOPE, specified by the user. No question asked.\n- **0D HOLD SCOPE analysis:** Touches 2-3 files (repository module, single-flight\n helper, tests) and adds no new class. No complexity smell. Minimum change is\n the sketch plus the F1 guard; F1 is not deferrable because it is required to\n meet a stated invariant. Nothing else can be cut without breaking a stated\n requirement.\n- **0E Temporal interrogation:** Decisions resolved now rather than mid-build:\n where generation state lives (F1: inside single-flight, bounded by in-flight\n keys), where sentinel encode/decode lives (F4: adapter), what \"enabling\n creates an empty cache\" means for partial percentage changes (F3: every\n change flushes), and who acts on bypass (F2: alert + runbook). Human ~6 h,\n CC ~45 min for the whole change.\n\n### Findings registry (each recorded once; sections cross-reference by ID)\n\n| ID | Sev | Section | Evidence | Selected remedy | Decision | Residual risk | Verification |\n|----|-----|---------|----------|-----------------|----------|---------------|--------------|\n| F1 | CRITICAL GAP | 1, 4 | Sketch fills cache after an awaited DB read with no version check; plan states \"no additional version checks or coordination\". Schedule S1 below shows a read begun after a completed write returning the pre-write value for up to 30 s, violating the retained contract. Single-flight join variant (S1 R3) has the same effect. | Per-key fill generation captured before the DB read; `invalidate(key)` on successful write bumps it and drops the in-flight entry; fill stores only when generation matches. Sentinel fills use the same guard. | Accepted (auto, recommended, Completeness 10/10 vs 4/10 for \"document as acceptable\", which is prohibited by the requirement rule) | Generation state must be cleared on cache reinitialize; covered by \"new single-flight state\" in F3 flush. | Tests T1: pause/release both S1 orders; assert R2 and R3 read DB and return v2; assert cache holds no v1 after R1 resumes. |\n| F2 | WARNING | 8 | Adapter failure puts the process in bypass \"until an empty cache is reinitialized\". Plan monitors a fallback-error counter only; no gauge, alert, or named recovery action. Correct results continue, so the perf regression is silent. | `profile_cache_bypass_active` gauge; one structured log at bypass entry (error class, stage, no key); alerts: gauge 1 for 5 min, or hit ratio below 0.6 for 15 min at 100%; runbook: flag off then on reinitializes, repeat means leave off and file bug. | Accepted (auto, recommended, 10/10 vs 6/10 counter-only) | Alert thresholds are initial guesses; tune after first week. | Test T4: inject adapter throw, assert gauge 1, log line without key, reads served from DB; flag cycle resets gauge to 0. |\n| F3 | WARNING | 9 | Plan defines an empty cache only on \"enabling\". A 50% to 10% partial rollback then re-advance would expose entries whose keys had writes bypass `cache.delete` while disabled. Per-key percentage evaluation on read and write is not stated to be the same function. | Any flag-state change reinitializes cache and single-flight state. One deterministic `cacheEnabledFor(key)` used by both paths. | Accepted (auto, recommended, 10/10 vs 7/10 \"document: only use full disable\") | Each stage advance is a cold start; plan already states cold starts fit DB capacity. | Test T3: enable K, write K while K disabled, re-enable, assert miss and fresh DB read; property test that read/write evaluation agree for the same key and flag state. |\n| F4 | WARNING | 5, 2, 6 | Sketch returns `cached` directly and calls `cache.set(key, value)`, so sentinel encode/decode is unspecified. If the repository signals absence by throwing, the sketch never caches absence and the 10 s sentinel is dead code. Wrapper test list omits sentinel hit, TTL, and create-invalidation. | Adapter owns encode/decode; cached absence yields the identical result as uncached absence; if repository throws typed not-found, wrapper catches only that class, stores sentinel, rethrows. | Accepted (auto, recommended, 10/10 vs 6/10 \"positive caching only\") | Repository absence form not verified (codebase not explored); implementer confirms in T2. | Test T2: absent read twice within 10 s hits DB once and both results are identical; after 10 s DB is read again; create invalidates sentinel via F1 path. |\n\n### Section outcomes (1-11)\n1. **Architecture:** 1 finding (F1). Diagram D1 below. No new coupling beyond\n repository to single-flight generation API. SPOF is the single process\n (pre-existing, documented). 10x load: 900 hot keys still fit; 100x: entry\n and byte caps evict, hit rate falls, DB absorbs the rest. Rollback: flag off\n (seconds) or revert (no migration).\n2. **Error & rescue map:** 7 error paths mapped, 0 unrescued gaps after F2 and\n F4. Registry below. No catch-all handlers introduced; the only new catch is\n the typed not-found class in F4.\n3. **Security & threat model:** No issues found. No new endpoints, inputs, or\n dependencies. Keys carry tenant and validated profile ID, so cross-tenant\n reads via key manipulation are not possible; auth runs before the cache.\n Memory exhaustion bounded by 16 MiB and 1000 entries. Logs exclude keys\n (F2 log line asserts this). Low likelihood, low impact across the board.\n4. **Data flow & edge cases:** 1 finding (F1, async ordering). Shadow paths\n traced in D2; all handled. No user-visible interaction (backend only).\n5. **Code quality:** 1 finding (F4). readProfile has 3 branches, writeProfile 2;\n no complexity concern. No DRY violation: flag evaluation is one function by\n F3. Not over-engineered: generation state is the minimum coordination that\n satisfies the invariant.\n6. **Tests:** Diagram D7 produced; 4 gaps, each closed by T1-T4. 2am test: S1\n schedule tests. Hostile QA: write during coalesced fill with 50 waiters.\n Chaos: adapter throws mid-set. Pyramid: unit-heavy, correct. Flakiness:\n TTL tests must use an injected clock, not wall time.\n7. **Performance:** No issues found. Hit path is one synchronous map lookup.\n Max memory 16 MiB plus bounded generation entries. No new DB queries,\n indexes, or connections. Coalescing already bounds miss storms.\n8. **Observability:** 1 finding (F2). Existing metric list is adequate once the\n bypass gauge, alert, and runbook exist. Three-week debuggability: bypass\n entry log names the error class and time.\n9. **Deployment & rollout:** 1 finding (F3). No migration. Flag-gated, staged,\n with explicit rollback (D5, D6). Post-deploy checklist: first 5 min watch\n error rate and bypass gauge; first hour watch hit ratio and p95.\n10. **Long-term trajectory:** No issues found. Reversibility 5/5. Debt: one\n small generation API in single-flight, documented in code comment with\n diagram D3. A new engineer reading this plan in 12 months sees the invariant\n and the guard side by side.\n11. **Design & UX:** SKIPPED, justified: no UI scope (internal backend change).\n\n### Outside voice\nCodex review skipped (codex_reviews disabled). Re-enable: `gstack-config set\ncodex_reviews enabled`. No native fallback was dispatched; disabled is an\nintentional opt-out. The review-log persistence command was not run in this\nsession (no shell per run rules); outside_status is recorded here as disabled.\n\n### NOT in scope\n- Distributed or shared cache: no second process exists; startup rejects it.\n- Prewarming: cold start fits DB capacity per plan.\n- Cache framework or decorator class (Approach B): no behavioral gain now.\n- Alert-threshold tuning beyond initial values: needs a week of data.\n\n### What already exists\n- LRU adapter with caps, TTL, sentinel, failure bypass: reused as is.\n- Per-key single-flight wrapper: reused, extended with generation/invalidate (F1).\n- Typed API error mapping: reused unchanged.\n- Runtime feature flag: reused; flush-on-change rule added (F3).\n- Repository contract tests: reused; wrapper tests added (T1-T4).\n\n### Dream state delta\nAfter this plan the repository interface is unchanged and the cache is a\nsingle seam. The 12-month ideal (swappable backend) needs only a new adapter\nbehind the same wrapper. Nothing here forecloses it.\n\n### Error & Rescue Registry\n```\nMETHOD/CODEPATH | WHAT CAN GO WRONG | EXCEPTION CLASS | RESCUED? | RESCUE ACTION | USER SEES\n---------------------------|------------------------------------------|----------------------------------|----------|-------------------------------------------------|---------------------------\nreadProfile cache.get/set | adapter fault (size calc, accounting) | adapter's internal error classes | Y | adapter enters bypass; F2 gauge+log; DB read | nothing (slower)\nreadProfile repository.read| DB timeout / connection failure | existing typed repository errors | Y (exist)| rethrown; single-flight releases; nothing cached| existing API error\nreadProfile repository.read| record absent | typed not-found (or null result) | Y | F4: store sentinel 10 s; return identical result| existing not-found\nreadProfile singleFlight | fill rejects with N waiters coalesced | same repository error | Y (exist)| all waiters receive the error; entry released | existing API error\nwriteProfile repository.write| validation / conflict / timeout | existing typed repository errors | Y (exist)| rethrown; cache untouched (failed-write test) | existing API error\nwriteProfile invalidate/delete| adapter fault | adapter's internal error classes | Y | adapter bypass; F2 gauge+log | nothing\ncacheEnabledFor(key) | flag client lookup failure | flag client's existing error | Y (exist)| treated as disabled; existing flag client metric| nothing (slower)\n```\nImplementer confirms the concrete class names for adapter and flag-client\nerrors in T4; catch-all handlers are not permitted.\n\n### Failure Modes Registry\n```\nCODEPATH | FAILURE MODE | RESCUED? | TEST? | USER SEES? | LOGGED?\n--------------------|---------------------------------------|----------|-----------|---------------------|--------\nreadProfile fill | stale fill after completed write (F1) | Y (guard)| Y (T1) | correct value | n/a\nreadProfile join | later reader joins pre-write fill (F1)| Y (guard)| Y (T1) | correct value | n/a\nreadProfile | absent result, sentinel path (F4) | Y | Y (T2) | not-found (same) | n/a\nreadProfile | DB error on miss | Y | Y (exist) | API error | Y (exist)\nadapter | cache fault -> bypass (F2) | Y | Y (T4) | nothing, slower | Y (F2)\nwriteProfile | DB write fails | Y | Y (exist) | API error | Y (exist)\nflag | partial rollback leaves stale entries (F3)| Y (flush)| Y (T3) | correct value | flag change log (exist)\nflag | lookup failure | Y | Y (exist) | nothing, slower | Y (exist)\n```\nBefore remedies: F1 was RESCUED=N, TEST=N, USER SEES=stale value silently,\na CRITICAL GAP. After accepted remedies: 0 CRITICAL GAPS remain.\n\n### TODOS.md updates\n0 items proposed. Every evidenced gap is an in-scope repair (T1-T4). No\nhypothetical capacity or optional feature is surfaced in HOLD SCOPE.\n\n### Diagrams\nD1 System architecture and dependencies (before -> after):\n```\nBEFORE: caller -> auth -> repository -> DB\nAFTER: caller -> auth -> repository wrapper -> cacheEnabledFor(flag)\n | hit | miss | off\n v v v\n LRU adapter singleFlight(gen) ---> DB\n (sentinel, ^ invalidate(key) on write\n bypass) |\n writeProfile ---> DB, then invalidate + delete\nNew edge: repository wrapper -> singleFlight generation API (F1). No other new coupling.\n```\nD2 Data flow with shadow paths:\n```\nkey \u2500\u25b6 cacheEnabledFor \u2500\u25b6 cache.get \u2500\u25b6 singleFlight.run \u2500\u25b6 repository.read \u2500\u25b6 gen check \u2500\u25b6 cache.set \u2500\u25b6 value\n \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n nil/invalid: rejected undefined=miss join in-flight absent: sentinel mismatch: adapter fault:\n upstream by key validation sentinel=absent (same gen only) (F4) skip set (F1) bypass (F2)\n (existing tests) error: all waiters error: typed, nothing cached\n```\nD3 State machine, cache entry for key K:\n```\n fill (gen ok, value) write / TTL 30s / evict\n [ABSENT] \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6 [VALUE] \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6 [ABSENT]\n \u2502 fill (gen ok, absent) write (create) / TTL 10s\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6 [SENTINEL] \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6 [ABSENT]\n Invalid: [ABSENT] -> [VALUE] via stale fill after write (prevented by gen mismatch, F1)\n Invalid: entry survives a flag change (prevented by flush, F3)\n Process-level: [ACTIVE] --adapter fault--> [BYPASS] --flag off/on--> [ACTIVE, empty]\n```\nD4 Error flow: see registry; every path ends in \"existing typed API error\",\n\"served from DB\", or \"correct value\", never in a swallowed error.\nS1 Async ordering schedule (F1 evidence):\n```\n t | R1 read (begins before W) | W write | R2 read (begins after W) | cache[K] | DB[K]\n 1 | get(K) -> undefined | | | - | v1\n 2 | await repository.read -> v1 | | | - | v1\n 3 | paused | await write commits v2 | | - | v2\n 4 | paused | delete(K) (no entry) | | - | v2\n 5 | paused | returns | | - | v2\n 6 | resume: set(K, v1); return v1 | | | v1 STALE | v2\n 7 | | | get(K) -> v1; return v1 | v1 | v2\n VIOLATION t7: R2 began after W completed (t5), observes v1 for up to 30 s.\n Variant R3: begins at t5, misses, joins R1's in-flight promise, returns v1. Same violation.\n Guarded: t4 invalidate(K) bumps gen, drops in-flight; t6 gen mismatch -> no set;\n t7 miss -> fresh fill -> v2. R3 at t5 finds no in-flight entry -> fresh fill -> v2.\n Allowed by contract: R1 itself returns v1 (read in progress when write committed).\n```\nD5 Deployment sequence:\n```\ndeploy code (flag 0%) -> smoke: reads/writes bypass, gauge 0\n -> flag 10% (flush) -> 1 h healthy -> flag 50% (flush) -> 1 h healthy -> flag 100% (flush)\n -> record hit ratio, DB CPU, p95 against targets\n```\nD6 Rollback flowchart:\n```\nregression seen? \u2500\u2500 no \u2500\u2500\u25b6 continue stage\n \u2502 yes\n \u25bc\nflag 0% (both paths bypass, cache emptied) \u2500\u2500\u25b6 error/latency recovered?\n \u2502 yes: investigate with bypass log + metrics \u2502 no: revert deploy (no migration)\n```\nD7 Test map (Section 6):\n```\nNEW DATA FLOWS: read hit; read miss+fill; read absent (sentinel); write invalidate; flag bypass\nNEW CODEPATHS: gen match/mismatch; invalidate(key); cacheEnabledFor; flush on flag change\nNEW ASYNC WORK: single-flight fill with concurrent write (S1 both orders)\nNEW INTEGRATIONS: none external\nNEW ERROR PATHS: adapter fault -> bypass + gauge; typed not-found -> sentinel + rethrow\nCoverage: unit (all above, injected clock and deferred DB promises); integration\n(existing contract tests run with flag on and off); no E2E needed.\n```\n\n### Stale diagram audit\nNot audited: codebase exploration was skipped per run rules. T1 includes\nchecking the repository module, adapter, and single-flight helper for existing\nASCII diagrams and updating them to show the generation guard.\n\n## Implementation Tasks\nSynthesized from this review's findings. Each task derives from a specific\nfinding above. Run with Claude Code or Codex; checkbox as you ship.\n\n- [ ] **T1 (P1, human: ~3h / CC: ~20min)** \u2014 repository wrapper + single-flight \u2014 Add per-key fill generation and `invalidate(key)`; store only on generation match\n - Surfaced by: Section 1/4 \u2014 F1, schedule S1\n - Files: repository module, single-flight helper, wrapper tests\n - Verify: deferred-promise tests for both S1 orders; R2 and R3 return v2 and hit DB; no v1 in cache after R1 resumes; update any existing ASCII diagrams in touched files\n- [ ] **T2 (P1, human: ~1.5h / CC: ~10min)** \u2014 LRU adapter \u2014 Own sentinel encode/decode; cached absence identical to uncached absence\n - Surfaced by: Section 5 \u2014 F4\n - Files: adapter, repository module, wrapper tests\n - Verify: two absent reads within 10 s hit DB once with identical results; DB re-read after 10 s; create invalidates sentinel\n- [ ] **T3 (P2, human: ~1h / CC: ~10min)** \u2014 flag gating \u2014 Single `cacheEnabledFor(key)`; flush cache and single-flight state on any flag-state change\n - Surfaced by: Section 9 \u2014 F3\n - Files: repository module, flag wiring, wrapper tests\n - Verify: enable K, write K while disabled, re-enable, assert miss; read/write evaluation agrees for every key and flag state\n- [ ] **T4 (P2, human: ~1.5h / CC: ~10min)** \u2014 observability \u2014 Bypass gauge, entry log without key, two alerts, runbook entry\n - Surfaced by: Section 8 \u2014 F2\n - Files: adapter bypass path, metrics/alert config, runbook doc\n - Verify: injected adapter throw sets gauge 1 and emits log with error class and no key; flag cycle resets gauge; alert rules lint\n- _No new tasks from Section 3 (Security)._\n- _No new tasks from Section 7 (Performance)._\n- _No new tasks from Section 10 (Trajectory)._\n- _No new tasks from Section 11 (Design, skipped)._\n\nTasks JSONL artifact: not written (no shell in this run). Autoplan\naggregation for this phase must be regenerated from the list above.\n\n### Completion Summary\n```\n +====================================================================+\n | MEGA PLAN REVIEW \u2014 COMPLETION SUMMARY |\n +====================================================================+\n | Mode selected | HOLD SCOPE |\n | System Audit | skipped per run rules |\n | Step 0 | HOLD; approach A (inline wrapper) auto-chosen|\n | Section 1 (Arch) | 1 issue found (F1) |\n | Section 2 (Errors) | 7 error paths mapped, 0 GAPS after F2/F4 |\n | Section 3 (Security)| 0 issues found, 0 High severity |\n | Section 4 (Data/UX) | 9 edge cases mapped, 0 unhandled after F1 |\n | Section 5 (Quality) | 1 issue found (F4) |\n | Section 6 (Tests) | Diagram produced, 4 gaps (closed by T1-T4) |\n | Section 7 (Perf) | 0 issues found |\n | Section 8 (Observ) | 1 gap found (F2) |\n | Section 9 (Deploy) | 1 risk flagged (F3) |\n | Section 10 (Future) | Reversibility: 5/5, debt items: 1 (gen API) |\n | Section 11 (Design) | SKIPPED (no UI scope) |\n +--------------------------------------------------------------------+\n | NOT in scope | written (4 items) |\n | What already exists | written |\n | Dream state delta | written |\n | Error/rescue registry| 7 methods, 0 CRITICAL GAPS |\n | Failure modes | 8 total, 0 CRITICAL GAPS (1 fixed: F1) |\n | TODOS.md updates | 0 items proposed |\n | Scope proposals | 0 proposed, 0 accepted (HOLD) |\n | CEO plan | skipped (HOLD) |\n | Outside voice | codex, disabled |\n | Lake Score | 4/4 recommendations chose complete option |\n | Diagrams produced | 8 (arch, data flow, state, error, schedule, |\n | | deploy, rollback, test map) |\n | Stale diagrams found | not audited (see Stale diagram audit) |\n | Unresolved decisions | 0 |\n +====================================================================+\n```\n\n### Unresolved Decisions\nNone. D1 and F1-F4 were auto-decided to the recommended option per run\nrules; no destructive or irreversible option was involved.\n\n## GSTACK REVIEW REPORT\n\n| Review | Trigger | Why | Runs | Status | Findings |\n|--------|---------|-----|------|--------|----------|\n| CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | clean | mode: HOLD_SCOPE, 4 findings accepted, 0 critical gaps remaining |\n| Outside Review | codex (`codex_reviews: disabled`) | Independent 2nd opinion | 0 | disabled | \u2014 |\n| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 0 | \u2014 | \u2014 |\n| Design Review | `/plan-design-review` | UI/UX gaps | 0 | \u2014 | \u2014 |\n| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | \u2014 | \u2014 |\n\n- **OUTSIDE COVERAGE:** provider codex, phase plan-review, status disabled by config; no native fallback dispatched; no outside findings.\n- **VERDICT:** CEO CLEARED \u2014 eng review required\n\nNO UNRESOLVED DECISIONS\n",
|
|
"retrySchedule": "S1 Async ordering schedule (F1 evidence):\n```\n t | R1 read (begins before W) | W write | R2 read (begins after W) | cache[K] | DB[K]\n 1 | get(K) -> undefined | | | - | v1\n 2 | await repository.read -> v1 | | | - | v1\n 3 | paused | await write commits v2 | | - | v2\n 4 | paused | delete(K) (no entry) | | - | v2\n 5 | paused | returns | | - | v2\n 6 | resume: set(K, v1); return v1 | | | v1 STALE | v2\n 7 | | | get(K) -> v1; return v1 | v1 | v2\n VIOLATION t7: R2 began after W completed (t5), observes v1 for up to 30 s.\n Variant R3: begins at t5, misses, joins R1's in-flight promise, returns v1. Same violation.\n Guarded: t4 invalidate(K) bumps gen, drops in-flight; t6 gen mismatch -> no set;\n t7 miss -> fresh fill -> v2. R3 at t5 finds no in-flight entry -> fresh fill -> v2.\n Allowed by contract: R1 itself returns v1 (read in progress when write committed).\n```",
|
|
"retryFinding": "| F1 | CRITICAL GAP | 1, 4 | Sketch fills cache after an awaited DB read with no version check; plan states \"no additional version checks or coordination\". Schedule S1 below shows a read begun after a completed write returning the pre-write value for up to 30 s, violating the retained contract. Single-flight join variant (S1 R3) has the same effect. | Per-key fill generation captured before the DB read; `invalidate(key)` on successful write bumps it and drops the in-flight entry; fill stores only when generation matches. Sentinel fills use the same guard. | Accepted (auto, recommended, Completeness 10/10 vs 4/10 for \"document as acceptable\", which is prohibited by the requirement rule) | Generation state must be cleared on cache reinitialize; covered by \"new single-flight state\" in F3 flush. | Tests T1: pause/release both S1 orders; assert R2 and R3 read DB and return v2; assert cache holds no v1 after R1 resumes. |",
|
|
"firstGuardedEvidence": "| F1 | CRITICAL | \"no additional version checks or coordination between a cache fill and a write\" vs contract \"every read begun after that write completes must observe the committed version\". Schedule S1 below shows a fill storing V0 after V1 committed. Same race caches `ABSENT` after a create. | D2: `stale` flag on the in-flight single-flight record; write marks it after commit; stale fill returns but does not store. Counter `profile_cache_fill_skipped_stale`. | None for the invariant. A burst of writes on a hot key lowers hit ratio for that key only. | Paused-fill test, both orders, plus create-after-absent variant (T1). |\n\nS1 Async schedule (F1), shared state = cache[K]\n```\n t | Read R1 (fill) | Write W | cache[K]\n 1 | get(K) \u2192 undefined | | empty\n 2 | await repository.read(K) | | empty\n 3 | DB snapshot = V0 | await repository.write(K) | empty\n 4 | | commit V1 | empty\n 5 | | finally: mark stale, delete | empty\n 6 | | return (W complete) | empty\n 7 | resume: stale \u2192 no store | | empty (unguarded: V0 stored = violation)\n 8 | R2 begins: miss \u2192 read V1 | | V1\n Other order: R1 resumes at t5 before W's continuation, stores V0; W's delete at t5 removes it. Safe.\n```"
|
|
}
|