HookPayload fallback can still exceed cap on large handoffs #630
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#630
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
ADR-0206 records a known gap in the #627 hook-payload cap fix.
OsSdlc::Pipeline::HookPayload#to_json(plugins/os-sdlc/lib/os_sdlc/pipeline/hook_payload.rb, shipped by #627) drops only the map node's enrich facts when the serialized SubagentStart payload exceedsHOOK_CONTEXT_CAP(10,000 UTF-16 units).The
:handoffkey (the pending handoff content from the prior agent) is not an enrich fact, so it survives the fallback.fallback_payload(line 28) already replaces:briefwith the fetch instruction, so the brief file body is already covered;:handoffis the only large key left in the fallback envelope. A handoff alone larger than about 10,000 units still pushes the fallback over the cap. Claude Code then persists the string to a file with a 2,000-character preview, and the agent loses the fetch instruction.This was witnessed live; that observation is how this ticket was opened. (The original body's "Not yet observed live" line was wrong and is corrected here.)
Approach
Whenever the payload falls back at all, drop
:handoffunconditionally. One measurement, one fallback shape:Fallback envelope after the change:
session_id,implementation_id,dispatch_id,agent,node,instructions,brief(fetch instruction).Rejected alternative: a second measurement that keeps
:handoffwhen it fits (two fallback shapes for no gain).Required work:
fallback_payloadin plugins/os-sdlc/lib/os_sdlc/pipeline/hook_payload.rb to.except(:handoff)as above.dispatch_idand the fetch instruction (asserts:handoffis absent from the fallback result).Acceptance criteria
HookPayloadbuilt from a payload containing a:handoffkey whose serialized size alone exceedsHOOK_CONTEXT_CAP, with no enrich keys present, serializes to JSON at or underHOOK_CONTEXT_CAPUTF-16 units.:handoff/"handoff"key, regardless of whether the un-fallen-back payload fit without it.dispatch_idand abriefvalue includingos-sdlc-runner brief --dispatch-id <id>.hook_payload_test.rbcases (none of which construct a payload containing:handoff) continue to pass unmodified.Owner sketch
Blast radius
\1
test_payload_at_exactly_the_cap_is_emitted_unchanged_with_enriched_facts_inline,test_payload_over_the_cap_emits_routing_envelope_and_brief_command_only,test_a_non_bmp_character_counts_as_two_utf16_units) build payload hashes with no:handoffkey, so.except(:handoff)is a no-op for them; none of their assertions change. A new test case is required (see Required work) to cover the:handoff-present path.StartSubagent#payload(plugins/os-sdlc/lib/os_sdlc/pipeline/start_subagent.rb:40-50) mergesbrief(fromBriefComposer#compose) onto the envelope hash; it does not add:handoffitself.BriefComposer#compose(plugins/os-sdlc/lib/os_sdlc/pipeline/brief_composer.rb) always includes ahandoff:key viahandoff_json, which returnsnilwhen@handoffis absent — so:handoffis present with anilvalue when there is no handoff, not absent from the hash..except(:handoff)removes the key in both cases, so this is safe either way.enrichfact, so a handoff alone over the cap still overflows. This is a follow-up." — this line names the exact gap this ticket closes and must be updated or superseded by the amending ADR, not left standing as an open follow-up.Non-goals
The amending ADR (ADR-0206 consequences line 37 names this gap): written once for #630, #662, #670 after all three land, outside this run.
Trimming or capping
:brief/ticket-brief content size independent of the handoff (rejected already in ADR-0206 alternatives).Any change to
BriefLookup#callor theos-sdlc-runner brieffetch CLI — it already returns the handoff on request (plugins/os-sdlc/lib/os_sdlc/pipeline/brief_lookup.rb:20), so no seam is lost by removing:handofffrom the fallback.Moving
HOOK_CONTEXT_CAPto a different limit — separate follow-up per ADR-0206.Origin
• Trigger: ADR-0206 consequences, review of the #627 diff in session 94320dd4
• Improvised this session: none
• Chain: agent loses fetch instruction ← fallback payload exceeds cap ← handoff/brief not treated as enrich facts ← DESIGN (ADR-0206 consequences)
• Root candidate: this ticket
• Where: plugins/os-sdlc/lib/os_sdlc/pipeline/hook_payload.rb
• Session: 94320dd4-8ab4-49a8-ad82-a46504401428
• Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/94320dd4-8ab4-49a8-ad82-a46504401428.jsonl
Skeptic verdict: CREATE — real, documented gap (ADR-0206) in the #627 fix with a clear cause chain ending in a design decision, not improvisation; distinct root (handoff/brief not treated as enrich facts) from the other same-session ticket (behavior-verifier), so no root collision; scoped illustration provided.
Work started on branch ticket-630 via /os-sdlc:implement.
Resolution
Done: HookPayload#fallback_payload drops :handoff whenever the payload falls back over HOOK_CONTEXT_CAP; the fetch CLI already returns it. One fallback shape: session_id, implementation_id, dispatch_id, agent, node, instructions, brief.
Evidence: Branch ticket-630 commit
f4e8634cvia os-sdlc implementation 22: 8 dispatches, 0 retries, all pass; new test test_handoff_alone_over_cap_with_no_enrich_keys_is_dropped_and_dispatch_id_and_brief_kept; suite green (dispatch 255).Follow-ups: Amending ADR for ADR-0206 (envelope shape) written once for #630/#662/#670 after all three land; tracked in #662 and #670 bodies. No other follow-ups.