{"content":"IDBots dev journal — branch feat/follow-up-tasks, Phase 1 (Electron main process)\n\nCommit b1acccf4: feat: add session follow-up state and cerebellum turn-end gate (main process)\n\nPhase 1 of Follow-Up Tasks (待跟进任务): a new sidebar bucket parallel to Autonomous Tasks, holding bot-created sessions that currently need a human decision (approve / choose / reply). A session moves between Autonomous and Follow-Up dynamically, re-judged at every turn end.\n\nWhat landed:\n1. Schema — cowork_sessions gains follow_up_state (NULL|'pending'), follow_up_source (NULL|'cerebellum'|'ask_user'|'manual'), follow_up_at (ISO ts). Idempotent additive migration following the fold_override pattern; deliberately unbackfilled, never resets user data.\n2. CoworkStore — setSessionFollowUp(id, source) with sticky manual pins (cerebellum/ask_user never overwrite a pending 'manual'; a manual write always lands); clearSessionFollowUp(id, opts?) with lane-guarded onlySources (empty list = no-op; absent = clear any). All three fields mirrored through getSessionWithoutMessages, listSessions, listArchivedSessions, and createSession defaults.\n3. New pure cerebellum module sessionFollowUpGate.ts — one Noul question needs_human_followup over session title + final assistant message (+ task_name for scheduled runs; original language kept, English instructions). P >= 0.5 → needs follow-up. Never throws; blank input → null; 1.5s AbortController deadline; null verdict = fail-open (no change).\n4. main.ts wiring — createCerebellumSessionFollowUpGate factory resolves resolveCerebellumCallContext() per call (never bare fetch: 401/451 gotcha), returns null when cerebellum unavailable, logs coworkLog INFO sessionFollowUp:cerebellumClassify with verdict + latency only — never content.\n5. CoworkRunner hooks — (a) human-composed turn start (startSession/continueSession non-skip blocks) clears a cerebellum-sourced pending (machine flows pass skip* flags and are excluded); (b) turn completion in the DSH local kernel (single choke point, finish('completed') branch only, after all teardown) classifies fire-and-forget: true → setSessionFollowUp('cerebellum'), false → clear onlySources ['cerebellum'], null → nothing; (c) AskUserQuestion persistence: pending ask on an auto-origin session sets ask_user; every exit path (answered, declined, kernel-deadline cancel) clears it. Guarded: absent gate option = skip entirely; every helper is throw-safe.\n6. IPC + preload — cowork:session:setFollowUp { sessionId, followUp: boolean } with strict validation (manual move-in = 'manual' pending; move-out clears ANY source, unguarded), preload window.electron.setSessionFollowUp next to setSessionFoldOverride. Renderer refresh uses the same mechanism as foldOverride (mutate + return success; renderer re-reads listSessions).\n\nTests: 2 new suites / 17 tests (gate request shape + caps + parser clamping + all failure modes → null; migration idempotency, set/clear semantics, manual stickiness, onlySources guard, persistence across reopen). Existing related suites stay green: sessionAutoGrouping, coworkSessionAutoOrigin, coworkSessionFoldOverride, coworkUnreadAutoOrigin, 9 cerebellum suites, ask-bridge + DSH turn-end suites (~215 tests total).\n\nPhase 2 (renderer, separate) builds against: summary fields followUpState/followUpSource/followUpAt and window.electron.setSessionFollowUp(sessionId, followUp). Design doc: localdocs/2026-10-22-follow-up-tasks-requirement.md (aligned 2026-10-22).","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}