plans/agent-manager-git-poller-remaining.md
The implementation is ready for merge from the code and validation perspective. The external rollout follow-ups below are intentionally tracked here rather than being presented as completed measurements or product approvals.
The current worktree contains:
The production runtime has one polling implementation. Temporary benchmark code, Git command observers, batched ahead/behind, and alternate merge-base paths were removed after measurement showed they did not materially improve the dominant steady-state workload.
Expected implementation files:
packages/kilo-vscode/src/agent-manager/git-stats-snapshot.tspackages/kilo-vscode/src/agent-manager/GitStatsPoller.tspackages/kilo-vscode/src/agent-manager/project/pollers.tspackages/kilo-vscode/src/agent-manager/AgentManagerProvider.tspackages/kilo-vscode/src/KiloProvider.tspackages/kilo-vscode/tests/unit/git-stats-snapshot.test.tspackages/kilo-vscode/tests/unit/git-stats-poller.test.ts.changeset/calm-agent-manager-git-polling.mdplans/agent-manager-git-poller-optimization.mdNo benchmark implementation or profiling instrumentation should be committed.
The latest minimized implementation passed:
222 focused and Agent Manager architecture tests,knip,check-kilocode-change,git diff --check.Manual isolated VS Code verification also passed for local stats:
9 files, +1340, -82.10 files, +1341,
-82 within one visible poll.9 files, +1340, -82 within one poll.The temporary file was removed and is not in the working tree.
These measurements used read-only Git commands against the same linked worktrees. They did not change worktree contents or Git metadata.
On 52 linked Kilo worktrees:
Required cache phases on 40 comparable worktrees:
200 to 41, a 79.5% reduction,3.54s to 2.75s, a 22.1% reduction.Final steady-state policy, scanning 20 dirty worktrees, six clean worktrees, and the local checkout:
| Metric | Previous full poll | Optimized steady state | Change |
|---|---|---|---|
| Wall time | 10.63s | 1.42s | -86.6% |
| User CPU | 20.61s | 0.59s | -97.1% |
| System CPU | 35.88s | 11.54s | -67.8% |
| Combined CPU | 56.49s | 12.13s | -78.5% |
| Involuntary context switches | 411,914 | 188,273 | -54.3% |
The filesystem cache was warm and /usr/bin/time reported zero block-input
operations, so this comparison does not establish a reliable disk-read
reduction.
A disposable fixture repository was created under the approved temp directory with:
wt-01 selected.Matched 35-second self-test profiles were captured from a committed baseline extension and the optimized extension. Both profiles had no trace data loss.
| Metric | Baseline | Optimized | Change |
|---|---|---|---|
| Distinct Git PIDs observed at 10 Hz | 59 | 53 | -10.2% |
| Longest renderer task | 70.42ms | 68.81ms | -2.3% |
| Renderer task duration | 98.46ms | 94.42ms | -4.1% |
The renderer results are expected to be small because Git polling runs in the extension host, not the webview renderer. PID sampling undercounts short-lived processes and is useful only as supporting evidence.
Matched 30-second windows were captured from the same disposable fixture after validating 40 worktree cards in both runs. Both traces had no data loss. The temporary GitOps hook recorded every Git command from the extension host.
| Metric | Baseline | Optimized | Change |
|---|---|---|---|
| GitOps command count | 1,994 | 466 | -76.6% |
| Cumulative Git command time | 42.16s | 13.62s | -67.7% |
merge-base commands | 389 | 43 | -88.9% |
diff --numstat commands | 389 | 43 | -88.9% |
ls-files --others commands | 389 | 0 | -100% |
rev-list --left-right --count commands | 389 | 43 | -88.9% |
The optimized run replaced the baseline's repeated command families with 285 porcelain-v2 status probes and 33 shared ref snapshots. The renderer remained near idle in both runs, with approximately 0.72 seconds of script work over the 30-second window.
Artifacts are temporary and currently live under:
/var/folders/6c/3j3r25ds6pd1dw3nlrfnvv280000gp/T/kilo/git-poller-profile.F0VLor
Do not add those artifacts to Git.
Do not cite the following as final evidence:
sessionsLoaded, so only the local card rendered.activeTarget.projectId used local:<path>
instead of projectIdFor(canonicalRoot).baseline-exact.tsv; it was discarded after the matched
final windows completed.This session does not have sudo access, so Falcon CPU could not be measured in a controlled before/after experiment.
Required managed-endpoint comparison:
FileAnalysisService, and FXPredictService.Target:
If Git workload drops but CrowdStrike does not, the remaining status scans are the likely floor. Do not add more cache layers without profiler evidence.
The implementation changes clean dormant-worktree freshness from five seconds to at most 30 seconds. This is timer-based polling, not filesystem events.
Current behavior:
This tradeoff needs explicit product approval. If all worktrees must retain five-second freshness, remove dormant sharding and keep only status fingerprints and exact-result caching. The direct measurements show that this leaves status scans as the dominant cost.
AgentManagerProvider keeps a busySessions set so worktrees with actively
working Kilo sessions remain hot. Session deletion and session.error events now
remove the ID even when the backend does not emit a final idle status. Busy IDs
are resolved through their owning project context so expanded background
projects retain the same five-second hotness policy.
The lifecycle review is complete:
The focused scheduler tests cover hot/dormant selection; provider lifecycle cleanup is handled by idle, deletion, error, panel-close, and project-switch paths.
Review the final diff after exact profiling and remove anything not justified by the data.
Specific review points:
GitStatsPoller.ts grew substantially. Extract only if it improves clarity
and remains within architecture caps; do not create generic abstractions.GitStatsSource exists as a narrow test seam and snapshot boundary. Confirm
no broader interface is needed.semaphore remains an existing option but is not consumed directly by the
poller. Do not add another semaphore layer.local-diff.ts and review/detail behavior unchanged.plans/agent-manager-git-poller-optimization.md so its final design and
measured outcome match the minimized implementation. Remove stale proposed
phases that were explicitly discarded.After the last code change, rerun from packages/kilo-vscode/:
bun run formatbun run lintbun run check-typesbun run check-types:webviewbun run bundlebun run knipbun run check-kilocode-changeFrom repository root:
bun run script/check-md-table-padding.tsgit diff --checkAlso rerun the isolated UI mutation check for local stats after the final build.
All profiling worktrees and state used for the valid profiles were created in a disposable temp fixture. They did not reference real managed worktree paths.
The original real-checkout guard became invalid because the main checkout changed concurrently during profiling:
b135b4e to efbae40,packages/opencode/package.json changed,bun.lock and changeset changes remained.Those changes were not reverted or modified by this work. Because the baseline changed concurrently, establish a fresh guard immediately before any remaining profile and compare it immediately afterward.
The guard should include:
.kilo/agent-manager.json,.git/info/exclude,.git/worktrees/*/gitdir,git worktree list --porcelain,Abort and investigate if the guard changes. Never revert concurrent user or agent changes.
These are rollout or product follow-ups, not untracked implementation work:
Do not merge if any of these remain true: