Commit graph

617 commits

Author SHA1 Message Date
777genius
f4f42e2ca4 perf(main): avoid full team scans for global tasks 2026-05-30 23:14:42 +03:00
777genius
c2ab7a7ff4 perf(main): skip unchanged task resume locks 2026-05-30 22:47:52 +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
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
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
3b7b5dfd75 fix: preserve file lock acquire errors 2026-05-30 17:08:29 +03:00
777genius
d43cd3a0db test: sort team config reader imports 2026-05-30 16:06:01 +03:00
777genius
92f1000a4f test: cover transcript head metadata cache 2026-05-30 15:51:59 +03:00
777genius
127d31ba88 perf: cache unchanged team task reads 2026-05-30 15:51:15 +03:00
777genius
28a55416ca test: isolate runtime usage stubs from process table 2026-05-30 15:46:27 +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
776298b0e3 perf: reuse caller stat in fileBelongsToTeam, drop duplicate fs.stat
On the live resolution path collectRootJsonlSessionIds already stat()s each root
jsonl for its mtime-window filter, then fileBelongsToTeam stat()ed the very same
file again for its cache validation -- two fs.stat syscalls (plus two Stats
allocations) per file, every poll. fileBelongsToTeam now takes an optional
precomputed stat and the mtime-filter caller passes the stat it already has, so the
file is statted once. Measured 20 files -> 20 stat calls on the mtime path (was ~40).

Using a single stat snapshot is also slightly more consistent than two reads that
could straddle a concurrent write. The other call site (subagent scan) passes no
stat and is unchanged (fileBelongsToTeam stats it itself). Adds a regression test
that a caller-supplied stat is the one recorded in the affinity cache.
2026-05-30 14:11:58 +03:00
777genius
c8d40be460 perf: cache negative team-affinity verdicts from a full head window
fileBelongsToTeam only cached POSITIVE affinity durably; a negative verdict was
re-decided on any change, so during a launch every non-matching transcript in the
project dir that grew (mtime+size change from an active session) was re-streamed
(createReadStream+readline) and re-parsed (up to 40 head lines) on every bootstrap
poll. A live atlas-hq-5 launch profile put this whole subsystem (readline streaming
+ fileBelongsToTeam + line/team matching) at ~31% of main-thread JS, the single
largest launch cost.

A team's first 40 head lines are immutable for an append-only transcript, so a
`false` decided from a FULL inspected window (>= TEAM_AFFINITY_SCAN_LINES) stays
valid while the file only grows. Track headWindowFull on the cache entry and short-
circuit such negatives the same way positives are short-circuited (size >= cached).
Short files (partial window) are still re-scanned on growth, so a team mention that
later lands inside the head window is still detected. A shrink/rewrite (size <
cached) forces a re-scan, identical to the positive path.

Behavior-preserving for affinity correctness (no new false negatives); only removes
redundant re-streams. Adds regression tests for both the durable-negative and the
short-file-flips-to-true cases.
2026-05-30 13:17:49 +03:00
777genius
126a485477 wip: team messages panel updates and runtime usage cache refinements
Checkpoint of in-progress work:
- renderer: team messages panel/composer, messagesPanelLogic, teamSlice,
  AnimatedHeightReveal plus their tests
- main: runtime process usage-stats caching (ignoreCachedMisses, bounded
  eviction), alive-run-id helpers, team watch-scope notify wiring

Note: the getTeamAgentRuntimeSnapshot rssBytes expectation in
TeamAgentLaunchMatrix.safe-e2e is environment-dependent and still red.
2026-05-30 12:54:11 +03:00
777genius
f79ea145d7 perf: batch per-member task-interval resume into one locked pass
During launch the live-status loop resumes every alive member every audit cycle.
resumeActiveIntervalsForMember runs a synchronous file-lock + full read of every
task file, so for an N-member team with M task files it did N locked passes x M
readFileSync per cycle (e.g. 6 members x 20 task files), blocking the main event
loop. Profiling a 6-member mixed launch showed mutateTeamTasks/withFileLockSync as
a top main-thread cost (~14%).

Add resumeActiveIntervalsForMembers that applies the identical per-member resume
logic against a member set in a single locked pass, and use it in the live-status
loop. Same mutations, but one lock + task read per cycle instead of one per member.
Adds a test covering multi-member resume in one pass.
2026-05-30 10:02:01 +03:00
777genius
35b76f1354 perf: share bootstrap transcript tail parse across members
During launch, the bootstrap-wait loop polls each member and, per member, re-read
and re-JSON.parsed the same growing transcript tail (readRecentBootstrapTranscriptOutcome
was the top main-thread JS hotspot at ~21% during bootstrap, ~40% with its helpers).
The same file was parsed once per member per poll.

Memoize the parsed tail by (filePath, mtime, size) in a shared cache so the file is
read + parsed once per change and reused across all members. The per-member filter
and failure/success scan is byte-for-byte the same logic; only the redundant read +
JSON.parse is removed. Cache is bounded (LRU, same cap as the outcome cache) and
invalidated on mtime/size change, matching the existing outcome cache semantics.

Adds a test asserting the tail is parsed once and shared while per-member outcome
detection is unchanged.
2026-05-30 01:05:54 +03:00
777genius
b4b9175287 perf: reuse team summary for comment notification init 2026-05-29 15:43:24 +03:00
777genius
f0514a7d17 perf: skip unverifiable runtime process scans 2026-05-29 14:38:01 +03:00
777genius
9be096f864 perf: cache persisted bootstrap outcome lookups 2026-05-29 14:19:04 +03:00
777genius
d0c6fdd28c perf: extend persisted runtime probe cache 2026-05-29 14:04:28 +03:00
777genius
35a9b05637 perf: cache persisted spawn status reads 2026-05-29 13:06:26 +03:00
777genius
fa242d9ff6 perf: cache bootstrap transcript outcomes 2026-05-29 12:58:15 +03:00
777genius
0b97985474 perf: cache team transcript affinity checks 2026-05-29 12:46:29 +03:00
777genius
169ac8bb68 perf: include process table usage metrics 2026-05-29 12:34:13 +03:00
777genius
3b0c2ed24b perf: cache runtime usage telemetry 2026-05-29 12:29:37 +03:00
777genius
7d21f9bd76 perf: avoid stale runtime pid sampling 2026-05-29 12:26:15 +03:00
infiniti
0cbba46083
fix(team): speed up provider runtime preflight 2026-05-27 23:54:10 +03:00
777genius
77e08af03f fix(team): propagate managed runtime settings env 2026-05-27 18:56:24 +03:00
777genius
7cc1a59bbc fix(team): preserve mixed provider runtime settings 2026-05-27 18:22:10 +03:00
infiniti
ebcc0e717f
fix(team): reconcile provisioned-but-not-alive bootstrap state 2026-05-27 12:16:41 +03:00
Илия
3849c01955
fix(provenance): classify synthetic user turns
* fix(provenance): classify synthetic user turns

* fix(provenance): keep assistant display rendering intact

* fix(provenance): preserve source tool result rows
2026-05-26 23:51:17 +03:00
777genius
ab6ab1fc4c test(team): cover provisioned runtime recovery 2026-05-26 23:44:40 +03:00
777genius
c79b7d4234 fix(team): suppress unverified relay state claims 2026-05-26 23:44:40 +03:00
777genius
f237318c29 fix(agent-teams): surface OpenCode runtime permissions 2026-05-26 19:46:24 +03:00
777genius
636beb5e42 fix(scripts): quote Windows shell invocations 2026-05-26 19:46:13 +03:00
777genius
58a0eb603d build(runtime): require Node 24 toolchain 2026-05-26 19:44:23 +03:00
777genius
b5d7da1ea8 fix(attachments): support claude gif delivery 2026-05-25 23:43:29 +03:00
777genius
63e16d1043 fix(workspace-trust): canonicalize git worktree trust roots 2026-05-25 21:30:56 +03:00
777genius
c033a0cb87 fix(team): persist incomplete launch state before cleanup 2026-05-25 14:53:05 +03:00
infiniti
2b3a184bef
fix(opencode): recover empty bridge output sends
* fix(opencode): handle empty readiness bridge output

* fix(opencode): retry read-only bridge no-output

* fix(opencode): recover empty bridge output sends

---------

Co-authored-by: iliya <iliyazelenkog@gmail.com>
2026-05-25 00:41:54 +03:00
777genius
1bc8ccc07a fix(ci): restore workspace validation 2026-05-25 00:14:43 +03:00
infiniti
50f876f863
fix(opencode): retry read-only bridge no-output
* fix(opencode): handle empty readiness bridge output

* fix(opencode): retry read-only bridge no-output

---------

Co-authored-by: iliya <iliyazelenkog@gmail.com>
2026-05-24 23:22:34 +03:00