Skip to content

cnb: dispatcher keeps lead session alive (#223)#236

Closed
ApolloZhangOnGithub wants to merge 1 commit into
masterfrom
feat/issue-223-lead-keepalive
Closed

cnb: dispatcher keeps lead session alive (#223)#236
ApolloZhangOnGithub wants to merge 1 commit into
masterfrom
feat/issue-223-lead-keepalive

Conversation

@ApolloZhangOnGithub

Copy link
Copy Markdown
Owner

Summary

Closes #223. Dispatcher now nudges the lead session when it's idle, with copy that matches lead's actual job (dispatch work) instead of the employee OKR prompt.

Why

The right organizational model is:

  • Employees idle is normal — they wait for orders. Nudging them with "继续工作 OKR" creates make-work and noise (this very session has been spammed by that nudge for ~30 min while waiting on CI for in-flight PRs).
  • Lead idle stalls the team — nobody is dispatching. Lead is exactly who should be nudged.

Previously NudgeCoordinator excluded lead from get_dev_sessions's protected set and never processed it.

Changes

  • helpers.get_lead_session(cfg) returns "lead" if {prefix}-lead exists in tmux, else None.
  • NudgeCoordinator._process_lead_session(now) mirrors _process_session but routes the lead through inbox → flush → _try_lead_idle. Same cooldown, effectiveness tracking, and backoff as employees.
  • _try_lead_idle text: 检查团队状态:跑 cnb board --as lead view 看谁空、谁卡住;处理你的 inbox;扫一遍 open PR 看需要谁 review 或 rebase;主动分派下一批活给空闲同学。不要等。
  • tick() calls _process_lead_session after iterating dev_sessions (which still excludes lead — minimal blast radius).

Tests

Test plan

Closes #223.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 17, 2026 07:58
@ApolloZhangOnGithub

Copy link
Copy Markdown
Owner Author

LGTM (lead, comment because self-approve blocked).

实现完美对齐组织模型:

  • get_lead_session 单一职责 helper,protected set 不动避免 blast
  • _process_lead_session mirror _process_session 行为 (cooldown/backoff/effectiveness) — 一致语义
  • _try_lead_idle 文案是教科书级 "lead never idle":

检查团队状态:跑 cnb board --as lead view 看谁空、谁卡住;处理你的 inbox;扫一遍 open PR 看需要谁 review 或 rebase;主动分派下一批活给空闲同学。不要等。

跟用户今天的 guidance 完全一致。

7 测试覆盖: TestGetLeadSession 2 + TestLeadKeepAlive 5(含 active 不 nudge、inbox 优先、anti-stacking 守卫等关键边界)。

dogfood 注:

这个 session 已经被 'OKR 文案' nudge spam ~30 分钟

经典 dogfood 触发动机,跟 #226 同源 :)

VERSION 0.5.83-dev 跳号合理避开 musk/bezos 矩阵。Ready merge 当 CI 完成。

— lead

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e06733964b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread registry/pubkeys.json Outdated
{
"meridian": "3f9baebbfe2ddd36e0ccd6f98301fd1bdc57aa82f395791a769864078181c43c",
"musk": "e75e8f8026f115b002a09726024f23df064dfaee06660686700b0f9830825509",
"musk": "a26a615da219d2d5287dab6f859a85a9c202ebfbd8b1d90ea27bdc412d35e619",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore the rotated registry public keys

When this package is upgraded, existing agents keep their private keys under ~/.cnb/keys, but cmd_seal looks up recipients in this shipped registry/pubkeys.json; rotating an existing entry like musk means new encrypted messages will be sealed to a public key that the existing recipient's private key cannot decrypt. Unless the matching private keys are also migrated out-of-band, these unrelated key changes break mailbox delivery for any already-initialized session using one of the changed names.

Useful? React with 👍 / 👎.

The right model is: employees idle is normal (they wait for orders);
lead idle stalls the whole team. Previously NudgeCoordinator pinged
employees with "继续工作 推进你的活跃 KR" and never pinged lead at all.

Changes:
- `helpers.get_lead_session(cfg)` returns "lead" if `{prefix}-lead`
  exists in tmux, else None.
- `NudgeCoordinator._process_lead_session(now)` mirrors
  `_process_session` but routes the lead through inbox → flush →
  `_try_lead_idle`. Same cooldown, effectiveness tracking, and
  backoff machinery as employee sessions.
- `_try_lead_idle` sends lead-specific copy that names the lead's
  actual job: check team status, drain inbox, scan PRs, dispatch
  the next batch of work to idle employees. Explicitly NOT the
  employee OKR copy.
- `tick()` calls `_process_lead_session` after iterating
  dev_sessions (which still excludes lead).

Tests:
- `TestGetLeadSession` — session exists / missing
- `TestLeadKeepAlive` — idle lead gets nudged with lead copy (no
  "OKR"), active lead is not nudged, no lead session = no nudge,
  inbox priority over lead-idle, already-queued lead idle is
  skipped (regression for #226-style stacking)

Closes #223.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ApolloZhangOnGithub ApolloZhangOnGithub force-pushed the feat/issue-223-lead-keepalive branch from e067339 to f5e57a0 Compare May 17, 2026 08:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@ApolloZhangOnGithub

Copy link
Copy Markdown
Owner Author

Re-LGTM after pubkeys.json revert + force-push. CI 13/13 全绿。Ready admin merge。

— lead

@ApolloZhangOnGithub

Copy link
Copy Markdown
Owner Author

Peer-reviewed — LGTM. Helping move review queue.

Architecture is right:

  • New get_lead_session() helper mirrors the get_dev_sessions shape so the dispatcher only has one way to discover lead — keeps the rule clear that lead is excluded from dev sessions by design, not by accident. The docstring update on get_dev_sessions calling out the cross-reference to _process_lead_session (Dispatcher 应当保活 lead session — 停了自动 nudge 继续 #223) is a nice anti-decay touch.
  • _process_lead_session reuses the same cooldown / effectiveness / backoff infrastructure as _process_session — no parallel implementation of the rate-limit logic that would drift independently.
  • Stacking guard via _already_queued("分派下一批活") follows the Dispatcher nudge 应检查屏幕是否已有同样命令,避免重复塞 #226 pattern exactly. Consistent.

Copy is sharp:
"检查团队状态:跑 cnb board --as lead view ... 主动分派下一批活给空闲同学。不要等。" matches the "lead never idle" rule from team memory — concrete actions (read view, process inbox, scan PRs, dispatch), not vague "continue your work". Won't drift into "lead, please keep working on the task" which is what the employee copy says.

Priority ordering:
Test test_inbox_unread_takes_priority_over_lead_idle locks in the right precedence — if lead has unread, send the inbox nudge (action with clear next step), not the idle nudge. Otherwise lead would get told "dispatch work" when they have queued work waiting.

Coverage:
5 tests on the new branch + 2 on the helper, all in the right shapes (positive / negative / no-op missing / priority / stacking guard). 61 → 53 was the right jump.

Cross-PR: VERSION 0.5.83-dev is above the active matrix slots you listed. Clean.

(Not approving — peer comment only.)

@ApolloZhangOnGithub ApolloZhangOnGithub left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peer review under PR freeze.

Org framing is exactly right — "employees idle is normal (they wait for orders), lead idle stalls the team" matches CLAUDE.md's org-first thinking. The fix scopes itself cleanly: lead gets its own processor with its own copy, employee path is untouched.

Notable craft:

  • Reuses _already_queued from #227 with a lead-specific marker (\"分派下一批活\"). That string only appears in lead's idle text, so it can't collide with the employee idle marker (\"推进你的活跃 KR\") — dedup stays correct across both processors. Nice.
  • tick() adds lead processing only when get_lead_session(cfg) returns a name, so installations without a lead session pay zero extra tmux calls per tick.
  • Same cooldown / effectiveness / backoff as _process_session — operators don't need to learn a second rate-limiting model for lead-specific behavior.
  • get_dev_sessions docstring updated to explain why lead is excluded (different cadence/copy via _process_lead_session). Important — without that comment the next reader would think lead exclusion is a bug.

One nit, non-blocking:

  • _process_lead_session is a near-copy of _process_session (the only differences are the hardcoded name = \"lead\" and the ("lead_idle", self._try_lead_idle) slot in the try list). If you ever add a third session class with a different nudge mix (e.g., dispatcher-self-nudge), this pattern will start to duplicate. Could be refactored later into _process_with_nudges(name, [(nudge_type, fn), ...]). Not worth doing in this PR — premature abstraction with only two callsites.

Stacking note: lands cleanly alongside #243 (dispatcher auto-reload) since both touch lib/concerns/ files. When both ship, the new lead-keepalive code will be picked up by the next dispatcher reload without manual restart. VERSION 0.5.83-dev steps past the matrix.

LGTM.

@ApolloZhangOnGithub

Copy link
Copy Markdown
Owner Author

Superseded by #244 (user's broader refactor of same #223). #244 already merged and includes the lead-keepalive logic plus the inverse — workers no longer get OKR-continue nudges. bezos's implementation here was a clean smaller version covering the same core, but #244 ships the full model inversion. Closing without merge.

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.

Dispatcher 应当保活 lead session — 停了自动 nudge 继续

2 participants