Problem
Paper §5 invariant #2 ("Accumulation"): "Sub-agent spend counts toward parent totals."
This only fires AT SubagentStop. While a child agent is running concurrently with its parent, the parent's PostToolUse fail-fast check sees only its own cumulative spend.
Concrete: maxSpendUSD=$10, parent at $9, child spending $5 concurrently — parent's next PostToolUse passes ($9 ≤ $10), child stops, merge brings parent total to $14. Policy ceiling exceeded.
Code reality
mergeChildIntoParent (internal/hooks/handler.go:1645) has exactly one callsite — handler.go:1110 inside handleSubagentStop. No push-up from child PostToolUse to parent during runtime.
Options
A — push-rollup (continuous accumulation): child PostToolUse acquires parent lock, loads parent, merges incremental delta, saves parent. Cost: extra lock contention per child tool call. Cleanest realization of paper invariant #2.
B — pull-rollup (parent-side aggregation): parent PostToolUse enumerates all child sessions whose ParentSessionID == parent.SessionID, sums their metrics on the fly. Cheaper when children are rare; correctness depends on enumeration being complete.
C — qualify paper: acknowledge accumulation is "at child completion" not continuous. Document, drop the implied real-time guarantee.
Recommend A or B for a real "fail-fast" guarantee. Pick one before implementation.
Acceptance
References
- Paper §5 invariant #2 ("Accumulation")
internal/hooks/handler.go:1110 (single mergeChildIntoParent callsite, SubagentStop only)
Problem
Paper §5 invariant #2 ("Accumulation"): "Sub-agent spend counts toward parent totals."
This only fires AT
SubagentStop. While a child agent is running concurrently with its parent, the parent'sPostToolUsefail-fast check sees only its own cumulative spend.Concrete:
maxSpendUSD=$10, parent at$9, child spending$5concurrently — parent's next PostToolUse passes ($9 ≤ $10), child stops, merge brings parent total to$14. Policy ceiling exceeded.Code reality
mergeChildIntoParent(internal/hooks/handler.go:1645) has exactly one callsite —handler.go:1110insidehandleSubagentStop. No push-up from child PostToolUse to parent during runtime.Options
A — push-rollup (continuous accumulation): child
PostToolUseacquires parent lock, loads parent, merges incremental delta, saves parent. Cost: extra lock contention per child tool call. Cleanest realization of paper invariant #2.B — pull-rollup (parent-side aggregation): parent
PostToolUseenumerates all child sessions whoseParentSessionID == parent.SessionID, sums their metrics on the fly. Cheaper when children are rare; correctness depends on enumeration being complete.C — qualify paper: acknowledge accumulation is "at child completion" not continuous. Document, drop the implied real-time guarantee.
Recommend A or B for a real "fail-fast" guarantee. Pick one before implementation.
Acceptance
References
internal/hooks/handler.go:1110(single mergeChildIntoParent callsite, SubagentStop only)