Repository navigation
Merge app/v3 into workstreams/main (sync 5) - #2355
Merged
Merged
Conversation
* test(factory): Stop must survive queued manager questions and restart Reproduce job 64 through factory.job_stop and an automatic team wake calling factory_start. Intentionally red; no production fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): deliver the question asking event and require acknowledgement The team watcher wakes on the asking event beside a question. Require a completed fake model tool result or an explicit stopped-wake receipt rather than passing on timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): deliver late question traffic to an open manager A new conversation intentionally skips team history older than its listening boundary. Deliver the pending question after opening, retaining the real Stop and restart paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): use the Talk seam directly for historical replay Keep the regression portable to the engine commit before 2312, where the test helper did not exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): require zero model calls after person Stop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): assert Stop at launch and decision seams Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): preserve person Stop across execution and automatic wakes Gate launch and admission on the durable person-stop record, while keeping person chat available. Honour surviving legacy Stop evidence and retain the publication boundary checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): apply Stop to ready and permission projections Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): cover explicit restarts legacy stops and proof-only jobs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): withdraw automatic brief work when a person stops The fake model counter exposed brief-writing calls after Stop. Skip those calls and classify no-step stopped outcomes without requiring a step failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): identify remaining calls and configure restart fixture offline Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): stop an in-flight manager wake and preserve person chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): retain person chat and recheck final readiness writes Distinguish explicit revoked or granted authority from legacy missing records. Preserve terminal controls, carry on from all stopped shapes, withdraw uncollected signals, and stop automatic continuation calls. Lower-seam tests now grant explicit person authority before their existing restart assertions; no-step tests additionally assert durable Stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): cover sync legacy wire and readiness preparation races Preserve legacy field presence on the job wire, retain person answers queued during a response, and exercise final-readiness cancellation after preparatory reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): refuse late automatic tool batches after person Stop Record honest paired refusals for tools returned by an already-running automatic call. Preserve person steering, support standalone proof and PR stops, and treat explicit Resume pipeline as a person grant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): honour explicit legacy stop receipts on the ended phase Keep generic activity and stream prose out of execution authority; a typed stopped failure on the current ended phase is durable evidence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): drive real manager queue and GitHub entry points after Stop Use manager tools, worker admission, a reopened desk and the GitHub poll with new commits. Verify each person restart control executes its check step after obtaining a lease. Apply box-produced gofmt output to unchanged implementation files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): fix runner fixture result and explicit restart permission Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): cover retries and person messages during stopped wakes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): close automatic retry admission after person Stop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): let unexpected automatic retries fail without hanging Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(provider): require route admission before each retry send Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): enforce Stop at every provider send including transport retries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(factory): format durable Stop changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): keep stopped person chat free of automatic naming spend Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): bind naming attempts to the stopped job authority Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(session): format automatic Stop admission Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(provider): format per-send Stop regression Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(factory): format final Stop admission regressions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(factory): describe Stop while proof awaits sign-off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): preserve Stop refusals and settle unpaid briefs Keep Resume limited to paused work, cancel surviving runner controls after another Stop door, and consume the runner wake subscription before testing person replies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): format Stop regressions and document unpaid settlement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): bound Stop fixtures and cover briefs without a writer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): retain paid brief content across a late reply after Stop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): refuse late brief replies after Stop Count actual worker executor starts when proving Stop blocks further paid steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): settle stopped brief reads without a background writer Project failed status and the Stop reason directly, retaining the paid brief. Remove the obsolete Resume restart helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(factory): align worker execution counter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): resume stays refused on a stopped job; Carry on is step rerun Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): add live question-pending Stop check Exercise the app wire, delayed manager question, Stop watch, chat, engine restart and explicit step rerun under a pinned-model $0.10 cap. The first live attempt failed during the post-Stop watch because one request had no recorded cost; retain the failing check without changing product code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): reproduce four post-Stop authority gaps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): account for unpriced requests cancelled by Stop Permit missing cost only for cancellation after the person invokes Stop; reserve the highest observed call cost for each and report their count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(session): Stop cancels commands while person chat completes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): reproduce poststage and repair description writes after Stop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): show queued traffic when live Stop acknowledgement is missing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): exercise revoked lease through the worker HTTP adapter Keep the original paid-step and revoked-lease assertions; deliver the server refusal through the same typed client error the real runner receives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(factory): describe Stop at write and paid-step boundaries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): recheck Stop after forge merge-method lookup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): verify healthy manager work and revoked runner settlement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(session): Stop cancels manager owned work while person chat finishes Watch person-stop refusal as well as budget. Reuse owned-family StopWork cleanup, retaining only a foreground answer to a person. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): recheck current authority before merge and proof comments The supplied red probes reproduce on the same product files: no diff from ca1cff4 to the starting HEAD. Reuse publishBoundary and worker CheckPublish immediately before writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): refuse the next paid step after lease revocation Recognize the existing worker lease-gone sentinel, which includes withdrawal. Other read errors keep the stored Stop-after-step choice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): cancel the withdrawn runner lifetime at the step boundary Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): guard repair, poststage and prepared merge writes with current authority Reuse publishBoundary for poststage pushes and writes and for repair descriptions. Carry the existing BeforeWrite callback through forge merge-method preparation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): forward post push checks and format Stop changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): preserve queued person answers and use the recorded live room Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): reproduce live factory and manager profile mismatch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(session): cancel factory owned work without closing person chat admission The queued-person regression fails when StopWork discards followups. Reuse existing task and background job cancellation, preserving the conversation and all person answer queues. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): deliver live Stop traffic to the job recorded room The named regression reproduced delivery to a newly minted unrelated room when the current title differs from the saved crew name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): align live factory and manager profile before opening either The named regression proved that the fake backend used CODEAF_HOME while the real manager used CODEAF_PROFILE_DIR, so delayed traffic never reached that manager. Keep both on the same disposable profile, including after restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(session): reproduce serial Stop delay across manager commands Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(session): signal all stopped manager commands without serial grace The two-command regression reproduces a TERM-resistant command delaying cancellation of its sibling. Run the existing per-command cancellation concurrently and join every cancellation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(session): require a current Stop receipt beside the manager answer The live manager explained Stop correctly but omitted the canonical stopped/Start receipt. Keep the live assertion intact and cover deterministic receipt delivery independently of model paraphrasing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(session): show the current factory refusal before a person chat answer The live answer paraphrased Stop correctly but omitted the exact stopped/Start receipt. Record and emit the existing authoritative refusal, then continue the normal person answer; automatic turns retain their existing refusal path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): reproduce unpriced cancellation in live ledger call counts Live5 reached restart with unchanged spend but requests=12 and paid ledger calls=11, exactly one allowed unpriced cancellation. Retain paid-call equality with a regression for that accounting policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): reconcile paid ledger calls with unpriced Stop cancellations Exclude only the recorded allowed unpriced cancellations from paid-call equality. Continue reserving each at the highest observed price; actual cost, model checks, caps and stopped-state assertions remain exact. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style(factory): format final Stop regressions and receipt policy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test stopped brief classification and repeated hold gates Exercise factory.job_brief after a person Stop, retain paid content, and require stopped classification to survive both wire shapes. Cover drain and heartbeat holds against a durable Stop record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cover repeated hold while stopped round cleanup is pending Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document stopped brief classification and hold precedence Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test stopped classification in an in-flight brief write response Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep person Stop authoritative for holds and classify stopped briefs Carry failure_kind stopped only from the durable person Stop through the factory API and app wire. Preserve failed status and the last paid brief. Reject Hold before idempotent shortcuts and suppress queued or repeated hold signals after Stop without changing pauseMu ordering. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Format stopped brief regression fixture Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Preserve Hold refusal wording while retaining the Stop error The existing factory.job_hold regression requires is not running after Stop. Wrap the durable Stop error with the original door refusal, preserving both wire compatibility and errors.Is classification without weakening tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: healthy workers can merge and post after approval Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: allow healthy leased writes; test authority outage admission Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hold paid steps when Stop authority remains unknown Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: honor Stop check before simple forge writes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: bind manager Stop cancellation to sampled producers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: distinguish rig Stop cancellation from later timeout Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require rig cancellation of a request open at Stop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: late Stop cannot cancel a retried task with the same ID Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: stale budget reads cannot stop a resumed manager Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: wait for sampled Stop to finish before inspecting task retry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: bind delayed cancellation to task attempts and work epochs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: authority outage hold reaches the worker floor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: report unknown Stop authority as a waiting boundary decision Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: held work retries once and resumed manager completes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a 503 after durable Stop cannot admit the next paid step Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format Stop regressions and guards Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: unread budget holds admission without cancelling existing work Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: retain the scripted provider for admission assertions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: temporary budget read errors recover without replacing the meter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: budget read uncertainty holds admission without cancelling work Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format budget uncertainty regressions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: expose unpriced Stop request lifecycle and retain red accounting regression Record timing, HTTP status, stream completion, client closure and purpose without logging request content. Preserve missing-cost rejection and the red pre-Stop completion specification. Live request 16 began after the person rerun and is not eligible for the open-at-Stop cancellation exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix Stop live accounting windows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Format Stop accounting table cases Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: name the pull request Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…re read once the repository is here (#2324) A start read that had no GitHub yet and no checkout was kept as a failure and never asked again, so a repository with no file started "unread" and its plan waited. Reads like that are now asked again by an action, and after 15 s by any read, under a name that ignores case. A repository with no file is now said plainly (start_rules.no_file) and holds nothing. A read that could ask nobody (start_rules.pending) stays held but is read again after the clone, before the first model call. A failure keeps today's hold with the real reason. A wrong "not found" no longer relaxes a repository's rules: a 404 only means no file once the repository itself answers, and a checkout git can't read fails. Memory compilation no longer reaches the chat's stream: its context kept the turn's observer, so its JSON drew in the conversation as if the agent said it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ng it (#2315) * factory: a job that has not worked reads its issue instead of repeating it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: first read Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * factory: a copied claim or title cannot hide under own words; a stub never repeats the title Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * factory: before work only the issue moves the read; a read's questions carry no markup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: first read uses the added kind Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * factory: the no-touch test's issue has words, since a thin issue writes no brief Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test: reproduce absolute paths in owed verification commands Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: keep portable receipt identity scoped to measured known tools Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: make owed check commands portable without crediting unmeasured runs Saved absolute argv and unmeasured shell commands leaked machine paths into guard debt. Normalize recognized measured tool identity and literal owed text while retaining raw receipts and conservative unmeasured coverage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require missing-path diagnostics for quoted owed executables Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format portable verification commands and regressions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: index portable owed commands by absolute executable paths Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: explain missing literal quoted executables in owed commands Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: name the pull request Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test: require person publish anyway through job and post paths Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: refuse publish anyway by another person Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: allow a person to publish past correctly skipped checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: cover scoped consent and refused publish anyway cases Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format publish anyway implementation Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require known files and normalized policy for override Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require authenticated press and document publish anyway Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require a new person press after a rerun Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: retain measured passes and recheck skipped conditions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: authenticate override and require known nonmatching files Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: carry person publish decision through a held worker Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: launch held-worker fixture through its server door Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: deliver scoped person consent to the held publishing worker Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: use worker error constructor for changed consent Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: validate portable person receipts at the post seam Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: preserve files-bound receipts and document publish action protocol Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: list publish anyway in the protocol method table Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: register the person publish action server contract Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: format and review the person publish action Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: reproduce publish-anyway handle injection through post Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: preserve existing approval normalization in injection regression Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: restrict publish-anyway PR attribution to plain logins Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * changelog: name the pull request Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(factory): Publish anyway isn't offered on a stopped job Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test: judge take rows only after the take starts; wait for the backend Close appNoEndedTake read rows from before the take began, so the chat feed's first row, correct when sent, failed the two landed-take tests about 1 run in 10. It now judges rows after the first Taking:true row and fails if there is none. Closing the test wire starts Close through Serve, so the cleanup's own Close returned at once and device listeners outlived the availability override. appDeviceBackend now waits for the running Close to finish. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: change entry for the take test fix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test(factory): specify shipped step method boundaries * feat(factory): teach concise methods in shipped step briefs * test(factory): ratchet method sizes and exercise real placement * test(factory): require conflict ownership and tighter method budgets * fix(factory): assign conflict resolution and trim step methods * test(factory): require repair rules without follow-up context * fix(factory): retain Follow PR rules without active follow-up * test(factory): select Follow PR stage independently of phase index * style(factory): format shared repair rule concatenation * docs(factory): number the step instructions change entry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(factory): specify evidence reuse and unrun-check reporting * fix(factory): reuse verification evidence and distinguish unrun checks * fix(factory): fit Test guidance within its reduced budget --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* A running step's chat streams like the manager's A step runs on its own session agent, so the app's hold on that conversation only read its journal and an open chat stayed frozen. Each step event is now told to the app. For a held chat, words go out as deltas and the journal's new entries are read back under the listing's own ids, at most five times a second per chat and off the step's own events. A chat nobody holds costs a lookup of its id and reads nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Unlock a step chat's saying from a defer The guard law requires it: an absorbed panic in a bare critical section would leave the stream locked and deadlock the step. Behaviour is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ny are not shared yet (#2341) * fix(sync): background publishing is bounded by progress, rescans and goes small and recent first A background publish of an existing chat had cellstore.SealWithin (30 s) for the whole chat, so a chat whose saved folder could not be uploaded in 30 s failed on every attempt and was never listed on the other computer. - syncsetup.PublishIdleWithin (2 min) is time without an answer from the relay; every frame put or holdings answer starts it again. - cellsync.Publisher.Upload records the frames an interrupted upload put, so the next export packs only what is still missing. - Every pass rescans for chat folders not seen yet, including finished copies of older chats in a project's `.moving` folder (unless the original works in the home folder), and offers untried chats newest first, then tried chats smallest upload first. - One log line per chat and outcome: duration, bytes sent of bytes to send. - Sync.CountUnshared counts cell chats with nothing shared yet, from disk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): one publisher per home copies older chats, and both surfaces say what is not shared yet Older chats (a journal, no cell) were copied and shared only while a terminal was open, and the app engine and a terminal on the same home each ran their own publication pass over the same chats. - Whichever process holds the home's sharing lock (v3/sharing.lock) publishes and copies at most one older chat a round; the app engine now does this too. The 30-day and home-folder rules are unchanged. - sync.get / sync.changed carry Sync.unshared {total, waiting, failing, kept_here}: this computer's chats with no directory record (PROTOCOL.md). - The terminal says it on the home devices row ("12 chats on this Mac aren't shared yet") and, with why, on /devices. - Change entry still needs its PR number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): only waits on the relay count toward the stall budget, and the log counts bytes that landed The no-progress clock started with the attempt, so packing a large chat on this computer used up the budget before a byte went out and the chat failed every attempt. Each request to the relay is now timed on its own; local work between requests is not. The log's "bytes sent" counted puts that failed or were cut short; it now counts only frames the relay accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a shared copy of a home-folder chat is not counted, and kept-here chats are not promised to be shared The count kept every copy of a home-folder chat as kept here, even one shared when it was made. The /devices sentence and the wire docs said older chats are shared once opened, which is not true of chats that work in the home folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): only a background upload keeps the frames of an attempt cut short Publish and Branch name the frames they put in the head's plan. Recording the frames of a failed attempt left them out of the retry's export, so a branch was created without naming orphan frames only its own upload writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a slow frame gets time to send, a vanished chat is forgotten, and a chat shared earlier is not logged again - A frame now gets the time to send it at 64 KiB/s on top of the two-minute budget, so one large frame over a slow uplink is not read as a stall. - A pending chat whose folder was deleted or moved was retried at its old folder for ever and never found where it is now; it is forgotten, and the rescan finds a moved one. - Every launch logged "shared" for each chat already listed; those need no line. - The progress test had 150 ms of margin and failed under load; it has more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(tui): the /devices sentence agrees in number for one chat It read "1 are still uploading" and "1 older ones are kept". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): keys, memory and preferences are shared before the chat backlog The app shared them after the round's chat pass, and a pass now lasts as long as its uploads keep moving, so a computer just paired waited for this one's whole backlog. They go first; a chat pass that went well does not clear their failure line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): the process that does not share a home shows the holder's count Only the holder of the sharing lock knows which chats failed and which the directory already lists, so the other process counted those as waiting. The holder now writes its count beside the lock and the other process shows it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a pass stops once sync is turned off, and lets its caller work between chats - A pass lasts as long as its uploads keep moving. Once sync was turned off, every chat left in it failed in turn, each with a failure line and a retry; the pass now stops. - Sync.BetweenChats runs between the chats of a pass with its lock released, so a caller can count and do its other sharing work during a long pass. - The progress test now runs longer than the budget in all, so a single deadline for the whole attempt would fail it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): the sharing line follows what failed, and keys and the count move on during a long pass - The app's sharing line is worked out from what is failing now, so a keys failure line goes once the keys are shared, even while a chat keeps failing, and a passing round clears an earlier "could not finish" line. - A failed pass over keys, memory and preferences is retried between chats, not after the whole backlog. - The count of chats not shared yet is said between chats (at most every ten seconds), in the app and the terminal, instead of only after a pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the N5 entry says what the review fixes changed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): the count's locks and the pass's relock come undone from a defer The guard law wants every critical section to unlock from a defer, and the pass took its lock back after BetweenChats without one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(app): a count that stays absent emits no sync change The publication loop files an absent count whenever sync is not on. It checked the whole status each time, so the first round emitted a sync.changed of its own before the app had answered its first request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the N5 entry carries its PR number 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>
* test runner: a shard mismatch names its tests instead of exiting silently Outside the C locale comm failed on the runner's C-sorted lists, so set -e ended the run with no result line, and a whole package looked like it never reported. The mismatch now fails the run and names the missing and extra tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: change entry for the shard mismatch fix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Fix take ledger identity and late receipt ownership Share each live usage row's identity with its saved model call and serialize append-if-absent across ledger writers and local processes. Keep accounting owners bound to their creation home, including late receipts after quit. Retain the documented legacy prefix fallback and join admitted hosted-test receipts before removing their home. Preserve pricing and spend calculations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Name the pull request in the changelog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: preserve usage identity across mixed history and shutdown Mark supplied call identities so new unsealed receipts cannot cover legacy calls. Validate cached ledger generations and retry a rotated charge on the active file. Retain closed agents until their admitted receipts settle and join them under the provider bound before closing usage writers. Stream historical rows through a reused compiled JSON decoder, retaining full row validation and the existing flush ceiling. Public accounting regressions cover all four findings without changing prices or spend arithmetic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: validate cached usage rows before suppressing replay An interior rewrite followed by growth can preserve sampled ledger ends while removing a cached identity. Retain row positions and verify the actual row before suppressing a charge; rebuild stale positions under the ledger lock. The public regression now records the expected $0.202 across 202 rows. Keep the append descriptor write-only and validate a separate read descriptor, preserving blocked-sink opening behavior and flush deadlines. Synchronize the shutdown regression on its real receipt waiter instead of a scheduling window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix remaining take ledger identity and receipt ownership gaps Mark modern unbilled and remote rows outside historical call coverage. Track settlement independently of Factory readiness and share admitted receipt ownership with descendants before child construction publishes them. Rebuild identity membership after external ledger changes, including restored interior identities. Replace the FIFO drain fixture with a locked regular ledger while preserving deadlines and verifying every overflow charge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix review gaps in usage provenance and restored remote spending Live producers now receive modern provenance at the shared recorder; saved historical imports retain their explicit ordered-prefix path. Validate remote event membership against the ledger generation before accepting or suppressing replay, covering replaced and rewritten ledgers. Restore stop and quit retrieval and route the retired-child receipt fixture through a supported title errand. Retain public-seam money regressions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Preserve mirrored event identity through take and restore stop lookup Remote charges lost their event identity in transcript digestion, and any ordinary sealed call excluded remote transcript spending from take. Retain that identity, import both sources, and reconcile charge keys under the ordinary writer lock as well as during take. Old remote event rows cannot cover unidentified ordinary history. Cover supported historical and modern combinations through real round-trip takes. Shorten the manual additions and validate the whole retrieval corpus. State the limit for earlier imports that erased remote provenance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix usage writer overflow throughput with bounded identity batches Validate one ledger generation and append up to 128 admitted rows under one file lock. Per-row prefix hashing and descriptor setup caused the 20,000-row race regression to exceed the unchanged flush deadline. Carry the recorder's charge identity alongside encoded rows and deduplicate within each batch. Keep quiet writes immediate, publish cached identities after append, and complete flush and overflow barriers after writes. Retain a public writer benchmark with exact charge verification and document the batching bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: classify the retired-receipts goroutine Its wait on a closed agent's admitted receipts is bounded by waitV3Receipts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: gate results for the ledger identity branch The process-writer helper's -test.v lines reached this binary's stdout, so the shard runner counted four extra results and internal/session got no verdict. Each helper's output is now captured and shown only on failure. The retired-receipts goroutine unlocks from a defer. The local usage schema baseline names the additive shared_id field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: pin usage ledger bytes without shared identity Pin the exact UsageLine JSON emitted by origin/app/v3 when shared_id is absent, including the existing row ID and adjacent billing fields. Document shared_id as an optional saved-format addition verified with separately built readers and base rewind and continuation doors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…2333) Every pass, every two seconds, ran one full scan of the knowledge events per job session to mark that session's events, even with Memory off. The marking now runs after the Memory check and seeks through a partial index that holds only events not marked yet. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… cancelled (#2348) * feat(sync): a move reports its bytes and stops when nothing comes through for 2 minutes - blobstore.WithTraffic: the store wire reports each request's start and end and the bytes it moves as they move. - syncsetup.TakeOptions.OnMove hears the step (preparing, copying, opening) and bytes copied, with the record's size as the total when this computer does not already hold most of the chat. - TakeOptions.IdleWithin (MoveIdleWithin, 2 min) ends a move whose request waited that long with nothing coming through: ErrMoveStalled. Local work between requests never counts against it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(app): chat rows say how a move is going and how it ended; moves can be cancelled - agents.take reports through its row: move {state queued|moving, step, done, total}, emitted at most four times a second off the copy's own goroutine. - A move that did not move the chat leaves move_ended {outcome stopped| failed|cancelled, line, detail} on the row until the chat is here or another move starts, so the app always learns how a move ended. - Moves stop after 2 minutes with nothing coming through, with a sentence that names the computer the chat is still on; missing objects and an unreachable relay get their own sentences. Other failures keep the existing sentence, with the error as detail. - agents.take_cancel cancels a running or queued move. Moves still run one at a time, now behind a slot a queued move can leave. - hello advertises chats.move; PROTOCOL.md documents all of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(sync): a chat's record says how many bytes a copy takes The record's size field was always 0. Publishers now set it to the bytes of the frames the plan names, which is what a computer without the chat copies, so a move shows "412 of 1,433 MB". - A new record starts it; a known size grows by each publish's frames. - A plan begun before sizes were kept stays 0 (unknown) rather than counting only its latest frames. - Takes and drives carry the size from the record they hold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(sync): another computer's chat row says how far its sharing has got - A beat carries how far the upload of pending turns has got (upload_sent/upload_total), only to a relay that answers Codeaf-Upload-Progress: 1; the lease keeps it until the next publish, release or acquire. The Go relay advertises it. - The publisher reports upload progress per frame; the batcher beats again when it moves on (every 30 s at most, as before). - Chat rows carry sharing {pending, sent, total} when the holder has sealed turns it has not shared yet. can_take is false then while the holder is a known computer; a removed or unknown holder never finishes, so its chat stays takeable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(tui): a continue says how much has come through and why it stopped - Home's line follows a running continue every half second: "copying to this computer: 412 of 1,433 MB…", then "opening it here…", and only while home still shows that continue's line. - The terminal's continue stops after 2 minutes with nothing coming through, like the app's: "stopped: nothing came through for 2 minutes; the chat is still on <computer>". - chatMover is chatContinuer without the vault notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): chat move progress entry (PR number later) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(sync): chat rows say which folder a move copies and how big it is - Records carry the sealed name of the folder a chat works in (folder), sent only to relays that answer Codeaf-Chat-Folders: 1; the Go relay does. A publish without one keeps it, like the title. - A chat shared in the background gets a size: the frame bytes its upload attempts put. - Chat rows carry folder and size (absent when this computer already has a copy), so the app can ask before a big move. - The terminal's continue card says, over chatlist.BigMoveBytes (100 MB), that moving the chat copies its folder too, and how much. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): chat move progress title fits on one line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a move cancelled or stalled after acquire still hands the lease back Cancel and the stall watch end the take's context, and every release-on-failure used it, so a move stopped while opening left the chat fenced here until the lease lapsed. Releases now go out on a fresh context bounded by handoff.GiveBackWithin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(app): a move keeps the engine's own refusal, and a second take of a moving chat is refused - Sync off, an older chat that stays here: the sentence reaches the client as it is, not as the generic one with the words as detail. - A second agents.take of a chat already moving answers busy, so the first keeps its Cancel and its outcome. - The terminal says a stalled move stopped, not that sync was unreachable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: a cancelled move hands its lease back; a second take of a moving chat is busy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a Cancel during the acquire request leaves no lease behind The acquire runs to its answer on a context Cancel does not end (the directory client bounds it), and a lease won for a take that has ended is handed back, so a relay that commits after the person cancelled never leaves the chat fenced here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(app): a holder's sharing is judged again when its presence changes, and its byte counts stay in range - A presence-only refresh lifts the block when the holder's presence becomes unknown, not only sets it. - upload_sent/upload_total past int64 clamp instead of going negative and breaking the desktop's list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sync): a move cancelled during the acquire never reads as opening Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the chat move progress entry carries its PR number Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the chat move progress entry says pr 2348 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…d figure, and late receipts save it (#2347) * session: a late recovered charge reaches the saved spend, and saves say so A receipt recovered after a cancelled turn ended moved the meter and the machine ledger but never meta.json, so every reader of the saved total under-reported until another turn sealed. reconciled now stamps the cumulative meter after banking. Spend stamps hold one mutex from capture to write, so an older captured total cannot land after a newer one, and each successful save is told to OnSpendSaved with the conversation's folder and the saved figure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * app: agents.open and every agent.changed carry the saved spend agents.list reports Only agents.list set Agent.spent_usd. The open answer and every agent.changed now carry the figure saved in meta.json, read in the same step that says the agent (beside unread), so a view copied earlier cannot deliver an older figure. A spend save restates the agent once, off the stamping goroutine, when the figure differs from what was last said. Other method answers keep their path and omit the figure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: saved agent spend in open answers and changes, and after late receipts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name pull request 2347 in its change entry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: agents.take carries saved spend because it answers through agents.open Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * app: saved-spend restate locks unlock from a defer The guard law requires every critical section in the guarded tree to unlock from a defer directly under its Lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
Checks on the merge commit
Landing on 🤖 Generated with Claude Code |
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.
Gate PR for a catch-up merge:
app/v3at1f1a733c5(15 commits, including #2347 agent spend being complete) intoworkstreams/mainatb1a02be03. No conflicts;internal/session/loop.goandsession.goauto-merged and are gofmtclean. The merge adds no code of its own. It lands on
workstreams/mainby fast-forward to the merge commit once itschecks match
app/v3's baseline.🤖 Generated with Claude Code