You are the handoff-size-check skill — pre-handoff payload validation against the 500k cap.
What this skill does
When the operator picks "run anyway" on a broad idea (elephant-hint default), the plan declares its own handoff size. If the plan's payload approaches the 500k cap → natural warning point ("this plan yields ~480k handoff, near cap — split it?").
Per v3.6 backlog 3.2 — complements 3.1 elephant-hint + 2.1 500k cap as the same mechanism from two ends:
- Elephant-hint (3.1): catches a broad idea BEFORE plan-writing
- Handoff-size-check (3.2): catches a large plan AFTER plan-writing
- Cleaner than two separate systems.
When to use
- Post-PLAN-phase auto —
/li:cycleinvokes this after plan.md is done - Standalone audit —
/li:handoff-size-check <plan.md>→ check a specific plan - Pre-cold-executor-handoff — verifies trio + warming total < cap
When NOT to use
- Mid-plan-writing (a warning against a partial plan is a false positive)
- Single-skill estimate — use
/li:context-budgetdirectly - Real-time monitoring — this is a batch check at handoff points
Workflow
Step 1 — Locate plan + warming-manifest
PLAN_FILE="${1:-.claude/runtime/state/plan.md}"
WARMING_FILE=".claude/runtime/state/warming-manifest.md" # from context-warm-* invocations
[ -f "$PLAN_FILE" ] || { echo "No plan found at $PLAN_FILE"; exit 2; }
Step 2 — Compute payload size
# Cold-executor trio sizes
spec_size=$(wc -c < .claude/runtime/state/spec.md 2>/dev/null || echo 0)
plan_size=$(wc -c < "$PLAN_FILE")
prompt_size=$(wc -c < .claude/runtime/state/prompt.md 2>/dev/null || echo 0)
# Warming projected loads
warming_total=0
if [ -f "$WARMING_FILE" ]; then
# Parse warming-manifest for per-load file-sizes
while IFS= read -r line; do
if [[ "$line" =~ ^load:[[:space:]]*([0-9]+) ]]; then
warming_total=$((warming_total + ${BASH_REMATCH[1]}))
fi
done < "$WARMING_FILE"
fi
# Convert bytes to tokens (rough: 1 token ≈ 4 bytes)
trio_tokens=$(( (spec_size + plan_size + prompt_size) / 4 ))
warming_tokens=$(( warming_total / 4 ))
total_tokens=$(( trio_tokens + warming_tokens ))
Step 3 — Apply mode-aware cap (per 2.1)
Read current mode from ~/.lintel/profile.yaml. Look up the cap from context-budget mode_envelopes:
hotfix: { soft: 200k, hard: 300k }
customer-engagement: { soft: 500k, hard: 750k }
research-dive: { soft: 750k, hard: 900k }
demo-prep: { soft: 300k, hard: 450k }
internal-tool: { soft: 400k, hard: 600k }
Step 4 — Surface verdict
HANDOFF SIZE CHECK — <mode> mode (cap: <soft>k soft / <hard>k hard)
══════════════════════════════════════════════════════════════════
Plan + trio: <X>k tokens (~<%> of soft cap)
Warming projected: <Y>k tokens
TOTAL HANDOFF: <Z>k tokens
Status:
Z < soft → ✅ GREEN — proceed
soft ≤ Z < hard → ⚠ YELLOW — near cap, consider:
- Split the plan (into 2 smaller phases)
- Skip --skip-warming-<X> on lowest-priority warming target
- Switch to research-dive mode (higher cap) if research-justified
Z >= hard → ⛔ RED — exceeds cap, MUST reduce:
- Plan is too broad → split now
- Warming includes too many files → cut to essentials
- Mode mismatch → consider research-dive
Suggested next step: <auto-recommendation>
Return code: 0 (green), 1 (yellow), 2 (red).
Step 5 — Audit-log
One line via the unified writer (ts/operator/cycle_id come from the envelope):
source "${LINTEL_SOURCE_ROOT:-$(git rev-parse --show-toplevel)}/bin/_audit.sh"
audit_log handoff-size-checks size_check "plan=$PLAN_FILE" "mode=$mode" \
"total_tokens=$total_tokens" "verdict=$verdict"
# → .claude/runtime/audit/handoff-size-checks.jsonl
Status protocol
- DONE — check done, verdict green
- DONE_WITH_CONCERNS — yellow verdict (near cap warnings)
- BLOCKED — red verdict (exceeds cap) — operator must address before handoff
- NEEDS_CONTEXT — no plan file at default path and
--planarg missing
Pause-points
- Red verdict: hard-block for operator decision (split / cut warming / abort handoff)
- Yellow verdict: surface options + ask whether to proceed (override OK with justification)
- Missing warming-manifest: assume warming = 0 + warn that the estimate may be low
Integration
Reads:
.claude/runtime/state/plan.md(or--plan <path>override).claude/runtime/state/spec.md,prompt.md(cold-executor trio).claude/runtime/state/warming-manifest.md~/.lintel/profile.yaml(current mode → cap)- skills/context-budget/SKILL.md mode_envelopes
Writes:
.claude/runtime/audit/handoff-size-checks.jsonl- stdout (verdict report)
- Return code (CI/script consumption)
Consumed by:
/li:cycle(auto-invocation post-PLAN)- Operator (pre-handoff manual check)
/li:ship(could integrate as a ship-gate)
Anti-patterns
- Auto-cut warming without operator-approval — cap-violation surfaces options; operator decides which warming targets stay.
- Override red verdict without justification-log —
--override "<reason>"logs intent. Silent bypass = future-debugging-pain. - Token-budget in bytes — Lintel cap is in tokens. Convert at compute time.
Failure recovery
- Plan-file unreadable: exit BLOCKED with diagnostic
- Mode unknown: fall back to customer-engagement defaults + warn
- Warming-manifest absent: assume 0 warming, surface "estimate may be low"
Recommended next steps after invocation
- Green: proceed with cold-executor handoff
- Yellow: review the warming list for cut-candidates, consider splitting
- Red: address blocker (split / cut / mode-change), re-run check
- Pair with
/li:context-budget --reportfor deeper headroom-analysis