Repository navigation
perf(diagnostics): opt-in feed-debug persistence, no-op worktree index saves, documented daily profile - #1349
Merged
Merged
Conversation
The background refresh (at least every 60 s) re-stamped updatedAt, stringified the whole index (30 MB+ for heavy users) and replaced the file even when every candidate was a cache hit, and the new timestamp invalidated the summary cache that exists to spare the 10 s UI poll. A refresh now persists only if something was parsed, a parse failed or the entry count moved; otherwise it records only when it checked. The store persists the caller's updatedAt instead of stamping its own. First tests for WorktreeActivityIndex (fail-first on origin/main). Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…are on; document the flags The feed-debug ring was shipped to disk once a second for every session in every build (up to 128 MiB per session file) with no switch. It is now persisted only with AGENT_CODE_DEV_DEBUG=1 or the Persistent Aggressive Debug Logs setting. The ring itself still records, and Save Debug Logs reads the ring, so bug reports are unchanged; only the after-crash copy needs a switch. Turning a switch on persists the retained tail on the next tick. The README gains a Diagnostics flags section: each flag and setting, its default and cost, and the recommended daily profile (all off, DEV_DEBUG only on demand). Proxy streaming is documented as the live transport, not a diagnostic. Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… switching persistence off Review of #1349: - "Nothing parsed and the same count" missed a swap (B leaves, C comes and goes, B returns unchanged from the LRU), so the stale set stayed on disk. The index now tracks its on-disk key set and persists when the set of paths differs. - Turning feed-debug persistence off ran the effect cleanup's final flush, writing one more batch; the cleanup now flushes only while the switch is still on (a real unmount). - Tests pin the in-memory generation through the served summaries and the provider-session cache guard (both mutations survived before). - README: AGENT_CODE_PERF adds spans and traces; the Performance Monitor's baseline runs regardless. The command-palette text for the setting names the feed-debug log too. Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re's no-restamp Review b of #1349: with the key-set comparison, a previously indexed transcript that fails to parse already counts as a change (it leaves the set); counting skipped files forced a full index rewrite on every refresh while an unindexed file stayed unreadable. A store-level test now pins that saveWorktreeActivityIndex keeps the caller's updatedAt (the old test only caught a restamp when two Date.now() calls straddled a millisecond). Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 2 of the #1349 review: the LRU only aged entries out, so for light users (whose summaries are built from the LRU) a deleted transcript kept appearing in the Worktrees summary, and one could return as a cache hit without being re-parsed. Every save now trims the LRU to the on-disk key set, which also makes any key new to the index a cache miss; the explicit key-set comparison is therefore unreachable and is removed. Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he index Review c of #1349 (round 2): re-adding the skipped-file trigger passed every test. A discovered transcript that keeps failing to parse is not index content; the new case keeps the file bytes and mtime unchanged across a refresh with one skipped candidate. Refs #767 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
Review disposition (final head
|
| # | Finding | Verdict | Disposition |
|---|---|---|---|
| R1-a major | A same-count swap of transcript paths was not persisted | valid | Fixed (bf0e2b58, then at the root in 764bdeb0): the LRU is trimmed to the on-disk keys on every save, so a returning key is a cache miss and gets re-parsed. The swap test is kept. |
| R1-a/c minor | Switching feed-debug persistence off still wrote one batch (effect cleanup) | valid | Fixed: the cleanup flushes only while the switch is on (enabledRef). A test checks for no append after switching off. |
| R1-a/c survivors | The in-memory updatedAt and the provider-session cache guard were unpinned |
valid | Fixed: served-summary and re-parse tests; both mutations are killed. |
| R1-b minor | The skippedFiles term forced rewrites while a file stayed unreadable |
valid | Fixed: the term is removed. A no-rewrite test (R2-c) catches the term being re-added. |
| R1-b minor | The store's no-restamp was only covered by a millisecond race | valid | Fixed: a deterministic indexStore test. |
| R1-c minor | The README over-claimed AGENT_CODE_PERF (the baseline Performance Monitor always runs) |
valid | Fixed. The command-palette text now also names the feed-debug log. |
| R1-c tradeoff | Default-off loses the after-crash feed-debug copy (1.1 GB on the owner's disk today) | accepted | Stated in the body. Save Debug Logs reads the in-memory ring. Reusing the "Persistent Aggressive Debug Logs" setting remains UNCONFIRMED; the owner may want a lighter dedicated switch. |
| R2-a major / R2-c minor | A removed transcript stayed in light users' served summaries (the LRU only aged out) | valid (pre-existing, exposed here) | Fixed (764bdeb0): the LRU is trimmed to the on-disk keys on save. A served-summary removal test is red without it (2 failures). |
| R2-a survivor | this.totalOnDisk = nextCount removal unpinned (first refresh with >1,000 transcripts) |
accepted | Not pinned: it needs a >1,000-transcript fixture. The field drives the light/heavy summary path, and the change doesn't touch that logic. |
| R2 declined | sessionRecovery.integration failed in combined runs under load |
separate | Filed #1357. This PR changes nothing that file imports, and it passes 66/66 ×3 unloaded. |
Verification at the final head:
src/main/worktreeActivitypasses 13/13, and persistence tests pass.npx tsc -bis clean (atc90fea0c; later commits change only tests and one method on a private class).
Final-pass cap (manager, 2026-09-27): round-2 a and c are manager-verified (temp/review-1349/manager-verify-a.md, -c.md): 764bdeb0 was checked fail-first, and af6dae0a is pinned.
Disclosed residual: round-2 a found a surviving mutation — deleting this.totalOnDisk = nextCount (WorktreeActivityIndex.ts) left the index tests green.
- It matters only on a FIRST refresh with more than 1 000 transcripts. The light-user summary path would then iterate only the capped LRU instead of loading the full on-disk index.
- It is not pinned by a test, and is accepted as a residual.
Owner
Author
|
OWNER-APPROVED: diagnostics feed-debug persistence opt-in (default off) is accepted. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #767. This PR covers items 1, 3 and 7 of the acceptance line. Item 6, moving the diagnostic sinks into a
utilityProcess, is split into #1346, so this isRefs, notFixes.Problem
Of #767's always-on diagnostic subsystems, three things remained on main:
updatedAtalso invalidated the summary cache that exists to spare the 10 s UI poll.Change
useFeedDebugPersist): it runs only withAGENT_CODE_DEV_DEBUG=1or the existing Persistent Aggressive Debug Logs setting.runtime.feedDebugLog), not the file, so bug reports are unchanged; only the after-crash copy needs a switch.WorktreeActivityIndex.refreshNow).lastIndexedAt, andupdatedAt(the content generation that keys the summary cache) stays the same.saveWorktreeActivityIndexpersists the caller'supdatedAtinstead of stamping a second timestamp.AGENT_CODE_PERFadds spans and traces; the Performance Monitor's baseline history runs regardless. The table also gives and the recommended daily profile (all off;DEV_DEBUG=1only on demand). "Proxy-Streamed Semantic Rendering" is documented as the live transport, not a diagnostic. The issue's original profile listed it as "off", but turning it off blanks live output, and its disk growth is bounded by Claude proxy-events.jsonl grows to 2+ GB per session and cannot be pruned while live #1273's rotation.Tests
WorktreeActivityIndex.test.ts(new; the class had no tests). It uses the real index store and transcript parser on a temp state dir; only home-directory discovery is replaced. There are 10 cases:updatedAt, while still recording the check;updatedAt;updatedAt.indexStore.test.ts: the store keeps the caller'supdatedAt, a deterministic check.origin/main.useFeedDebugPersist.renderer.test.tsx:origin/main.npx tsc -b: clean.Plan:
docs/plans/2026-09-26-diagnostics-default-off.md.🤖 Generated with Claude Code