Skip to content

Enforce a pre-spawn model budget for planning invocations (#163) - #196

Merged
mchwang merged 19 commits into
mainfrom
claude/stoic-torvalds-d69f6d
Oct 21, 2026
Merged

mchwang merged 19 commits into
mainfrom
claude/stoic-torvalds-d69f6d

Conversation

@mchwang

@mchwang mchwang commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Closes #163.

What changes

  • createClaudeCommand (agents/policy.ts) now checks a planning model budget when it builds the command. startClaudeInvocation builds the command before it allocates a container or network, so this is before the agent process starts.
    • Input: the prompt and schema together must be at most 64 KiB of UTF-8 (MAX_PLANNING_INPUT_BYTES). A larger request is refused. The error gives the size, split into prompt and schema, and says what to narrow. Bytes stand in for tokens because Claude's tokenizer is not available offline (labelled as assumed). This equals the 32 KiB + 32 KiB limits that prepareDraft/prepareSuggestions already apply, so it is a backstop for callers that skip them.
    • Run: the planning command passes --max-turns 50 (PLANNING_MAX_TURNS). Other phases do not.
  • parseClaudeOutput (agents/adapters/claude.ts) uses the envelope's errors strings as the text when a failed result's result is missing or empty. This applies in every Claude phase.
  • planningOutput (runner/planning-provider.ts) names the turn limit when that text includes "Reached maximum number of turns". Every other failure keeps the sign-in advice.
  • Docs: a "Planning model budget" section and a gate-table row in docs/implementation/agent-isolation.md. The section records why turns and bytes were chosen, and not tokens or dollars. Also updated: the alignment row in plan-library-alignment.md and the builder note in prompts/plan-author.md, which is stripped before sending.

Evidence for the CLI behaviour

  • Claude Code 2.1.281 (the image's pinned version) accepts --max-turns in --print mode even though its help hides it. Checked in the Linux arm64 binary's bundled source.
  • A real run of the 2.1.281 macOS arm64 build ran outside the container with --print --output-format json --json-schema … --max-turns 1. It exited 1 with subtype: "error_max_turns", is_error: true, no result key, errors: ["Reached maximum number of turns (1)"] and num_turns: 2. parseClaudeOutput on that file returned { text: 'Reached maximum number of turns (1)', providerFailed: true }. The test fixtures use that envelope verbatim, minus members the parser does not read.
  • Not shown: the Linux CLI's stop behaviour inside the container. Startup probing is Probe the planning profile at runner startup #164.

Re-recorded planning fixtures

test/planning-recorded.test.ts hashes the exact planning argv, so adding --max-turns 50 made the old recordings stale. The maintainer re-recorded test/fixtures/planning/recorded/claude-{draft,suggest}.json with scripts/record-planning.ts, running Claude Code 2.1.281 in the planning container with the new argv. The result is commit 69eb218. Only commandSha256, requestId, recordedAt and output changed. The prompt, schema and files hashes are unchanged, and neither file contains any credential text. The hashes were not edited by hand.

Validation (head 69eb218)

Gate Result
Focused tests: planning-recorded, agent-policy, agent-adapter, planning-author, planning-provider 117 passed
Type check clean
Full non-Docker suite (local, at intermediate checkpoint e58d019, not on head 58df0ce) 76 failed / 2383 passed. 67 are 20 s timeouts from machine load (other sessions' Docker). 2 are the expected planning-recorded failures. The rest are timing failures in pre-merge/runner-publishing, which this change does not touch; on an isolated rerun a different pair failed. Not a clean gate: CI is authoritative.
CI (test, real-docker) at 58df0ce both failed only in planning-recorded (83/84 and 90/91 files passed); at 69eb218 both passed (test, real-docker)
Real-Docker locally not run (CI owns it)

Review record

Base aced300 (origin/main) for every round. Each independent round was a fresh general-purpose subagent, reviewing the full diff.

Round Type / reviewer Head Findings Changed
0 Self-review 645fa16 Planning run that hits the turn limit gave an empty, misleading error Added errors fallback (e2a11c6)
1 Independent agent e2a11c6 M: input check is only a backstop, and overhead is uncounted. L: tuning advice backwards. L: turns→tokens claim unlabelled. L: misleading sign-in advice on a turn stop. L: result:"" hid errors All fixed in e58d019
2 Independent agent e58d019 M: turn-limit fake not checked against the real tool. L: unlabelled claim. Nit: wrap Ran the real 2.1.281 CLI with --max-turns 1; docs and comments cite it (f3998cb..98a6d1f)
3 Independent agent 98a6d1f L: fixture values edited by hand (50 vs observed 1). L: "(50)" stated as fact. L: limit-plus-one call count. Nit: wraps Fixture made verbatim; docs reworded (91a942f)
4 Independent agent 91a942f L: gate row overclaimed. L: "before anything is allocated" only true in the adapter. L: plan-author note implied a probe Reworded (77c276c)
5 Independent agent 77c276c L: advice keyed on text (documented). L: 64 KiB not tied to MAX_PROMPT_BYTES. Nit: wrap Test ties the constants (b01806f, 03d9da0)
6 Independent agent 03d9da0 L: schema bound untested. Nit: wrap. Optional: check earlier in the runner Draft-at-limit test added. Earlier check declined: the docs state where the check runs, and it meets "before the agent process starts" (4cde897)
7 Independent agent 4cde897 L: "50-turn" advice vs quoted "(1)". L: error did not say which part was too large Size split into prompt and schema (e661388). Advice declined: production passes 50, and the fixture is verbatim
8 Independent agent e661388 L: advice did not name feedback or previous plan Fixed (2498340)
9 Independent agent 2498340 L: docs said the schema bound was tested Docs say what is and is not tested (e966141, 4bb2fc1)
10 Independent agent 4bb2fc1 L: errors text reaches every phase (undocumented). L: startsWith fragile. Nit: wrap Documented; switched to includes (0f16acc)
11 Independent agent 0f16acc Nit: Markdown list continuation Fixed (cd5a8fb)
12 Independent agent cd5a8fb L: other output containing the text gets turn-limit advice Documented in code and docs (58df0ce)
13 Independent agent 58df0ce No findings —
Copilot copilot-pull-request-reviewer 58df0ce High: planning recordings must be re-recorded, not hash-edited Re-recorded by the maintainer (69eb218)
14 Independent agent 69eb218 No findings (checked hashes, provenance, no credentials, replay 7/7) —
Copilot copilot-pull-request-reviewer 69eb218 No open issues (recording finding resolved) —

Round 13 (aced300...58df0ce) authorized the first Copilot request. Round 14 (aced300...69eb218) authorizes the re-request.

Review-lesson audit

  • Unverified CLI behaviour and fakes not checked against the real tool (rounds 2, 3): covered by the existing CLAUDE.md rule "A fake of an external tool … Check those answers against the real tool and name the version checked."
  • Claims stated wider than their evidence (rounds 1, 3, 4, 9, 12): covered by "Treat every behavioural claim … as something to verify … and give it a test that fails if the claim is false."
  • Wording, wrap and advice-text findings (rounds 5–11): one-off. They are specific to this change's messages and docs and have no general rule to extract.
  • Copilot's stale-recording finding is covered by docs/implementation/planning-acceptance.md: a changed Claude argv makes a recording stale, so it must be recorded again, not have its hashes edited.
  • No AGENTS.md/CLAUDE.md change needed.

Follow-ups

🤖 Generated with Claude Code

mchwang and others added 18 commits October 20, 2026 17:54
createClaudeCommand now refuses a planning request whose prompt and schema
together exceed 64 KiB of UTF-8 (a byte count standing in for tokens, as
Claude's tokenizer is not available offline), and passes --max-turns 50 so
the run itself is bounded by turns, not only by time and output bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e count (#163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… turn-limit detection (#163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y phase (#163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…163)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Both planning recordings require authenticated re-recording because the new command invalidates their fingerprints and breaks replay checks.

1 open issue
What changed in this PR

Adds pre-spawn planning budgets for #163 within the Claude invocation pipeline.

Changes:

  • Caps combined prompt/schema input at 64 KiB and planning runs at 50 turns.
  • Preserves provider error details and adds turn-limit guidance.
  • Documents budget assumptions and adds boundary tests.
File Description
test/​planning-provider.test.ts Tests turn-limit error guidance.
test/​planning-author.test.ts Checks prepared-input budget compatibility.
test/​agent-policy.test.ts Tests exact byte boundaries and planning argv.
test/​agent-adapter.test.ts Tests early refusal and error decoding.
runner/​planning-provider.ts Adds turn-limit retry guidance.
prompts/​plan-author.md Updates builder-only budget instructions.
docs/​implementation/​plan-library-alignment.md Records model-budget implementation.
docs/​implementation/​agent-isolation.md Documents limits, assumptions, and evidence.
agents/​policy.ts Enforces input and turn budgets.
agents/​adapters/​claude.ts Preserves error text when results are empty.

Review effort: Balanced

Comment thread agents/policy.ts Resolved
Recorded by the maintainer with scripts/record-planning.ts through the
planning container (Claude Code 2.1.281). Both answers validate and
replay through E2/E3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Required exact-head full-suite and real-Docker CI results remain unconfirmed in the supplied evidence.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@mchwang
mchwang marked this pull request as ready for review October 21, 2026 05:25
@mchwang
mchwang merged commit e46cb68 into main Oct 21, 2026
3 checks passed
mchwang added a commit that referenced this pull request Oct 21, 2026
…review round 13)

Merges main (#195, #196, #197) and updates the status lines this PR
rewrites; tests that a held cancel refusal also survives Refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mchwang added a commit that referenced this pull request Oct 23, 2026
…e (D16) (#194)

* Show the merge job's step list and let a person cancel the merge alone (D16)

Merge PR's job now records the design's seven steps (Fetch, Rebase, Push,
Re-run checks, GitHub checks, Already-fixed check, Merge) with each step's
state and start and end times, in its merge_jobs record. Preparation and
the guarded merge report their steps through display-only callbacks.

The review screen shows the list under the review strip with a Cancel
merge button. Cancelling stops the job and its preparation without
cancelling the task: the task keeps its status, its pull request stays
open, and Merge PR may be clicked again. It is refused once GitHub has
been asked to merge. A restart after a cancel settles the job cancelled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 1 of the merge step list

Give the server test's fake preparation stopForMergeCancel; poll at once
when a cancel is answered with a job that ended; rewrite only the elapsed
times each second; name the pending Cancel 'Cancel requested'; test a
cancel during the guarded merge's validation, during the job's first
review load and before shutdown, and older poll records after a cancel;
document where the list says a job stopped and when Cancel shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 2 of the merge step list

Poll quickly again after a cancel, so its outcome shows within seconds of
a backed-off poll; settle a restart after both cancels as a cancelled
task; let screen readers read each step's word and time as text and
move focus off a hidden Cancel; test a merge cancel during the push;
document every case where no step reads where the job stopped, repeat
cancels and clock skew.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 3 of the merge step list

Let a stop win over an inspection that answers after it, poll at once
after an ended cancel answer unless a poll of this generation is in
flight, escape a step's fallback word, and say that Cancel explains
itself when the Merge step's write failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 4 of the merge step list

Poll again within 2 s when a cancel is answered with an ended or newer
job while a poll is on its way; move focus off Cancel whenever the bar
or the button is hidden; write why a disabled Cancel cannot stop the
merge beside it; give the restart row its cancelled case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 5 of the merge step list

Describe Cancel by its note only while the note is shown, test that focus
moves off a hidden Cancel (to Refresh when the merge control hides too),
and keep focus on the page when a failed load hides the merge controls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 6 of the merge step list

Test that focus on Cancel moves to Refresh when a reload hides the merge
control or fails, and stop the elapsed-time ticker when a failed load
hides the step bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address Copilot review of the merge step list

Keep the step list of a job that ended queued through the queue polls;
ignore a cancel answer the poll already showed, follow a newer running
job it carries and discard polls of older jobs; show a refusal only
while the cancelled job is still shown running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Tidy the cancel-answer doc bullet and say what clears the step list (#194 review round 8)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Say that a restart settles a cancelled merge as cancelled (#194 review round 9)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 10 of the merge step list

Refuse a merge-only cancel while the task is being cancelled, keep the
pending-cancel flag per job, update the Shutdown row and the #end
comment for a cancelled merge, name Cancel merge in the architecture
overview, note the approved D16 amendment beside D16, and test the
refusal banner for an enabled Cancel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep a cancel refusal in the banner until the job's record changes (#194 review round 11)

Also clear only this cancel's own pending state, check the task-cancel
state the refusal test relies on, and qualify the repeat-cancel rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Show a held cancel refusal again on each poll, and list the step-list tests (#194 review round 12)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Mark build step 4 done: #174, #176 and the step list are closed (#194 review round 13)

Merges main (#195, #196, #197) and updates the status lines this PR
rewrites; tests that a held cancel refusal also survives Refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* List D16's unbuilt failure banners and Queue row as missing; qualify onAsking (#194 review round 14)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address independent review round 15 of the merge step list

Add the step list's Waiting and Running marks to DESIGN.md (approved),
an AGENTS.md rule for focus when a background update hides the focused
control, cite #199 for the rest of D16 and DT7, save the waiting checks
only when they change, and correct the onAsking comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Cite #199 on the build step 4 checklist line, word the checks-write comment, and add Skipped to DESIGN.md (#194 review round 16)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add the Stopped and Unknown marks to DESIGN.md, record the step list's placement, and test focus when a reload shows the job ended (#194 review round 17)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test the older-job poll guard, the poll speed on a list-step change and the list surviving the timer (#194 review round 18)

Also log the step bar's placement in DESIGN.md and name the F6b queue
test in the handoff doc's test list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move focus off Merge PR and its blockers button when a reload hides them, and test each way (#194 review round 19)

Reads the focused control before hiding it, since hiding blurs it at
once. Also drops the redundant first save of the waiting checks and
widens DESIGN.md's step-bar log entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Decide Merge status's visibility once, so a running job's poll keeps focus on it (#194 review round 20)

Also test the fallback to Merge PR when a reload clears the last
blocker, and word the test fixture's revision note as order only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move focus off a hidden merge control only after the render sets its final state (#194 review round 21)

Focus went to a still-disabled Merge PR (without a runner) and fell to
the page. renderMerge now records the focused control, renders, then
picks Merge PR only when shown and enabled, otherwise Refresh. The
AGENTS.md rule now says the fallback must be shown and enabled and a
control's visibility is decided once per update.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Check Cancel's focus against the control focused before the update, and test the disabled fallback (#194 review round 22)

Also word the fallback as "not disabled (aria-disabled qualifies)" in the
rule and the comment, drop the second write of Merge status's
visibility, and document every focus move in merge-handoff.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Merge renderMergeSteps' doc comments, and say Cancel is marked unavailable, not disabled (#194 review round 23)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test the display-only onAsking guard and a queued job's Merge step, and keep Cancel pending until the poll answers (#194 review round 24)

Also replace the last "disabled Cancel" and "until Refresh" wording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep Cancel unavailable until a poll stops reporting the cancelled job as running (#194 review round 25)

A poll already in flight could answer the job's older running record
and clear the wait early. The in-flight test now checks Cancel after the
held poll's answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Read the in-flight Cancel state once, test that a replayed click does not call onAsking, and note restart downtime in step times (#194 review round 26)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test the older-record poll guard, an inspection answering after shutdown, Fetch failing for review, and a joined click (#194 review round 27)

Also name the merge step bar in DESIGN.md's Frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test on the real preparation path that Fetch is still running when a moved head stops it (#194 review round 28)

Also list round 27's tests in the handoff doc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test that Merge stays waiting when the attempt is not saved, and Rebase and Push are skipped when nothing moved (#194 review round 29)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test a restart while a task cancel is stopping, a cancel refused after a failed ending write, and a held refusal ending when the job moves on (#194 review round 30)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test each merge step state's mark, word and DESIGN.md color (#194 review round 31)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test that a pending cancel stays with its own merge job (#194 review round 32)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep a cancel's wait when a poll answers for an older merge job (#194 Copilot review)

A poll that read an older job is discarded; it no longer ends the wait of a
newer job whose cancel was answered as ended first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Bind a cancel's wait to the job shown when its answer arrives (#194 Copilot review)

An older job's cancel answered late, carrying the newer job that has just
ended, no longer replaces that newer job's wait with its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hold the ended record a cancel's answer carried (#194 review round 35)

Cancel stays requested for every record older than the ended job the
answer carried, so a poll read before that job ended no longer offers
Cancel again. The poll no longer clears the wait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test a Refresh answered after a cancel; name Cancel merge in the running-merge refusal (#194 review round 36)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wait for each cancel test's answer to be shown, not a fixed time (#194 review round 37)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wait for Cancel's render, not a response or a fixed time, in the cancel tests (#194 review round 38)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Wait for a render or the next poll in every D16 no-change check (#194 review round 39)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add the no-change race check rule to AGENTS.md (#194 review rounds 37-39)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Prove the step timer ran; widen the no-poll window past the poll delay (#194 review round 40)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Check an unavailable Cancel sends nothing over the poll-delay window (#194 review round 41)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Poll for the recorded cancel instead of reading it at once (#194 review round 42)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep the latest ended record when a cancel answers late (#194 Copilot review)

An answer is newer than the record shown, not always than the one held:
across three jobs, an older job's late answer replaced a newer ended
record and let Cancel be offered for that newer job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test that a later ended record replaces the held one (#194 review round 44)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Present and keep a newer ended job a late cancel answer carries (#194 Copilot review)

When the page already showed its own job ended, an answer carrying a newer
ended job was dropped: its outcome was never shown and its record was not
kept, so a Refresh read while it ran could offer Cancel. The answer now
keeps the record and asks the poll, which follows a later job also after
the shown job ended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Poll until a newer ended job is shown; drop an older job's queue attempt (#194 review round 46)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test the cancel-answer path alone, polling's stop, and a later job's own queue attempt (#194 review round 47)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop an older job's queue attempt when a full reload keeps a newer job (#194 Copilot review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep observations made while a merge click is on its way over its answer (#194 Copilot review)

A late cancel answer could adopt the click's job, a cancel of it could be
accepted, and then the click's older answer replaced that record, offering
Cancel again. The click's answer is now reconciled like a full response.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep an ended job's view against a poll read earlier; keep a followed job on a racing click refusal (#194 review round 50)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Follow an ended job's own attempt by action ID; drop only earlier or foreign answers (#194 review round 51)

Round 50's guard dropped every queue answer for an ended job unless it ended
queued, so a job that ended submitted with its attempt in GitHub's queue never
reached Merged. A refused click now keeps any running job the page follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Follow its own attempt only for a job that ended queued or submitted (#194 review round 52)

A blocked or failed job drops a copy of its own attempt kept while it asked
GitHub; a submitted job follows its attempt on every path; a refused click
carrying a later ended record presents it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Leave a refused click's queued or submitted end to the poll; test the guard's ended-state check (#194 review round 53)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test that a refused click never presents an older ended record (#194 review round 54)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enforce a pre-spawn model budget for planning invocations

2 participants