Cutting the delay between "Enter" and the agent starting

KISS Sorcar — task-start latency optimization, validated end to end with screenshots and database timings. Development model: claude-fable-5; independent read-only review: gpt-5.6-sol.

The problem

When a user submits a task, Sorcar performs several git and setup operations before the agent's first step. Measured on the production database, the gap between submission (start_ts) and the agent's first event was 1.5–1.7 seconds on every task, and 8.2 seconds for the first task after a daemon restart.

Where the time went (measured, not guessed)

cProfile of a real end-to-end run plus targeted git timings on this repository:

Step on the submit pathCost
git worktree add (full checkout of the task's isolated worktree)0.86–1.0 s
First git reset --hard in a fresh worktree (index re-hash of every file)0.94 s (if used naively)
Orphan-worktree reclaim + sweep maintenance, git status~0.2 s
Lazy model-SDK imports on the first task (KISSAgent._reset)0.3–6 s (cold)

The fix

  1. Spare worktree pool (src/kiss/agents/sorcar/worktree_pool.py): while a task runs, a background thread pre-creates the next task's worktree and warms its index. At submit time the agent consumes the ready spare and only pays for a cheap git reset --hard onto the current branch tip, an untracked-file sweep, and the dirty-state copy. The orphan reclaim/sweep maintenance moved into the background refill too. If the pool is empty or the spare fails any validation, the code falls back to the exact pre-existing inline path.
  2. Startup import prewarm (_prewarm_task_dependencies in src/kiss/server/server.py): a daemon thread imports the lazily loaded model-SDK modules and warms the model registry at server startup, so the first task no longer pays for them.

Submit path: before vs after

BEFORE (every submit, ~1.6s before the agent starts) retire previous reclaim + sweep git worktree add (~0.9s) copy dirty state model/tool init agent ▶ AFTER (every submit, ~0.3s; heavy work runs in the background) take spare reset + clean (~0.1s) copy dirty state model init (prewarmed) agent ▶ background refill thread: reclaim + sweep + git worktree add + index warm → spare ready for the NEXT task Fallback: empty/invalid pool → the original inline path runs unchanged.
The expensive full checkout and the git maintenance passes moved off the user-visible submit path into a background refill.

Measured results (real server, real UI, real model)

An isolated RemoteAccessServer built from this change was driven through its real web UI (Playwright); timings below are from the server's own SQLite event log (submission timestamp vs the first agent event), model claude-fable-5:

Production baseline (steady state) 1.60 s This change — first task (cold pool) 1.98 s This change — steady state (warm pool) 0.33 s First task after daemon restart was 8.2 s (cold imports + cold git) → now ~2 s: imports prewarm at startup, git warms on the first task
Submit → first agent event. Bars scaled to 300 px/s. Steady state improves ~5× (1.6 s → 0.33 s); every task after the first in a repo takes the fast path.
ScenarioBeforeAfter
Steady state (task N>1 in a repo)1.5–1.7 s0.17–0.33 s
First task in a repo / after restart1.6–8.2 s~2 s

Screenshot evidence

Web UI loaded before submission
1 — The Sorcar web UI served by the modified server, before submission.
First task running (cold pool)
2 — Task 1 (cold pool): agent started 1.98 s after submit; this run also fills the pool in the background.
Second task running (warm pool)
3 — Task 2 (warm pool): agent started 0.33 s after submit.
Second task finished
4 — Task 2 finished normally; merge/auto-commit flows are unchanged.

Safety: independent review and hardening

A read-only review by gpt-5.6-sol (instructed to report only substantiated problems) found 1 high, 2 medium and 2 low issues — all fixed and covered by new tests:

Verification

The pool leaves one idle kiss/wt-* branch per repository between tasks. It is contentless, marked, excluded from all maintenance while the daemon owns it, and automatically discarded by the next reclaim pass if the daemon dies. Background refills can be disabled with KISS_DISABLE_WORKTREE_POOL=1.