Pipeline Architecture 3-Model Consensus Cap Removal Blueprint

Full Handoff Chain & Limit Deconstruction

End-to-end dataflow telemetry, token mechanics, prompt budgeting, and the architectural transition from arbitrary hardware leashes to natural epistemic prompting.

Adjudication Cadence Daily 04:00 UTC / Tue Reviews Live Traces: 11 Runs Analyzed

⚑ The Core Finding: Prompt Leashes vs. Hardware Headroom

1. Sol Was Never Hardware Capped
The OpenAI API ceiling was already configured to max_output_tokens: 8192. The ~1,500 word ceiling was an artificial English prompt leash ("in no more than 1,500 words") authored to prevent Sol from reprinting Terra's report verbatim.
2. Hidden Reasoning Token Bite
In OpenAI's Responses API, max_output_tokens covers both invisible reasoning tokens and visible output. In our Sept 10 run, Sol burned 3,514 reasoning tokens before generating 1,196 visible tokens. An 8k limit leaves only ~4k for text!
3. The Proposed Zero-Limit Paradigm
Prompt for rigorous structure and conciseness, but give models massive token ceilings (16,384+). Never let an arbitrary integer limit truncate high-value trade counter-arguments or multi-player waiver ledgers.

πŸ”„ The Full Pipeline Handoff Chain

Who hands off what to whom, at what stage, and where data boundaries are enforced.

Stage 0 πŸ’Ύ Ingestion

Context Assembly

Pulls live platform data (Sleeper/ESPN/Yahoo), ESPN/FantasyPros projections, and previous day's audit markdown from disk.

Input: Disk + APIs
Cap: 12k chars context
Stage 1 πŸ€– Thesis

Terra (Primary CAO)

gpt-5.6-terra executes 2–3 autonomous tool-calling turns evaluating rosters, matchups, and waiver deltas. Produces the primary draft.

Handoff: Raw Draft Text
Output: ~14k chars / 2k words
Stage 2 πŸ” Antithesis

Gemini (Grounded Audit)

gemini-3.8-flash takes Terra's full draft, performs Google Searches, challenges premises, and classifies issues (FACTS, STRATEGY, PROJECTION).

Handoff: Unedited Critique
Output: 10k chars / 1.5k words
Stage 3 βš–οΈ Synthesis

Sol (Final Adjudicator)

gpt-5.6-sol takes both Terra's draft & Gemini's critique. Uses OpenAI Web Search to settle disputed facts, issuing binding Add/Drop rulings.

Handoff: Binding Decision Ledger
Output: 5.6k chars / 720 words
Stage 4 πŸ“Š Delivery

Consensus Assembly

assemble_consensus_report unites Sol rulings + Provenance Manifest + Gemini Critique + Terra Draft into HTML/MD and sends mobile push alerts.

Final Destination:
HTML Dashboard & ntfy/Gotify

πŸ“Š Empirical Telemetry from Live Production Runs

Parsed directly from run trace logs: out/run-traces/advisor-run-2026-09-10_234502-1981894.jsonl

Run ID: 2026-09-10 23:45 UTC
πŸ€– Terra (3 Turns) 19 Tool Calls
Input Tokens: 49,858
Reasoning Tokens: 3,343
Content Tokens: 3,222
Total Turn Usage: 56,423
Output Text: 14,096 chars (1,897 w)
πŸ” Gemini (Google Grounded) Search Enabled
Prompt Tokens: 8,130
Thinking Tokens: 6,777
Candidate Tokens: 2,856
Total Gemini Usage: 17,763
Output Text: 10,012 chars (1,463 w)
βš–οΈ Sol (Web Search Preview) Binding Ledger
Input Tokens: 69,015
Reasoning Tokens: 3,514
Content Tokens: 1,196
Total Sol Usage: 73,725
Output Text: 5,625 chars (721 w)
πŸš€ Full Advisory Cycle 1 Run
Pipeline Runtime: 68.4s
Total Tokens: 147,911
Reasoning / Thinking: 13,634
Final Document: 35,522 chars
*Sol input tokens include crawled pages from OpenAI web search preview.

πŸ“‘ Current Limits vs. Proposed "Zero-Constraint" State

Comprehensive audit of every bottleneck, why it was implemented, and the exact proposed modernization.

Handoff Stage & Component Current Hard Limit Why It Existed Observed Bottleneck / Risk Proposed Uncapped State
Previous Day Audit Ingestion
DEFAULT_PREV_AUDIT_CONTEXT_CHARS
12,000 chars
(~2,400 tokens)
Kept context lean for initial prototype testing when context window was presumed small. Cut off the bottom 60% of yesterday's audit. Yesterday's audit was 35,000 chars, so 23,000 chars of baseline reasoning were thrown away! 60,000 chars (or Uncapped)
Terra takes 128k+ tokens; a 60k char audit is only ~12k tokens (less than 10% of window).
Waiver Wire Pool Retrieval
AdvisoryEngine.get_waiver_wire()
top_n: 15 per pos
(Total ~60 players)
Prevented tool output from overflowing standard chat completion token buffers. Models cannot see contingent handcuff stashes (e.g. Isaac Guerendo, Braelon Allen, Blake Corum) if ranked beyond #15 on raw projections. top_n: 40–50 per pos
Gives full visibility into true handcuff and option-value wire depth.
Sol Prompt Word Cap
engine/adjudication.py:232
"in no more than 1,500 words" Intended to keep Sol from re-writing Terra's full 3,000-word draft since it's already appended below. Prompting "under 1,500 words" forced Sol to be terse (721 words in live run), skipping detailed player-by-player trade veto logic. Prompt for Structure, Not Word Count
Replace with: "Render an exhaustive, rigorous final review without filler or repetition. Prioritize thorough transaction justifications."
Sol API Token Ceiling
payload["max_output_tokens"]
8,192 tokens
(Reasoning + Output)
Default safety limit in OpenAI responses prototype. High risk of catastrophic truncation! Sol spent 3,514 tokens on reasoning in our run. If reasoning took 5,500 tokens, visible text would cut off midway. 16,384 tokens
Doubles the headroom so reasoning never eats the transaction ledger quota.
Gemini Grounded Review
run_gemini_review()
No hard token cap
(Thinking Level: MEDIUM)
Already unconstrained on token output. Currently healthy (used 2,856 candidate tokens and 6,777 thinking tokens with zero truncation). Maintain Unconstrained Headroom
Keep temperature 0.3 and thinkingLevel MEDIUM; allow full candidate depth.
Terra Autonomous Turn Cap
run_openai_responses_advisor()
range(12) turns Circuit breaker against runaway autonomous tool calling loops. Terra used 3 turns and 19 tool calls in live run. 12 is sufficient, but 16 gives headroom for deep trade target scans. 16 turns (Safety Ceiling Only)
Terra naturally completes in 2–4 turns; bump turn limit to 16 just in case.

🧠 The Mechanics: Why Prompting Beats Hard Max Tokens for Reasoning Models

❌ The Failure Mode of Hard Token Caps

In legacy LLMs (GPT-4, Claude 3.5), max_tokens only limited visible words. If you set 2,000 tokens, you got up to 1,500 words of output.

In reasoning models (GPT-5.x, o-series, Gemini with Thinking), the API budget combines hidden chain-of-thought tokens and visible output into a single pool.

Budget: 8,192 tokens
- Spent on Web Search & Reasoning: 5,500 tokens
= Remaining for Visible Output: 2,692 tokens (Cut off mid-sentence!)

Setting a low max_tokens does not make the model more conciseβ€”it makes the model run out of ink halfway through the page.

βœ… The Power of Prompt-Governed Depth

Reasoning models respond exceptionally well to qualitative criteria:

  • "Exhaustive but unpadded": Instruct the model to justify every transaction card thoroughly without conversational introductions or meta-commentary.
  • Structured Cards: Requiring mandatory headings (Verdict:, Why:, What is being forfeited:, Net roster impact:, Evidence:) forces high-density signal.
  • Generous Token Headroom (16k+): Guarantees that even if Sol conducts complex 4-step web searches, the visible transaction ledger will never be truncated.

πŸ› οΈ Ready Implementation Actions

Immediate code adjustments to apply across fantasy-daily-advisor and fantasy-2026.

Zero Breaking Changes
// 1. Lift Sol Prompt & Payload Caps (engine/adjudication.py)
- "Return only an executive review seal, material corrections, and the authoritative transaction decisions in no more than 1,500 words."
+ "Provide an exhaustive, authoritative adjudication. Thoroughly explain each approved or vetoed move in the Transaction Decision Ledger without arbitrary length limits."
- "max_output_tokens": 8192,
+ "max_output_tokens": 16384,
// 2. Expand Day-over-Day Context & Waivers (daily_advisor.py)
- DEFAULT_PREV_AUDIT_CONTEXT_CHARS = 12000
+ DEFAULT_PREV_AUDIT_CONTEXT_CHARS = 60000 # Expand from 12k to 60k chars
- res = engine.get_waiver_wire(position=args.get("position"), top_n=args.get("top_n", 15))
+ res = engine.get_waiver_wire(position=args.get("position"), top_n=args.get("top_n", 40))