You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Server trace log volume makes it Defender's top scanned file on Windows and rotates history out in about two hours #28196
On Windows, the server trace log is written often enough that it becomes the top file for Microsoft Defender real-time scanning. The write volume also rotates diagnostics out within about two hours. Much of the volume comes from small routine spans.
Environment
T3 Code (Beta) desktop 0.1.5.0 on Windows 11 (build 26200), ThinkPad T490s, i5-8365U, 16 GB RAM
A few active agent threads, normal daily use
Measurements
Write rate. All 11 server.trace.ndjson* files were about 10 MiB each, and their timestamps ran from 10:28 to 12:36. That is about 0.75 MiB/min, with some rotations only 8 minutes apart. A separate 20-second check saw the file's modified time change 14 times.
Defender cost. I took one 60-second New-MpPerformanceRecording during light use:
File
Scans
Total scan time
.t3\userdata\logs\server.trace.ndjson
38
336 ms
Everything else in the top extensions
about 200
about 400 ms
The absolute cost in this sample is small, and it is one sample. It shows the pattern: Defender rescans the file as it is rewritten, so the cost scales with flush frequency. Over 48 hours on this machine, Defender averaged 4.2% of total CPU and was at or above 10% for 14% of awake time. I can't attribute that total to T3 Code, because other apps were active too.
Span mix. Top spans in one rotated file (17,454 records in 10.4 MiB):
Same two-hour window on macOS. These are bytes by span family from 113 MB of server.trace (all 11 files, 112 minutes) on 0.1.7-nightly.20261102.4093, macOS 27.2:
A second capture on the same Mac later that day also covered 111 minutes.
On another Mac, 63% of server.trace bytes (107 MB over 2 h 10 min) were otlp-span records forwarded from the web client (service.runtime: t3-web). Most had durationMs: 0. The top ones were EnvironmentThreadState.applyEventsLocked (5,711) and applyItems (5,673), then EnvironmentRegistry.getEntry, withLeaseLock and acquireSupervisor (4,456 each), and EnvironmentRpc.request, authorize and currentSession (3,877 each). The EnvironmentRegistry rows in your table come from packages/client-runtime too, so they are probably the same forwarding. #26511 stopped tracing unchanged platform registrations, but these spans are still sent.
I opened #29757 (skill discovery resolves each repository root once) and #29758 (stop tracing per-event coalescer work) for two of the rows above.
Update from the same Mac on today's 0.1.8 nightlies (macOS 27.2). The repo-root and coalescer rows from my table above are gone after #29757 and #29758. Retention is still short while agents are working. Two captures today covered 68 minutes at about 96 MB an hour, and 47 minutes at about 144 MB an hour.
The 47-minute capture, per hour:
Span family
Per hour
Share
sqlite
43.9 MB
30%
sql.transaction + BEGIN + COMMIT
23.2 MB
16%
runGitCommand
6.7 MB
5%
GitManager.rememberPrLookupGitState
5.8 MB
4%
GitVcsDriver.readConfigValue
3.2 MB
2%
PortDiscovery.*
1.8 MB
1%
The SQL rows are 46% of the file. That's about 60k sqlite spans and 48k transaction spans an hour. db.query.text is only 28% of the sqlite span bytes, so the span count is the bigger lever.
I opened #31147 for the rememberPrLookupGitState row.
Where the SQL rows come from, from a T3-based desktop build at upstream 44ebb2f (Nov 10), macOS. 114 MB of server.trace.ndjson over 93 minutes with agent threads streaming:
Source of sqlite / sql.transaction / BEGIN / COMMIT spans
Shell stream reads.projectShellItems re-reads the changed threads' shells for every event batch (50 ms window) and for every shell subscriber, so open windows multiply it: getShellSnapshot({ threadIds }) when several threads changed, getThreadShell for one thread or when the batch read fails. In this capture almost all were the single-thread path (3,052 getThreadShell for 3,063 projectShellItems). ProjectionStore.getThreadShell walks the parent chain with one SELECT per ancestor, then up to five batch reads, inside a read transaction, and every statement gets a span; one getThreadShell plus one getShellSnapshot for a two-thread family wrote 19 spans in a test. Turning tracing off inside these reads, as EventSink.write does since #19430, is the obvious fix, but ProjectionStore.test.ts observes their SQL through spans (traceSqlStatements for shell query shape, traceSqlRouting for reader routing), so it needs a maintainer call on how those tests observe SQL.
Provider batch commits. 57% of the 8,431 EventSink.providerBatch spans had event_count: 0 and still opened a writer transaction (sql.transaction → BEGIN → COMMIT). Snapshot work enters commit(work) (ProviderCommitBatch.ts) and withProviderBatch opens the transaction before routing and assistant-text filtering decide, inside the work, to hold or drop the snapshot (RunExecutionService.ts). Held text that only waits for an idle flush still pays for a transaction and its spans. Skipping on event_count === 0 after the fact isn't safe: held text can still allocate a turn item position, and writeWithEffects can enqueue outbox effects without events. It would need the hold/drop decision made, in ingestion order, before the transaction opens.
Measured from the retained rotations with a span-name/parent-chain count; happy to share the script.
Activity
onlydole commentedon Nov 3, 2026
Same two-hour window on macOS. These are bytes by span family from 113 MB of server.trace (all 11 files, 112 minutes) on 0.1.7-nightly.20261102.4093, macOS 27.2:
sqlitefindRepositoryRoot+findPluginRepositoryRootThreadLiveEventCoalescer(flushPending, cancelWindow, offerAll)sql.transactionPortDiscovery(six span names)runGitCommandGitManager.rememberPrLookupGitStateWorkspacePaths.resolveRelativePathWithinRootA second capture on the same Mac later that day also covered 111 minutes.
On another Mac, 63% of server.trace bytes (107 MB over 2 h 10 min) were
otlp-spanrecords forwarded from the web client (service.runtime: t3-web). Most haddurationMs: 0. The top ones wereEnvironmentThreadState.applyEventsLocked(5,711) andapplyItems(5,673), thenEnvironmentRegistry.getEntry,withLeaseLockandacquireSupervisor(4,456 each), andEnvironmentRpc.request,authorizeandcurrentSession(3,877 each). TheEnvironmentRegistryrows in your table come frompackages/client-runtimetoo, so they are probably the same forwarding. #26511 stopped tracing unchanged platform registrations, but these spans are still sent.I opened #29757 (skill discovery resolves each repository root once) and #29758 (stop tracing per-event coalescer work) for two of the rows above.
onlydole commentedon Nov 4, 2026
Update from the same Mac on today's 0.1.8 nightlies (macOS 27.2). The repo-root and coalescer rows from my table above are gone after #29757 and #29758. Retention is still short while agents are working. Two captures today covered 68 minutes at about 96 MB an hour, and 47 minutes at about 144 MB an hour.
The 47-minute capture, per hour:
sqlitesql.transaction+BEGIN+COMMITrunGitCommandGitManager.rememberPrLookupGitStateGitVcsDriver.readConfigValuePortDiscovery.*The SQL rows are 46% of the file. That's about 60k
sqlitespans and 48k transaction spans an hour.db.query.textis only 28% of thesqlitespan bytes, so the span count is the bigger lever.I opened #31147 for the
rememberPrLookupGitStaterow.yaacovcorcos commentedon Nov 11, 2026
Where the SQL rows come from, from a T3-based desktop build at upstream 44ebb2f (Nov 10), macOS. 114 MB of
server.trace.ndjsonover 93 minutes with agent threads streaming:sqlite/sql.transaction/BEGIN/COMMITspansws.orchestrationV2.projectShellItems→OrchestratorV2.getThreadShellProviderCommitBatch.flush→EventSink.providerBatchShell stream reads.
projectShellItemsre-reads the changed threads' shells for every event batch (50 ms window) and for every shell subscriber, so open windows multiply it:getShellSnapshot({ threadIds })when several threads changed,getThreadShellfor one thread or when the batch read fails. In this capture almost all were the single-thread path (3,052getThreadShellfor 3,063projectShellItems).ProjectionStore.getThreadShellwalks the parent chain with one SELECT per ancestor, then up to five batch reads, inside a read transaction, and every statement gets a span; onegetThreadShellplus onegetShellSnapshotfor a two-thread family wrote 19 spans in a test. Turning tracing off inside these reads, asEventSink.writedoes since #19430, is the obvious fix, butProjectionStore.test.tsobserves their SQL through spans (traceSqlStatementsfor shell query shape,traceSqlRoutingfor reader routing), so it needs a maintainer call on how those tests observe SQL.Provider batch commits. 57% of the 8,431
EventSink.providerBatchspans hadevent_count: 0and still opened a writer transaction (sql.transaction→BEGIN→COMMIT). Snapshot work enterscommit(work)(ProviderCommitBatch.ts) andwithProviderBatchopens the transaction before routing and assistant-text filtering decide, inside the work, to hold or drop the snapshot (RunExecutionService.ts). Held text that only waits for an idle flush still pays for a transaction and its spans. Skipping onevent_count === 0after the fact isn't safe: held text can still allocate a turn item position, andwriteWithEffectscan enqueue outbox effects without events. It would need the hold/drop decision made, in ingestion order, before the transaction opens.Measured from the retained rotations with a span-name/parent-chain count; happy to share the script.
fix(server): trace file skips every fast successful span
fix(server): trace file counts fast spans instead of dropping them