Repository navigation
TDD 0067: /build-tdds Retry and escalation, judged by the model that actually ran - #187
Merged
cahenesy merged 8 commits intoOct 6, 2026
Merged
Conversation
tests/escalation.test.sh executes every TDD 0067 Verification-plan observation (1-13, 11b, 11c) against a fixture repo (integration branch master, runs built through tl_run_init / tl_run_set_tdd / tl_verdict_write), extracts and runs the four new skill blocks plus 0066's confirm/record blocks with escalation, covers the approved CLAUDE_CODE_SUBAGENT_MODEL mechanical-verify arm, and drives the live probe's exit classification against a stub claude (no network). Registered in tests/implement-gate.test.sh. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
… 0067) models.sh: a third [escalation-model] resolver arg turns every `parent` slot into `escalation` (pins keep their pin; mechanical verify keeps its rule); tl_escalation_outcome (escalated | already-top | fell-back) and tl_escalation_flags (--escalate / --no-auto-escalate and their env twins); tl_models_confirm / tl_model_warnings take the escalation model and outcome and add the `escalation:` confirmation line. Approved fix: on Claude, mechanical verify resolves a non-empty CLAUDE_CODE_SUBAGENT_MODEL as `pin:CLAUDE_CODE_SUBAGENT_MODEL` before the parent-cap fallback. run-record.sh: tl_run_set_models 6th arg; tl_run_latest_run, tl_run_retry_candidates, tl_run_failed_report, tl_run_retry_begin (archives only *.json verdicts into retry-<N>/, then `building`), tl_run_set_halt_blob, tl_escalation_decide, tl_run_set_escalation (all sidecar writes via _tl_models_write), tl_escalation_fellback_check. skills/implement/SKILL.md: tl:escalation-flags, tl:retry-candidates, tl:retry-begin and tl:escalation-decide blocks (block contract); step 3 offers Retry for failed/gate-fail TDDs; confirm/record wiring reads the sidecar escalation; fall-back prose (transient first, except a usage-credits refusal of the escalation model; an async worker's failure arrives in its completion notification); halt blob after a gate-fail; usage line; CLAUDE_CODE_SUBAGENT_MODEL applies to every worker dispatched without a model parameter. tl:retry-begin also copies the failed report to <report>.prev.txt and prints implementer_report=<copy>, because step 7 recreates an empty <slug>.build.txt (a test-first FAIL's report) before the implementer reads it; the eval tracks that line. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
tests/live/escalation-probe.sh (verification observation 14, run only by the runtime-verify gate). Observed on Claude Code 2.1.289: the Agent tool is async by default, so its tool_result is only an "Async agent launched" ack. The probe now reads both shapes: a sync tool_result that carries the reply, or the ack followed by the harness's system/task_notification for that tool_use_id (status, summary) and the subagent's own messages (text and its SubagentHandback input.message). The ack's prompt, task_started and the parent's text echo the nonce and are never read for it. P1 is also BLOCKED when a model seen for the subagent (the ack's resolvedModel, the subagent's message.model, "model sent to the API: <id>") is outside the requested family: a silent substitution. Exit 1 names its cause, including a session that hit a rate/usage limit before dispatching. The eval's stub gains the real shapes: async pass, a usage-credits failure, a family substitution, a completed agent without the nonce, an ack with no notification, and a rate-limited session. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
…58/0067-build-tdds-escalation
TDD 0067 revision 2 / ADR 0016: renumber to the rev-2 Verification plan and add obs 10 (tl_worker_actual_model), 11 (tl_escalation_verify, incl. the opus alias case), the tl:escalation-verify block (obs 13 chain + every post-worker arm), the step-7 rule order and text checks (obs 14), and the reworked live-probe classification against a stub that writes worker transcripts (P1 classified against the transcript, P2 refusal, P3 positive control, session_id from system/init). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
…, ADR 0016) - models.sh: tl_worker_actual_model <agent-id> reads the worker transcript (projects/*/<session>/subagents/agent-<id>.jsonl, quoted config dir, jq fromjson? -> python3 cascade, never a regex) and prints the distinct non-synthetic models; tl_escalation_verify <agent-id> <model> prints escalated | fell-back harness ran <id> | fell-back actual model unverified (<why>). - SKILL.md: <!-- tl:escalation-verify --> block (fallback check, then verify; action=redispatch|keep|none; inherited workers never verified); step-7 rule order transient (credits_required is not transient) -> dispatch error -> tl_escalation_verify; wired into steps 9 and 10. - live probe: P1 classified against the worker transcript, P2 refusal, P3 positive control on opus; CLAUDE_CODE_SESSION_ID from the child's system/init session_id; exit 0/3/1 per the revised design. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
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.
Implements TDD 0067 revision 2 (PRD f6ef178, ADR 0015 + ADR 0016). This is the last of the model cost/performance stack; 0064–0066 are already on
master.What changed
retry-<N>/, so an interrupted Retry resumes at test-first.--escalate/THROUGHLINE_ESCALATE=1, or automatic on a Retry when the TDD hasn't changed since the halt.--no-auto-escalateturns the automatic case off.tl_escalation_verifyreadssubagents/agent-<id>.jsonl:fell-backwith a reason;credits_requiredcounts as a fall-back, not a pause;tests/live/escalation-probe.sh(run only in the verify gate): P1 uses the escalation binding, P2 a bogus model, P3 is a positive control onopus. It handles both sync and async Agent streams.tests/escalation.test.sh: 303 checks, run against the real functions and the blocks extracted from the skill.releases.jsonentry.History
The first build halted BLOCKED at runtime-verify, which was correct:
fablerefused withcredits_requiredwhen run headless.fabledispatch silently ranclaude-opus-5-5.Gates (retry)
abf96dd test(failing)was red on the pre-retry code, then835ac7d feat)fablerefused →fell-back, P2 refused, P3opus→escalated. P3's transcript was checked independently and readsclaude-opus-5-5.Review follow-ups (not blocking)
SKILL.md:346). Pass it via an env var instead.credits_requiredexception (SKILL.md:421), so a credits refusal could be classed as a pause and the refused model re-dispatched on every resume.~/.claude/projects/-tmp-tmp-*session folders behind. The cleanup trap should delete them.tl_run_retry_beginsplits the.prev.txtcopy and thereport=line between the function and the skill block, and names the copy differently from the TDD (<slug>.<gate>.prev.txt). It works and is tested; the TDD wording should be aligned.TL_BASE_SHAisn't validated;After merging
claude plugin update throughline@throughline, then/reload-plugins, to get 3.49.0.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq