Skip to content

perf(server): bound settled-shell cutoff allocation - #28931

Open
hieu-lee wants to merge 3 commits into
pingdotgg:mainfrom
hieu-lee:hieu-lee/perf-settled-shell-cutoff
Open

hieu-lee wants to merge 3 commits into
pingdotgg:mainfrom
hieu-lee:hieu-lee/perf-settled-shell-cutoff

Conversation

@hieu-lee

@hieu-lee hieu-lee commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Shell snapshot trimming collects and sorts every eligible settled timestamp to select the 25th newest cutoff. This creates temporary storage proportional to settled history, although only 25 values are needed. A refreshed 2,403-open-PR catalog and targeted diffs found no existing cutoff optimization; #21082, #27975 and #21627 touch independent snapshot transport, SQL counts or PR-link behavior.

Solution

Keep at most 25 timestamps in a local min-heap. Its root is the same cutoff; counting, ties, input/output order, lineage exclusions, pinned/snoozed/live/ancestor exceptions, and reconnect state remain unchanged. There are no new exports or wire changes.

The local qualification uses the complete baseline/current omitOlderSettledShells exports. A read-only sanitized database supplies the canonical updated_at ASC, thread_id ASC ordering, lineage, settlement timestamps, project grouping and pin/snooze fields for 78 active rows, 64 eligible settled. These fields feed complete schema-decoded shell templates; derived run fields are inert and time is fixed. Complete outputs agree and input immutability is checked. No private message text, title or path is published.

Nine alternating batches of 5,000 calls and three GC-inclusive allocation samples measured 25.086 → 13.964 ms (1.80×), with 51.80% fewer sampled allocated bytes. Independent confirmation measured 25.173 → 14.120 ms (1.78×), with 52.05% fewer sampled bytes. Even maximum candidate allocation versus minimum baseline allocation remains above 50% reduction. This qualifies the measured in-memory trimming workload—not SQL, complete subscriber latency, retained heap or whole-app memory.

Known tradeoff: larger oldest-first synthetic histories can be 4–10% slower, despite 67–98% lower sampled allocation. That ordering is reachable through the real SQL sort; the real-shaped result does not erase this limitation. Random, newest-first and tied synthetic histories qualify at 351 and 10,000 rows, but this is not a universal no-slowdown claim. Local benchmarks and artifacts are deliberately excluded from the PR.

Existing tests were expanded before production edits: 18 shell tests plus 4 selected WebSocket/ProjectionStore integration cases pass (subscription trimming, history cursor/counts, deferred decode and subagent-family reads). vp run check:changed is green, and a fresh batch of three independent Codex reviews is clean. The PR contains only production logic and its prewritten tests, with no visible UI or provider-specific change.

Built with GPT-6.1 Sol in the Codex harness through T3 Code.

TLDR

shell-cutoff.mp4

@hieu-lee

hieu-lee commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@github-actions github-actions Bot added vouch:unvouched Author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Nov 1, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at a1a2ce4

Macroscope's review found this PR approvable — Bounds settled-shell cutoff timestamp storage to 25 entries instead of sorting all settled timestamps. The existing visibility policy and retention exceptions remain unchanged, with no persistent-data changes.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

shellTrimFacts now uses a min-heap capped at 25 settled timestamps to determine the cutoff. A test checks that ascending, reverse, and shuffled input produce the same retained IDs, cutoff, and per-project omission counts.

Changes: Shell retention

Layer / File(s) Summary
Bounded cutoff and order-independence validation
apps/server/src/orchestration-v2/ShellStream.ts, apps/server/src/orchestration-v2/ShellStream.test.ts
shellTrimFacts maintains a min-heap capped at 25 timestamps and uses its root as the cutoff. The test checks consistent retained IDs, cutoff, and omission counts across three input orders.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Suggested reviewers: juliusmarminge, t3dotgg

Merge Risk: Minimal · up to 41c93

This change makes the settled-shell cutoff selection more efficient without altering which threads are retained. The supplied evidence shows no concrete risk, and it looks safe to merge.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title "perf(server): bound settled-shell cutoff allocation" follows conventional commit form and names the main change. The change bounds the settled-shell cutoff selection to a 25-entry min-heap,…
Description check Passed The description follows the template's main sections: Problem, Solution (in place of Change), Scope, Verification, and a TLDR. It explains the problem and the fix, and it lists tests run and measured …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "perf(server): bound settled-shell cutoff allocation" follows conventional commit form and names the main change. The change bounds the settled-shell cutoff selection to a 25-entry min-heap, reducing temporary allocation. It is specific and matches the changeset in ShellStream.ts and its test.

Full details: Description check

Explanation

The description follows the template's main sections: Problem, Solution (in place of Change), Scope, Verification, and a TLDR. It explains the problem and the fix, and it lists tests run and measured results. Scope is only partly addressed. It names related PRs (#21082, #27975, #21627) as independent. It does not link an issue or say whether a maintainer requested the PR, and it does not state why no issue is needed. The Verification section is detailed. It also discloses the known 4-10% slowdown on oldest-first histories. The description is mostly complete.

Resolution

Optionally add an explicit Scope statement: link the issue that shows the bug, or explain why a small optimization needs no issue. Also state whether a maintainer requested the PR. The template's Problem and Change headings are renamed to Problem and Solution; align them if the repository requires exact headings.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between a1a2ce4 and 41c93ee.

Files selected for processing: 2

  • apps/server/src/orchestration-v2/ShellStream.test.ts
  • apps/server/src/orchestration-v2/ShellStream.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor
Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@hieu-lee

hieu-lee commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

@maria-rcks could you review the bounded cutoff heap, retention ties/reconnect behavior and the explicitly disclosed large oldest-first CPU tradeoff? The latest head has green runnable CI, no unresolved CodeRabbit findings, and more than 15 minutes without a new real finding. Focused tests and a fresh batch of three independent Codex reviews passed before commit. Benchmark code is local-only and absent from the final diff; workload limits are in the PR description.

@maria-rcks

maria-rcks commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

checked exact head a1a2ce46f8290c657d9f859f945e8d482c92e380 against github/main at 71646e031a6dc9db1309b3b9dff597f872cf2fd3 on a linux boat vm. no changes were needed.

used repository playwright with /usr/bin/google-chrome. created a real git project and 28 conversations through the web ui, each with a completed codex gpt-6.1-sol turn, then settled them. stopped main before starting the pr and copied the stopped task-local data for the comparison. no mocks or seeded demo data.

fresh authenticated shell requests exercised the running server, with the debugger inspecting the timestamp array after collection:

GET /api/orchestration/shell?omitIdleSubagents=1&omitOlderSettled=1
x-t3-orchestration-protocol: 2
main: 28 settled timestamps stored; newest 25 retained; older count 3
pr:   25 settled timestamps stored; newest 25 retained; older count 3
both: cutoff 2026-11-02T23:40:21.808Z; retained retention-04 through retention-28
PASS identical retention ids, ordering, cutoff, and per-project older counts

freshly paired clients on both versions paged the settled shelf and opened the oldest real transcript. on the pr, pin/unpin and snooze/wake promoted an older thread back to active and fresh snapshots retained it. the restored conversation then completed another real codex turn, returning PR_RESUMED_OK.

blacksmith: all 18 shell-stream tests passed; vp run check:changed FETCH_HEAD~1 passed after fetching the exact head and its parent in the worker. format, lint, knip, graphql, affected typechecks, and 19 selected tests passed. the head also has 31 successful ci checks.

baseline history paging:
main settled history paging and oldest transcript

pr history paging:
pr settled history paging and oldest transcript

real codex follow-up in the restored older conversation

Not verified

native ios/android and electron clients, other providers, remote relay/tunnel connections, and live subagent/side-chat retention were not exercised. equal-timestamp ties were covered by the existing shell tests, not manufactured in the app. this verifies bounded timestamp storage and preserved behavior; it does not revalidate the description's speed or allocated-byte percentages. the optional allocation sampling attempt timed out without usable measurements.

@hieu-lee

Copy link
Copy Markdown
Contributor Author

@juliusmarminge could you review this when you have a moment?

Written by Claude Sonnet 5.5 via Claude Code in T3 Code.

@juliusmarminge juliusmarminge added the takeover:in-progress A takeover lead is working on this PR label Nov 15, 2026
juliusmarminge and others added 2 commits November 15, 2026 03:01
…-shell-cutoff

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore the existing omitOlderSettledShells cases and replace the
reconnect integration test with one test that feeds the same settled
rows oldest-first, newest-first and shuffled, which is what can break
in the bounded heap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

The automated pipeline stopped on this pull request and will not merge it:

the capture step could not show the problem on the base commit, so there is nothing to prove fixed.

Created 2 projects and 78 threads on each server; settled 64 with hourly ascending timestamps. Measured trimmed and untrimmed fresh HTTP snapshots with 50 warm-ups and 15 alternating batches of 200 requests per condition. Decoded each server's rows and measured untouched production trimming functions with 20,000 warm-ups and 15 alternating batches of 100,000 calls, pinned to the same CPU core. Compared returned IDs, ordering, cutoff and counts. Exercised cutoff ties and pin/snooze transitions through real server commands. Separately sampled allocations and observed cutoff-array lengths using diagnostic copies excluded from timing.

It stays open for a person to finish or close.

@juliusmarminge juliusmarminge added takeover:blocked Takeover blocked; reason in the PR body and removed takeover:in-progress A takeover lead is working on this PR labels Nov 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). takeover:blocked Takeover blocked; reason in the PR body vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants