Xeo Forge v1.24.0 — Local-First Agent Workbench
Xeo Forge v1.24.0 — The Reinforced Frame
The structure release: no new behavior was promised, so none was shipped — instead the three largest files in the codebase (1,917 + 1,476 + 1,091 lines) were decomposed into named, guarded, single-purpose modules, with the full test suite pinning behavior unchanged at every step. The governing law held throughout: test first → split → verify.
The three decompositions (all moves verbatim)
- The agent loop (
lib/agent/loop.ts1,917 → 1,620): five concerns moved verbatim intolib/agent/run/—protocol.ts(run protocol types + event contracts),model-client.ts(provider call/retry plumbing),language.ts(run-message language),memory.ts(memory candidates incl.persistMemoryCandidates),tool-bridge.ts(tool dispatch bridging). Contract tests re-pinned double-sidedly (definition site + call sites,definitionSites.length === 1) so duplication cannot silently return. - The DB query package (
lib/db/queries.ts1,476 → a 28-line pure re-export facade): the repo's ONLY application-table writer now lives in 9 domain modules (users, tasks, events, admin, credits, uploads, context, profiles, providers) plus a package-privateshared.ts. All 53 import sites stay untouched —@/lib/db/queriesremains the only sanctioned path — and the one cross-domain dependency (tasks → profiles) is wired explicitly.test/db-queries-structure.test.ts(7 assertions) freezes the export surface, forbids deep imports and facade SQL, and pins exactly-one definition site per function. - The work surface (
app/work/WorkClient.tsx1,091 → 216): 7 hooks + 7 components moved verbatim (useWorkRunState,useWorkspaceDiff,useGitStatus,useWorkDerived,useWorkActions,useDecisionCountdown,usePendingMemory;WorkRunPane,WorkGovernanceRail,WorkCenterHeader,WorkSecondaryTabs,WorkDiffTab,WorkRunList,WorkComposer). The DiffSink identity is memoized so the SSE subscription happens once per task, never per render — the resubscribe regression class is designed out, not just re-tested.
Dead surface removed
app/work/WorkIntake.tsx (438 lines) is gone, per maintainer decision. A comprehensive grep proved zero production importers: the /work route redirects to /chat, and the live demo entry lives in UnifiedWorkspace (POST /api/demo → /work/<id>?demo=1) — WorkIntake was a dead duplicate of that flow. Only its source-reading test pins were removed with it (3 assertions); the four live demo-contract blocks stay, and the historical release records that mention it stay untouched. Icon hygiene was checked (all 4 imported icons remain used elsewhere). Evidence: Phase 1.5 of the audit document below.
New behavior evidence (the suite that makes future change safe)
test/run-agent-behavior.test.ts— 6 end-to-end scenarios through a REAL database and REAL event emitter against a mock OpenAI-compatible SSE provider: chat finalize-on-first-text, native reasoning events, inline<think>extraction, build-mode evidence gate (a real tool call, not bookkeeping), honest 401 failure, and the<action>fallback path. Build tasks follow the real authorization path end to end (createTask planning → planned → approveTaskPlan → run with the row's approved plan).test/work-ingest.test.ts(7) + redirected double-sided contract pins for chat-hang H3, demo-replay pacer, cancellation, and ThinkingBlock.- Dead code was discovered and reported honestly during the README media refresh — disclosed first, deleted only on the maintainer's explicit call.
Docs that show, not tell
- README now leads with a real 17-second governed-run GIF (plan → approve → build → verify → memory, captured from the real app against a scripted provider) plus fresh dark-theme captures; the v1.15-era hero shot — which literally showed "Run failed — no global model is configured" with three failed tasks — is gone. The demo provider used for the capture ships in
scripts/so the recording is reproducible. AGENTS.mdlayout reflects the new architecture: the db/queries package + facade rule (enforced by the guard test), thelib/agent/run/primitives, and the app/work decomposition.docs/audits/2026-08-29-v124-structural-rework.mdrecords the whole rework phase-by-phase with commit hashes, before→after numbers, and honest scope boundaries.
Verification honesty
- Full vitest suite: 891/891 green across 50 files (866 pre-rework → 894 through the splits → 891 after removing the 3 dead-surface intake pins);
tsc --noEmitclean; ESLint clean on every touched file. CI is the canonical gate. - Every phase was pushed immediately after its commit; the dead-surface deletion went through grep evidence → full suite → documentation in exactly the order the maintainer specified.
Known gaps (carried honestly)
- Structure-only release: no behavior change is claimed anywhere, and the suite pins exactly that claim.
- The v1.23 project map counted 93 functions above the complexity-15 threshold; line-count decomposition addressed the three largest files, and the complexity debt inside the remaining functions (including
runAgent) was not systematically attacked. - The v1.23 known gaps carry forward unchanged: per-task permission overrides accepted but never supplied, GUI zone rules without a runtime consumer, the docker tier covering
code_executeonly, and read-only subagents.
Full rework evidence: docs/audits/2026-08-29-v124-structural-rework.md