Conversation
load_settings_in and load_projects_in resolve the record file for the read, then re-resolve it through global_dir() for the write-back. TERMIC_DATA_DIR is process-global and tests run in threads, so a with_scratch_data_dir window can flip it between the two resolutions: the migrated write lands in a settings.json/projects.json the load never read from. That clobbers the scratch a neighbouring test just wrote (the intermittent agent_hooks::...status_line failure), and flipped the other way drops test content into the developer's real data dir. Keep the already-resolved path for the write-back; the callers' doc comments already promise the write lands where the records came from. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
New Delivery tab in the right panel: select repos, inspect CI/review evidence per repo, prepare scoped agent requests (fix / replies / PR descriptions / conflict resolution), queue or send to a running agent tab, and import the agent's report back into draft cards. - Durable requests in delivery.json with scope summary, status lifecycle (prepared/queued/sent/drafted/failed/uncertain), reply drafts and PR text proposals; orphan queued requests reconcile against live queues. - Create PRs dialog drafts titles/bodies per repo or all at once, repeatable, auto-filling only pristine fields; reuses open PRs. - Per-item actions: fix failed CI checks and unresolved review threads individually or in bulk; draft replies per thread. - Board: Needs action filter, delivery chips on cards/members that jump to the task's Delivery tab. - Fix WKWebView disabled-trigger bug: DropdownTrigger/PopoverTrigger mirror child's disabled onto the Radix trigger (pointerdown opens disabled menus in WebKit). - Fix CiTree summary-wrapping bug: interactive controls inside <summary> toggled the disclosure; explicit open state instead. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Heads up, this branch now has a second commit ( |
|
Could you split this one? As it stands the PR is titled and described as a 23-line test fix, and carries a 4,099-line feature nobody has reviewed:
I would merge the first today. It is a better diagnosis than the one I pushed: I treated that flake as my own unsynchronised Worth saying that neither of us has reproduced it. You got 6 clean full-suite runs, I got 8 after my change. Two unproven fixes for one flake, and your caveats section is the right way to say so. The Delivery panel should stand on its own PR with its own description. It is not that I object to it, it is that I cannot review what the body does not mention, and at 36 files it is the kind of change that wants its own reasoning written down. Same request as #352, one step further: there at least the body said it was stacked. If the two are genuinely entangled, say so and I will read them together, but from the commit boundaries they look independent. |
Correctness: - import_report validates report shape and applies lists atomically; drafts are mandatory only for replies requests - amend rotates the request id and report path so stale queue copies can't send pre-amend text; kept evidence retains its snapshot - status writes return the replaced status so send paths detect races; same-status writes preserve a recorded error - results are retained per (repo, action) so a failed update row isn't erased by a later PR result - delivery.json corruption is parked aside instead of bricking commands - git/provider stderr is scrubbed of URL userinfo before surfacing - queued requests with no live queue item self-fail after two misses, exempting in-flight sends - spawn failures surface immediately via TerminalTab.spawnError Panel UX: - remove both checkbox selection models; every action now sits on its object: per-repo ⋯ menu, section-level bulk buttons with counts, per-item Fix/Reply controls, and an All-repositories header scope - request cards show kind + scope + status and can jump to the agent tab that received the prompt (recorded on the request) - reply drafts: save/copy/post with confirm, provider max length - PR drafting lives in the Create PRs dialog with per-repo remove - read-only probes use per-control spinners instead of locking the panel Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
What this fixes
An intermittent full-suite failure simion saw while verifying #353:
agent_hooks::tests::a_clones_status_line_is_read_from_its_own_config_dirfails ~once percargo testrun, passes alone, pre-existing onmain.The mechanism
with_scratch_data_dirserializes tests that redirectTERMIC_DATA_DIR, butTERMIC_DATA_DIRis process-global: tests that readglobal_dir()-derived paths without the lock can still straddle a neighbour's scratch window.That alone is a known hazard — but it produces writes through one specific path: the migration write-backs.
Both
load_settings_inandload_projects_inresolve the record file once for the read, run their migrations, and then callsave_*_in(id, …)— which re-resolvesglobal_dir()a second time at write time. If a scratch window opens in the gap, the write lands in a directory the load never read from:load_settings_innerresolves env → real/fixture path, reads a legacy-shapedsettings.json, setsmigrated→ write-back re-resolves → a scratch window just opened → the migrated copy lands over that scratch'ssettings.json, wiping the agent the victim test just saved → itsnext-claudelookup falls back to~/.claude→ assert fails.Why not lock the accessor instead
Gating
global_dir()(or the settings accessors) onDATA_DIR_LOCKdeadlocks:PORT_ALLOC_LOCKis held across task-create flows that callload_settings_inner, while scratch closures call task-creation paths that needPORT_ALLOC_LOCK.The fix
Both write-backs now write to the path already resolved for the read (
save_settings_at(&f, …)/save_projects_at(&f, …)), which is what their own comments already claim — "the write has to land in the profile the records came from".save_settings_in/save_projects_inkeep their signatures for explicit saves.Honest caveats
set_var/save_settings_*/global_dirwriter that can inject a foreignsettings.jsoninto a live scratch without an unlocked writer call.TERMIC_DATA_DIRpoints at mid-window (wrong data for their asserts — the "different test each time" signature from the comment intest_support.rs). Closing that needs the accessor gating ruled out above, or dropping the process-global seam entirely.Test plan
cargo test— 1216 pass on this branch