Skip to content

Staff session staffId persistence#609

Merged
SuuBro merged 3 commits into
masterfrom
goal/staff-sess-ca98c8d6
May 18, 2026
Merged

Staff session staffId persistence#609
SuuBro merged 3 commits into
masterfrom
goal/staff-sess-ca98c8d6

Conversation

@SuuBro
Copy link
Copy Markdown
Owner

@SuuBro SuuBro commented May 17, 2026

Summary

Staff sessions silently lost their staffId association across server restart / agent CLI respawn. The three inbox tools (inbox_list, inbox_complete, inbox_dismiss) are gated by BOBBIT_STAFF_ID in the agent process env, set on every (re)spawn from PersistedSession.staffId. Pre-fix, StaffManager mutated session.staffId only in memory — SessionManager.createSession() didn't accept staffId in its opts, so plan.staffId stayed undefined and persistOnce wrote nothing to disk. On respawn, restoreSession read ps.staffId = undefined → no env var → inbox tools refused to register → staff agent could never mark entries complete, and pending entries re-fired forever.

Root cause

  • StaffManager.createStaff / ensureSessionForStaff set session.staffId = id after createSession() returned — purely in memory.
  • SessionManager.createSession had no staffId field in its inline opts type, so the field never reached either plan-builder.
  • persistOnce() faithfully writes staffId: plan.staffId — but with plan.staffId always undefined for staff sessions, the persisted record on disk was always missing staffId.

Fix

  1. Spawn-path plumbing — added staffId?: string to SessionManager.createSession opts; threaded staffId: opts?.staffId, into both plan-builder literals (worktree branch and normal branch).
  2. Staff-manager call sites — pass staffId: id in both createSession invocations.
  3. One-shot backfill migration — new src/server/agent/staff-backfill.ts runs at server boot, finds sessions with no staffId whose title matches a staff name AND whose worktreePath/cwd matches the staff's worktree, and heals them with a loud warn log. Conservative — refuses title-only matches.

Regression test

tests/staff-session-staffid-persistence.test.ts — 7 tests across 3 describe blocks:

  • Spawn-path regression (source grep for the staffId: opts?.staffId, plan-builder lines, fails on master, passes after fix) + behavioural round-trip via persistOnce.
  • Forward guard for staffId round-trip through store.put.
  • Backfill migration — happy path, idempotency, conservative-match rejection (title-only without worktree agreement does NOT backfill).
  • Source guards for restoreSession env wiring and persistOnce write.

All 7 pass on this branch; coder confirmed they fail on master when the source fix is stashed.

Documentation

  • docs/debugging.md — new symptom entry "Staff inbox tools missing after restart / [INBOX] completion silently fails" with jq diagnostic, expected warn log, the four spawn-path wires, and a pointer to the pinning test.
  • Module docstring on staff-backfill.ts and one-liner comments on the load-bearing plan-builder and call-site lines, all pointing to the regression test.

Verification

  • npm run check — pass
  • npm run test:unit — 1101 pass
  • npm run test:e2e — 1111 pass, 11 flaky-retry passes, 8 skipped

Out of scope (deferred to follow-ups)

  • Inbox-tool error UX when BOBBIT_STAFF_ID is missing (spec Enforce PR-only master policy in team-lead prompt #5). The fix means this state never happens for new sessions and the backfill heals existing ones, so the original motivation evaporated.
  • Generalising the fix to BOBBIT_GOAL_ID / BOBBIT_TASK_ID — investigation shows those already work correctly via plan.goalId / plan.taskId.

🤖 Generated with Bobbit

SuuBro and others added 3 commits May 17, 2026 23:48
…ation

Staff sessions lost their staffId association across server restart /
in-place respawn because StaffManager set `session.staffId = id` only in
memory \u2014 SessionManager.createSession() never accepted `staffId` in its
opts, so plan.staffId stayed undefined and persistOnce wrote no staffId
to disk.

On respawn, restoreSession read ps.staffId = undefined \u2192 no
BOBBIT_STAFF_ID env \u2192 defaults/tools/inbox/extension.ts gated all three
inbox tools off \u2192 staff agent could no longer mark entries complete.

Fix:
- Thread staffId through createSession opts \u2192 plan \u2192 persistOnce, so it
  lands in PersistedSession at spawn time and survives any respawn path.
- Add a one-shot startup backfill (src/server/agent/staff-backfill.ts)
  that heals existing broken sessions by matching title + worktreePath
  against the staff registry, with a loud warn log on every match
  (spec req #4). Wired from server.ts boot via
  sessionManager.backfillStaffIds(staffManager).

Regression test: tests/staff-session-staffid-persistence.test.ts \u2014
Tests 1 and 3 fail on master, pass after fix. Source guards pin the read
side (restoreSession), the write side (persistOnce), and the new
plan-builder wiring (createSession opts \u2192 plan).

Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
Co-authored-by: bobbit-ai <bobbit@bobbit.ai>
@SuuBro SuuBro merged commit 6348150 into master May 18, 2026
@SuuBro SuuBro deleted the goal/staff-sess-ca98c8d6 branch May 18, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant