Repository navigation
Tasks: the older task road refuses duplicate work and holds a tree spend total - #2464
Merged
Merged
Conversation
AbirAbbas
added a commit
that referenced
this pull request
Nov 6, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AbirAbbas
added a commit
that referenced
this pull request
Nov 6, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AbirAbbas
force-pushed
the
workstreams/l-fix9-e3
branch
from
November 6, 2026 14:39
7b12565 to
b72db24
Compare
…end total With CODEAF_TASK_BELT=node the session-tree road bounded depth (3), children per node (20) and each node's own bill, but two nodes of one tree could hand out the same work, and the tree as a whole had no spend total. It now applies the default road's bounds from #2446: - A child whose title matches, after plandb's normalization (now exported as plandb.NormalizedTitle, one definition for both roads), any non-cancelled task in the same tree is refused with the same words, and a division naming the same work twice is refused whole. Pending proposals reserve their titles. A typed task starts a separate tree, so separate trees may reuse a title. - Every node, helper and check of one tree shares one spend tally held to the lower of crew.task_cap and the conversation's remaining limit (the same arithmetic as the default road). Reaching it stops the whole tree and the ending names the limit and how to raise it. A checkpoint keeps the tree's spent total. Two existing division tests used repeated titles as filler; their fixtures now name distinct work and keep every assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round: the first version held the tree to a new shared guard with its own stop and cancellation, which read a limit stop as a person's stop, missed paid tool receipts, could re-grant a conversation-bound allowance after a restore, and waited on checkpoint writes before cancelling. The tree total now reuses the older road's existing per-node check instead: before each worker request, the summed bill of the tree's root and every descendant is compared with the tree's ceiling, which is fixed when the root is admitted (the default road's arithmetic) and kept in the checkpoint. A node over it ends on the cost-limit ending with the configured-limit words, or the conversation-limit words when that bound it. The shared guard and its hooks are gone. TestAPartsBriefHoldsItsBoundWhateverLengthTheFieldsArriveAt sent two parts with the same title, which a division now refuses; its second part's title differs and every field stays at full length. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lan specs an id The spend test's graph dropped every report, so the root never finished folding its parts; it now delivers child reports as production does. The work-identity test's plan write lacked an id, so plandb refused it before comparing titles. No production change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AbirAbbas
force-pushed
the
workstreams/l-fix9-e3
branch
from
November 6, 2026 14:55
b72db24 to
f9b3471
Compare
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
Follow-up to #2446. With
CODEAF_TASK_BELT=node(the older session-tree road, still a live escape hatch), tasks had depth 3, 20 children per node and a per-node bill limit, but no duplicate-title refusal and no spend total for the tree. This gives that road the same bounds #2446 gave the default road, reusing its code.claimChild: proposals, quick tasks, divisions, plan dispatch), a title equal to any non-cancelled task in the same tree after plandb's normalization is refused with Tasks: a worker does its own task, and a task tree is bounded in depth, count and spend #2446's words, and nothing starts. A division that names the same work twice is refused whole. Pending proposals reserve their titles.plandb.NormalizedTitleexports the existing normalization so both roads share one definition. A typed task starts its own tree, so separate trees may reuse a title.crew.task_cap, $5 by default, and the conversation's remaining limit, factored intotaskTreeCost), and kept in the checkpoint as an additive fact, so a restore cannot re-grant it. A node over it ends on the cost-limit ending with the configured-limit words, or the conversation-limit words when that limit bound it. A node in flight ends at its next request, as with the per-node limit; a node that starts later spends nothing. No new guard, stop or cancellation path.Validation contract → tests (
internal/session/task_node_bounds_test.go)TestNodeTreeRefusesDuplicateWorkAnywhere,TestNodeTreeAllowsCancelledTitlesAndSeparateRoots,TestNodeTreeReservesPendingProposalTitlesTestNodeTreeRefusesAnEntireDuplicateDivisionAndQuickTaskTestNodeTreeAllowsCancelledTitlesAndSeparateRoots,TestNodeTreeSpendStopsEveryNodeAndNamesTheBindingLimitTestNodeTreeSpendStopsEveryNodeAndNamesTheBindingLimit,TestNodeTreeCheckpointKeepsTheUnspentAllowance,TestNodeTreeCheckpointWithoutLimitComputesItAtRestore,TestNodeTreeWithNoConversationAllowanceSpendsNothing,TestNodeTreeLimitRefusesBeforeCheckpointWritesTestNodeTreeUnderTheCeilingFinishesNormallyTestNodeTreeUsesThePlanStoresWorkIdentityExisting tests changed
All three used repeated titles as filler, which C1/C2 now refuse on purpose. Their fixtures name distinct work; every assertion is unchanged.
TestADivisionWiderThanTheCapIsRefusedWholeRatherThanHalfTaken: fills the fan cap with 18 distinct parts instead of repeating two titles, and asserts that setup count.TestAThirdAskAfterARepairNeitherRefusesNorDoublesTheFamilysChecks: the third ask namesranking/browsinginstead of re-sendingrank/browse.TestAPartsBriefHoldsItsBoundWhateverLengthTheFieldsArriveAt("every field at once"): its two parts had the same full-length title; the second now starts "the beta adapter " and every field stays at full length.Review round
A fresh review of the first version found five majors, all in its separate shared spend guard (a limit stop read as a person's stop, paid tool receipts missed, a restore could re-grant a conversation-bound allowance, cancellation waited on checkpoint writes, a racing test). The tree total was redone as the check above, which has none of those paths.
🤖 Generated with Claude Code