Repository navigation
fix: let long team tasks accept follow-ups past 32 journal entries - #28
Merged
Merged
Conversation
A two-phase lane hit both per-task journal walls at once, at the same time. Its 32 delivered coordinator follow-ups filled the control journal, so the next `sab team message` was refused with "This task reached its bounded control-operation limit". Its 31 worker replies left only the slot reserved for a final gate-clearing checkpoint, so the worker could no longer report gate progress. At that lane's pace (32 follow-ups in about 34 hours), a task's seven-day lifetime needs far more entries. - TEAM_TASK_CONTROL_MAX (previously the private TASK_CONTROL_MAX) and TEAM_MAX_REPLIES rise from 32 to 256. Both journals keep their full history, so these all work exactly as before: - request-ID idempotency, including the oldest operations; - conflict detection; - mutation receipts; - delivery recovery; - the reserved final gate-clearing reply slot; - the cancellation and release safety valves. - Every message and reply response embeds the task view. That view now windows replies and messages to the latest TEAM_TASK_VIEW_ENTRIES (32) and reports replyCount and messageCount, so responses stay within today's size envelope instead of growing with a long task's history. - Single-entry responses map their exact reply or message with the new publicTeamReply() and publicTeamMessage() helpers, so an idempotent retry of an old operation still returns that entry. A refused operation was never journaled, so no migration is needed. A coordinator can retry with the same request ID after deployment. Tests: - A live-shaped regression: 32 delivered follow-ups, 31 replies, 6 pending gates, awaiting release. It verifies that follow-up 33 resumes the same task with ownership, gates and earlier history intact; that idempotency and conflict checks still cover the oldest request; that the mutation receipt for it resolves; and that the worker can checkpoint gate progress and still clear the final gate. - The new bounds are enforced. - Views are windowed, with exact single-entry mappers. - Daemon responses never look entries up in the bounded view. Restoring either old cap, removing the window, removing the bound, or reintroducing a view lookup each turns these tests red. Full suite: 585 pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Xs8AVBVrTGfpzUMiCQp2R
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A long two-phase lane hit both per-task journal walls at once:
This PR raises both journals to a lifetime-sized bound. It keeps their complete history, and bounds the task views so responses do not grow with that history.
Root cause
TASK_CONTROL_MAX = 32caps a task's control journal: the request-ID records formessage,replace,cancelandrelease. Every coordinator follow-up adds one.TEAM_MAX_REPLIES = 32caps worker replies and checkpoints, and reserves the last slot for the checkpoint that clears the final gate.mainwith a task of the live shape (32 delivered follow-ups, 31 replies, 6 pending gates,awaiting_release):task_control_limit;reply_limit("reserved its final reply slot").Fix
TEAM_TASK_CONTROL_MAX(now exported) andTEAM_MAX_REPLIESgo from 32 to 256. Nothing is evicted or compacted, so the following behave exactly as before:sab team mutationreceipts;sab team message,replyandcheckpointresponse embedspublicTeamTask(), which for this lane is already about 200 KB. Views now show the latest 32 replies and messages (TEAM_TASK_VIEW_ENTRIES) plusreplyCountandmessageCount. Response size therefore stays within today's envelope. For tasks with 32 or fewer entries the view is unchanged apart from the two counts.publicTeamReply()andpublicTeamMessage(), so an idempotent retry of an old operation still returns its exact entry.Tests
a long task accepts follow-ups and checkpoints past the former 32-entry walls:task journals stay bounded at their lifetime caps.task views show the latest entries with totals while journals keep full history, including the exact single-entry mappers.single-entry team responses never depend on the bounded task view, a daemon contract.Each mutation was applied on its own, then the files were restored byte-identical:
Validation
npm test: 585 pass, 0 fail. The focused team suites pass 91 of 91.npm run check,npm run audit(0 vulnerabilities),node --check, Pi extension--list-modelsandshellcheckall pass. Every daemon named import resolves.Deployment notes
🤖 Generated with Claude Code
https://claude.ai/code/session_011Xs8AVBVrTGfpzUMiCQp2R