Skip to content

W3-01b: drain sessions before database maintenance - #335

Merged
mergify[bot] merged 3 commits into
mainfrom
claude/w3-01b-drain
Oct 4, 2026
Merged

mergify[bot] merged 3 commits into
mainfrom
claude/w3-01b-drain

Conversation

@Cuarroc

@Cuarroc Cuarroc commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Dieses Paket sorgt dafür, dass die Datenbank-Wartung erst beginnt, wenn keine Sitzung mehr läuft. Läuft nach zehn Sekunden noch eine Sitzung, wird die Wartung mit Nennung der Sitzung abgelehnt und nichts ändert sich. Nach erfolgreichem Start sind neue Starts und Schreibzugriffe gesperrt, bis die Wartung beendet wird; Updates können das nicht umgehen.

Report

What changed (173 added lines, main.rs + pty.rs; no store/api/bin changes)

  • pty.rs: PtyManager::begin_maintenance / end_maintenance latch. reserve_session (the single launch entry) and install_when_idle refuse while it is set; serialized through the registry lock.
  • main.rs: enter_database_maintenance freezes launches, polls owned sessions for a bounded wait (10 s), refuses by naming the live sessions (latch released, store untouched), then calls the W3-01a Store::enter_maintenance; leave_database_maintenance restores writes, then launches. Tauri commands enter_maintenance / leave_maintenance.
  • Tests (red-first, new in main.rs): refused while a session is active; drained maintenance freezes launches, updates and writes until leave; leave restores everything; maintenance refusals use the shared ERR_REFUSED vocabulary.

Evidence

  • Base: origin/main / merge base f48af09e48d26ec8ad27dcaa4bc21870e046a7d3; head 900d25397aed59b23cdfea77defa8fadd5ba4225.
  • Red-first observation: cargo test --manifest-path src-tauri/Cargo.toml tests::maintenance_refusal_uses_shared_error_vocabulary -- --exact --nocapture before the fix → exit 1, exact assertion failed on Maintenance refused: ....
  • Green observation: the same exact test after the fix → exit 0, 1 passed.
  • bash scripts/ci/red-first.sh --plan → exit 0, count=5, specs=5.
  • bash scripts/ci/gates.sh lane prepush → exit 0 (12/12 gates green; 1790 Rust tests passed, 17 skipped).
  • Push hook reran lane prepush at head 900d253 → exit 0 (12/12 gates green; 1790 Rust tests passed, 17 skipped).
  • git ls-remote origin refs/heads/claude/w3-01b-drain → exit 0 and exact remote head 900d25397aed59b23cdfea77defa8fadd5ba4225.

Architecture drift: one medium finding was fixed. The timeout refusal at src-tauri/src/main.rs:1135 used a new Maintenance refused wording instead of the canonical prefix at src-tauri/src/errors.rs:13; commits eded577 (red test) and 900d253 (fix) now use the existing ERR_REFUSED pattern. No second state, lock, IPC-result, or Rust-to-frontend event pattern was introduced.

NICHT ABGEDECKT

  • The Windows prepush run does not compile #[cfg(unix)] tests or Linux clippy arms (KNOWN_ISSUES KI-7); the Linux half is covered by the merge-queue/CI lane, not this local run.
  • No GUI/frontend caller of the new commands; not exercised in the running app.
  • Sessions that start between the drain poll and Store::enter_maintenance are impossible (latch set first), but a long-lived running session simply refuses maintenance; no forced kill by design.
  • External services (updater endpoint, OmniRoute, mirror) are outside the prepush gate.

Review disposition

Candidate: 900d25397aed59b23cdfea77defa8fadd5ba4225. Author family: Claude.

  • Codex reviewer — model identifier not exposed by the session — C1, medium, src-tauri/src/main.rs:1135: new refusal wording drifted from src-tauri/src/errors.rs:13 and docs/architecture-rules.md:31-34. Accepted: red test in eded577; production fix in 900d253.
  • Ollama reviewer — requested glm-5.2:cloud, reported glm-5.2 — initial F1, low, src-tauri/src/main.rs:1144: requested a test for store-enter failure cleanup. Rejected after countercheck: no demonstrated defect; the branch explicitly releases the PTY latch, and the package's red-first tests cover the observable refusal contract.
  • GLM initial F2, low, src-tauri/src/main.rs:1152: requested a test for store-leave failure. Rejected after countercheck: keeping the launch freeze on store failure is the documented fail-safe behavior; store transition failures are already covered in src-tauri/src/store/maintenance_tests.rs:6.
  • GLM initial F3, low, src-tauri/src/pty.rs:805: requested a dedicated installation-started guard test. Rejected after countercheck: no incorrect behavior or reachable bypass was shown; begin_maintenance and install_when_idle share the registry lock.
  • GLM initial F4, low, src-tauri/src/main.rs:1121: questioned 50 ms polling. Rejected after countercheck: the loop is bounded, the 50 ms interval is intentional, and no correctness or resource failure was demonstrated.
  • Ollama reviewer — requested glm-5.2:cloud, reported glm-5.2 — final F1, medium, src-tauri/src/main.rs:1115: alleged that concurrent leave during drain can clear the PTY latch. Rejected after countercheck: Store::leave_maintenance returns MaintenanceError::NotActive at src-tauri/src/store.rs:1038, so pty.end_maintenance() is not reached; if enter wins the store mutex first, enter then leave is a valid serialized order.
  • GLM final F2, low, src-tauri/src/main.rs:1144: repeated the store-enter cleanup test request. Rejected: same evidence as initial F1; no fault survived countercheck.
  • GLM final F3, low, src-tauri/src/main.rs:1152: requested leave-without-enter coverage. Rejected: src-tauri/src/store/maintenance_tests.rs:33 already proves NotActive, and the ? in leave_database_maintenance preserves the PTY latch on that error.
  • GLM final F4, low, src-tauri/src/pty.rs:805: suggested rejecting maintenance while emergency stop is active. Rejected: the two process-local safety latches are independent by design; emergency stop still blocks launches, and no unsafe transition was demonstrated.

No high-severity finding remains open. No second review round was required for a high finding; the final full-candidate GLM run nevertheless revalidated the changed candidate and returned approve with conditions, whose only medium condition was disproved against the real Store implementation.

Freeze new PTY session starts, wait a bounded time for owned sessions to
finish, then reserve the database through the W3-01a store APIs. A session
that outlives the wait refuses maintenance by name and changes nothing.
Updates refuse while maintenance is active; leave restores launches/writes.

Test-First: src-tauri/src/main.rs::tests::maintenance_is_refused_while_a_session_is_active
Test-First: src-tauri/src/main.rs::tests::drained_maintenance_freezes_launches_and_writes_until_leave
Test-First: src-tauri/src/main.rs::tests::leaving_maintenance_restores_launches_and_writes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Cuarroc
Cuarroc marked this pull request as ready for review October 4, 2026 17:35
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T17:41:57.887825Z 56cd6d1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56cd6d11b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/pty.rs
Comment on lines +795 to +796
if self.maintenance_active.load(Ordering::Acquire) {
return Err("Database maintenance is active; leave it before starting sessions".into());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Behandle Wartungssperren in der Queue als vorübergehend

Wenn während der bis zu zehnsekündigen Drain-Phase noch Queue-Kapazität frei ist und der 30-Sekunden-Poller eine bereite Aufgabe startet, erreicht LiveLauncher über workers::create_worker diese neue Ablehnung. dispatch_project behandelt jedoch jeden Launcher-Fehler in queue.rs:465-467 als terminal und setzt den Eintrag auf failed; dadurch kann bereits eine später abgelehnte oder auslaufende Wartungsanfrage eine wartende Aufgabe dauerhaft verlieren. Die Wartung muss den Dispatcher vor dem Claim pausieren oder diese Ablehnung als transient behandeln und den Eintrag wieder auf ready setzen.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/pty.rs
Comment on lines +795 to +796
if self.maintenance_active.load(Ordering::Acquire) {
return Err("Database maintenance is active; leave it before starting sessions".into());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Präfixiere Wartungsablehnungen mit ERR_REFUSED

Wenn ein Start während der Drain-Phase über POST /api/workers hier abgelehnt wird, erkennt api::core_status in api.rs:2228-2235 nur das gemeinsame Präfix refused: und stuft diesen neuen freien Fehlertext deshalb als HTTP 500 statt 409 ein; auch ipc.ts::describeError normalisiert nur dieses Präfix. Verwende für diese und die übrigen neu eingeführten Wartungsablehnungen crate::errors::ERR_REFUSED, wie es Architekturregel 5 vorgibt.

AGENTS.md reference: AGENTS.md:L298-L301

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/main.rs
Comment on lines +1130 to +1131
if live.is_empty() {
break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Warte auch auf noch nicht reservierte Starts

Wenn create_worker bereits den Worktree und die running-Workerzeile angelegt hat, aber noch nicht agents.spawn_bound in workers.rs:583-590 erreicht hat, ist die PTY-Registry hier leer und die Wartung kann erfolgreich beginnen. Der anschließende Reserve-Versuch wird abgewiesen; bleibt die Wartung länger als den fünfsekündigen SQLite-Timeout aktiv, schlägt auch das ignorierte delete_worker in workers.rs:599-601 fehl, während der Worktree trotzdem entfernt wird, sodass dauerhaft eine laufende Workerzeile ohne Worktree zurückbleibt und ein währenddessen erzeugtes Backup diesen Phantom-Worker enthält. Erfasse Starts daher vor ihren Worktree-/DB-Nebenwirkungen in der Drain-Registry oder reserviere sie bereits davor.

Useful? React with 👍 / 👎.

@mergify

mergify Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Queued — the merge queue status continues in this comment ↓.

Test-First: src-tauri/src/main.rs::tests::maintenance_refusal_uses_shared_error_vocabulary
Test-First: src-tauri/src/main.rs::tests::maintenance_refusal_uses_shared_error_vocabulary
@Cuarroc

Cuarroc commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify mergify Bot added the queued label Oct 4, 2026
@mergify mergify Bot mentioned this pull request Oct 4, 2026
11 tasks done
@mergify
mergify Bot merged commit e4a6425 into main Oct 4, 2026
11 checks passed
@mergify
mergify Bot deleted the claude/w3-01b-drain branch October 4, 2026 18:48
@mergify

mergify Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 12 minutes 37 seconds in the queue, including 12 minutes 21 seconds running CI.

Required conditions to merge

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.

1 participant