Commit graph

1928 commits

Author SHA1 Message Date
777genius
c1ebecf813 perf(renderer): reduce activity timer storage writes 2026-05-31 06:37:38 +03:00
777genius
03106e0c24 perf(renderer): centralize theme side effects 2026-05-31 06:35:21 +03:00
777genius
61919f5aec perf(renderer): reuse theme state in activity badges 2026-05-31 06:31:16 +03:00
777genius
477d18d798 perf(renderer): memoize active task summary data 2026-05-31 06:25:28 +03:00
777genius
34c2215c31 perf(renderer): cache active teammate roster keys 2026-05-31 06:16:19 +03:00
777genius
66ab83a7ce perf(main): avoid cli arg cache copies 2026-05-31 06:13:44 +03:00
777genius
a0faab56aa perf(main): reuse normalized bootstrap success inputs 2026-05-31 06:12:57 +03:00
777genius
743bef8f30 perf(main): lengthen runtime process table cache 2026-05-31 06:08:01 +03:00
777genius
0e82c1bdbd perf(main): trim repeated runtime hot loop work 2026-05-31 06:05:25 +03:00
777genius
ad6a7b1998 perf(renderer): compare kanban task dependencies 2026-05-31 05:59:02 +03:00
777genius
ad2f602cba perf(renderer): gate timeline live lead props 2026-05-31 05:58:56 +03:00
777genius
a4ad5f6297 perf(renderer): cache member telemetry preview snapshots 2026-05-31 05:58:49 +03:00
777genius
db2c82475b perf(renderer): pass composer member avatars 2026-05-31 05:37:33 +03:00
777genius
4d0f3d802b perf(renderer): skip idle reply candidate scans 2026-05-31 05:35:02 +03:00
777genius
5041c79916 perf(renderer): cache repeated team badge selectors 2026-05-31 05:28:10 +03:00
777genius
93a45e0823 perf(renderer): defer lead thought preview work 2026-05-31 05:13:22 +03:00
777genius
9a1c778d67 perf(renderer): cache member runtime telemetry renders 2026-05-31 05:05:54 +03:00
777genius
0924a35682 perf(renderer): isolate kanban log activity updates 2026-05-31 04:53:40 +03:00
777genius
583bb5f26a perf(renderer): isolate pending replies from team page root 2026-05-31 04:46:22 +03:00
777genius
7019567537 perf(renderer): isolate send dialog state from team page 2026-05-31 04:39:08 +03:00
777genius
c9e9e4ae09 perf(renderer): ignore lead activity churn in task sidebar 2026-05-31 04:33:47 +03:00
777genius
e21e80ac05 perf(renderer): reduce kanban grid resize handles 2026-05-31 04:26:04 +03:00
777genius
b9bc6ff83e perf(renderer): compare visible sidebar project rows 2026-05-31 04:21:34 +03:00
777genius
5669373283 perf(renderer): narrow messages panel loading state 2026-05-31 04:19:00 +03:00
777genius
36939d428a perf(renderer): skip stable sidebar task group renders 2026-05-31 04:15:01 +03:00
777genius
b6ea569623 perf(renderer): ignore member telemetry history churn 2026-05-31 04:08:51 +03:00
777genius
a2a4f99fce perf(renderer): avoid sorting stable team mention metadata 2026-05-31 04:00:34 +03:00
777genius
b9527004f3 perf(renderer): stabilize messages team mention selector 2026-05-31 03:58:13 +03:00
777genius
4fe21949e2 perf(renderer): cache activity item parsing 2026-05-31 03:53:52 +03:00
777genius
bc660e7e9b perf(renderer): slow process-lite runtime telemetry refresh 2026-05-31 03:46:25 +03:00
777genius
b2c416dee6 perf(renderer): narrow sidebar task team subscriptions 2026-05-31 03:37:22 +03:00
777genius
4799fe1a3b perf(renderer): cache activity timeline rendering 2026-05-31 03:31:50 +03:00
777genius
b8f394d9f7 perf(renderer): skip avatar lookups for hidden member badges 2026-05-31 03:21:21 +03:00
777genius
c02565b07d perf(renderer): skip unchanged kanban task cards 2026-05-31 03:19:31 +03:00
777genius
a491cd6c1c perf(renderer): narrow activity approval subscriptions 2026-05-31 03:12:21 +03:00
777genius
b6308ccb42 perf(renderer): defer message filter option work 2026-05-31 03:03:55 +03:00
777genius
808e5f73e4 perf(renderer): lazy mount closed menu controls 2026-05-31 02:59:56 +03:00
777genius
f06a50f859 perf(renderer): reduce sidebar task list render work 2026-05-31 02:55:14 +03:00
777genius
12c578a44d perf(renderer): mount team dialogs on demand 2026-05-31 02:42:48 +03:00
777genius
b6139d8558 perf(renderer): skip unchanged project task groups 2026-05-31 02:36:13 +03:00
777genius
fd3137237d perf(renderer): memoize project task groups 2026-05-31 02:32:59 +03:00
777genius
ee5554e59d perf(renderer): stabilize kanban board handlers 2026-05-31 02:27:30 +03:00
777genius
9376416b50 perf(renderer): memoize global task rows 2026-05-31 02:22:43 +03:00
777genius
64d2bae98d perf(renderer): memoize member card row controls 2026-05-31 02:14:32 +03:00
777genius
a5444f3240 perf(renderer): defer inactive messages panel branches 2026-05-31 02:07:52 +03:00
777genius
482105a94c perf(renderer): memoize kanban task card actions 2026-05-31 02:02:53 +03:00
777genius
93b53dbeb2 perf(renderer): lazy render unread comment tooltip 2026-05-31 01:55:00 +03:00
777genius
2d8966a6a6 perf(renderer): reduce team page render work 2026-05-31 01:47:27 +03:00
777genius
38ea035fb5 perf(renderer): lazy render task tooltip content 2026-05-31 01:47:27 +03:00
777genius
c7af5cd891 perf(renderer): reduce team page render work 2026-05-31 01:45:57 +03:00
777genius
b8e1958db8 perf(renderer): lazy render task tooltip content 2026-05-31 01:39:57 +03:00
iliya
a7a732e226 fix(team): guard runtime process row cache invalidation 2026-05-31 01:39:39 +03:00
777genius
b688800d57 perf(main): cache live runtime process table reads 2026-05-31 01:24:48 +03:00
iliya
0296c68a4d fix(ci): resolve validate lint errors 2026-05-31 01:22:47 +03:00
777genius
601d02fd45 perf(main): cache live runtime process table reads 2026-05-31 01:17:53 +03:00
777genius
027623c8d1 perf(renderer): avoid timer sync on telemetry-only updates 2026-05-31 00:54:17 +03:00
777genius
6b08e0d1a7 perf(renderer): batch visible message read updates 2026-05-31 00:48:26 +03:00
777genius
e5f2c262e8 perf(renderer): memoize global task rows 2026-05-31 00:40:24 +03:00
777genius
7de2da23d4 perf(renderer): defer member telemetry sparklines 2026-05-31 00:33:46 +03:00
777genius
21ef4e406e Merge remote-tracking branch 'origin/perf/team-page-lag-optimization' into perf/team-page-lag-optimization 2026-05-31 00:27:03 +03:00
777genius
ab8ed5e378 perf(main): reduce bootstrap transcript context scans 2026-05-31 00:26:02 +03:00
777genius
2f0abb430c perf(renderer): share unchanged global tasks 2026-05-31 00:20:34 +03:00
iliya
76299a4e44 fix(team): align runtime telemetry tests with process rows 2026-05-31 00:14:16 +03:00
777genius
e90886316f perf(main): cache runtime resource telemetry 2026-05-30 23:59:56 +03:00
777genius
172ddad18a perf(main): reuse task snapshots for projections 2026-05-30 23:30:39 +03:00
777genius
b32cc59b46 perf(main): avoid repeated lead session tail scans 2026-05-30 23:21:42 +03:00
777genius
4b5a49e6e8 perf(main): share lead session tail reads 2026-05-30 23:19:15 +03:00
777genius
f4f42e2ca4 perf(main): avoid full team scans for global tasks 2026-05-30 23:14:42 +03:00
777genius
933bf9532d perf(main): reuse worker cached summaries 2026-05-30 23:05:02 +03:00
777genius
8f1e223d61 perf(renderer): slow task refreshes during launch 2026-05-30 22:57:41 +03:00
777genius
c2ab7a7ff4 perf(main): skip unchanged task resume locks 2026-05-30 22:47:52 +03:00
777genius
7ea57cb012 perf(renderer): defer task project scans 2026-05-30 22:33:17 +03:00
777genius
1f46a14a79 perf(main): trim runtime process liveness scans 2026-05-30 22:14:52 +03:00
777genius
4575255c28 perf(main): skip redundant task interval resume scans 2026-05-30 22:07:24 +03:00
777genius
e7d7b3014e perf(main): reduce runtime launch metadata work 2026-05-30 21:52:36 +03:00
777genius
9f8fc6895a fix(renderer): use context menu open change signal 2026-05-30 21:02:51 +03:00
777genius
b8a53dcc09 perf(renderer): reduce member card render work 2026-05-30 20:58:31 +03:00
777genius
60d806135c perf(renderer): lazy mount task context menus 2026-05-30 20:54:22 +03:00
777genius
2c13516d9f perf(renderer): lazy render member hover cards 2026-05-30 20:50:17 +03:00
777genius
d59865f300 perf(team): reduce runtime telemetry polling 2026-05-30 20:03:45 +03:00
777genius
b13ee56359 perf(team): cap global task projections earlier 2026-05-30 18:57:45 +03:00
777genius
304d0a5ef1 perf(team): avoid redundant task cache clone 2026-05-30 18:48:43 +03:00
777genius
7be9158eb3 fix(team): prevent composer recipient overflow 2026-05-30 18:46:21 +03:00
777genius
a7606032fc fix(runtime): preserve provider status during refresh failures 2026-05-30 18:44:31 +03:00
777genius
a06423a574 fix(team): preserve live overlay in worker message pages 2026-05-30 18:44:12 +03:00
777genius
180bdb7575 perf(team): cache transcript affinity verdicts 2026-05-30 18:39:16 +03:00
777genius
0a8fbc9801 fix: avoid render-time ref access in height reveal 2026-05-30 18:02:19 +03:00
777genius
1ebeba8f6e fix: satisfy lint after performance fixes 2026-05-30 17:43:08 +03:00
777genius
9ed1988346 fix: refresh watch scope on provider fallback 2026-05-30 17:34:05 +03:00
777genius
06036460e9 fix: keep watch scope safe on provider errors 2026-05-30 17:11:31 +03:00
777genius
3b7b5dfd75 fix: preserve file lock acquire errors 2026-05-30 17:08:29 +03:00
777genius
a18009cc0f fix: keep created teams in watch scope 2026-05-30 16:51:47 +03:00
777genius
1af8dd638b docs: normalize jsonl reader comment punctuation 2026-05-30 16:07:44 +03:00
777genius
8cb44cd793 perf: replace readline with a chunked line generator in team JSONL readers
readline.createInterface runs an expensive Unicode line-break regex + extra
stream/string-decoder machinery per chunk. The main transcript parser (parseJsonlStream)
already uses a buffer + manual newline split; these per-team readers still used readline.

Add readJsonlLines(): an async generator that yields a JSONL file's lines via a chunked
utf8 stream read + a plain '\n' split (drop-in for 'for await (const line of rl)'), so the
consumers' loop bodies are unchanged. Stream is utf8-decoded before splitting, so multi-byte
chars across chunk boundaries are safe; trailing CR (CRLF) is stripped; empty lines and a
final newline-less line are yielded, matching readline; breaking out of the loop destroys
the stream via the generator's finally.

Adopt it in MemberStatsComputer, TaskBoundaryParser, and FileContentResolver (file-history
scan). Behavior-identical (their existing tests pass: 18 + 6 + 12) plus 6 new tests for the
generator (CRLF, empty lines, no-trailing-newline, early break, multi-byte chunk boundary).

Note: session-browser readline paths (jsonl metadata extractor, metadataExtraction,
SessionContentFilter) are off the launch path and left as-is for now.
2026-05-30 15:58:09 +03:00
777genius
127d31ba88 perf: cache unchanged team task reads 2026-05-30 15:51:15 +03:00
777genius
61e2678a5d perf: cache team transcript head metadata 2026-05-30 15:26:09 +03:00
777genius
0a750a9fa8 perf: share a frozen team-summary snapshot instead of cloning on every listTeams
listTeams() deep-cloned ALL team summaries via structuredClone on every call -- even
cache hits and concurrent in-flight awaiters. A heap allocation sample of a launch
put this (listTeams -> cloneTeamSummaries -> structuredClone) as the single largest
memory allocator, driving heap churn + GC pressure during launch (this stand has ~158
teams, and listTeams is called constantly: startup, notification init, task projection,
IPC polls, provisioning).

Build ONE deep-frozen, independent snapshot per uncached load and hand the same
reference to the cache entry, in-flight awaiters, and every later reader. The single
cloneTeamSummaries keeps it independent of any cached config the loader returns;
freezing lets all readers share it safely. Audited every listTeams consumer -- all
iterate / map / filter / serialize, none mutate -- and the freeze turns any stray
future mutation into a loud error rather than silent cross-caller corruption.

TeamConfigReader 26/26 (added a frozen + same-reference regression test), and the
listTeams consumers (TeamDataService 116, CrossTeamService 26) all pass under frozen
summaries.
2026-05-30 15:25:26 +03:00
777genius
58dfac8377 fix: preserve runtime rss fallback when process table misses roots 2026-05-30 15:16:03 +03:00
777genius
f0797e2c12 perf: replace readline with a bounded chunked read in the affinity head scan
fileBelongsToTeam streamed the head window via createReadStream + readline. readline's
line iterator runs an expensive Unicode line-break regex and stream/string-decoder
machinery per chunk, which showed up as a top main-thread cost during launch (the line-
split regex alone was ~5.7% in the warm launch profile).

Replace it with a bounded chunked fs.read + a plain '\n' split. JSONL is strictly
newline-delimited and each line is trim()'d (so a trailing CR from CRLF is dropped),
so a '\n' split is cheaper and more correct (it will not split on a bare CR or a
Unicode line/paragraph separator inside a JSON string value, which readline would). A
StringDecoder preserves multi-byte UTF-8 sequences that straddle a chunk boundary.

Byte-identical semantics to the old loop: inspect up to TEAM_AFFINITY_SCAN_LINES
non-empty lines, first match wins via early break, and a final line is honored even
without a trailing newline. Reads in 64KB chunks so a team decided in its first lines
is not penalized by a huge file. Adds tests for CRLF endings + no-trailing-newline,
a multi-byte char straddling the 64KB boundary, and the 40-line window bound (21 pass).
2026-05-30 14:54:58 +03:00
777genius
5c1d2e8d92 perf: memoize bootstrap failure-reason per parsed line across members
readRecentBootstrapTranscriptOutcome ran extractBootstrapFailureReason (regex +
optional JSON.parse + ~40 substring scans per call) for every candidate line, once
per team member: an anonymous transcript line (no agentName) passes the per-member
filter for ALL members, so an N-member team re-extracted the same line's failure
reason N times per scan -- a top main-thread cost in the warm launch profile (~5.4%
with isBootstrapInstructionPrompt).

Memoize the result on the shared parsed-tail line (parsedBootstrapTranscriptTailCache
already reuses the same line objects across members and re-scans while the file is
unchanged). The compute stays LAZY inside the newest-first candidate loop, so each
line is extracted at most once across all members AND lines past the first match are
never extracted -- preserving the early-break that an eager precompute would lose.
The memo is keyed implicitly by the line's cache entry (filePath + mtime + size); a
file change re-parses into fresh line objects, so it cannot drift from the line text.

Pure-function memoization: byte-identical input (candidate.text === parsedLine.text)
-> identical output, so failure/success/null outcomes and reasons are unchanged.
Bootstrap-transcript outcome tests pass (306), no behavior change.
2026-05-30 14:34:57 +03:00