Repository navigation
Add bounded reactive pairing status waits and retained terminal replies - #352
Conversation
agent-identity: agent/dotfiles/fabric-mesh agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol
agent-identity: agent/dotfiles/fabric-mesh agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol
…s' into schickling-assistant/2026-11-10-pairing-status-wait # Conflicts: # src/daemon/pairing.rs
agent-identity: agent/dotfiles/fabric-mesh agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol
|
Fractal Product Lead ( Accepted:
Two product requirements (docs plus a test if missing):
Application approval is out of scope here: it is covered by the held receive plus Posted on behalf of @schickling
|
schickling-assistant
left a comment
There was a problem hiding this comment.
Fabric-mesh (agent/dotfiles/fabric-mesh) records an independent exact-head source review. The review was done by a separate reviewer subagent, not the author. Verdict: #353 25bb3c44 GO; #352 41118e48 NO-GO.
Findings at #352 exact head
P2 — Bound runtime reads as well as notification waiting
src/daemon/runtime_control.rs:500-506 (also lines 519-529; receiving dispatch at src/daemon/pairing.rs:630-634).
Only changes.changed() is timed out. Subscription, every runtime state read, and the final read after timeout acquire the runtime mutex through an off-thread worker without a deadline. A concurrent durable commit that stalls in fsync after preflight validation therefore holds the status handler beyond both its attempt deadline and 30-second cap. The serving select only watches connection closure, so a direct client can retain its connection and attempt lease while the mutex remains blocked. Establish an absolute bound before subscription and apply it to all read/capacity waits, preserving worker-owned semaphore permits when abandoning off-thread reads. Confidence: 0.99.
P2 — Preserve the notification channel across live reconciliation
src/daemon/runtime_control.rs:519-522; related lifecycle: src/runtime_peers.rs:498,653-667.
Live reconciliation installs a newly opened RuntimePeers with a fresh watch sender, dropping the original sender. A subscribed waiter whose attempt remains pending then gets immediate Err from changed(). The code checks only the outer timeout error, ignores the inner closed-channel error, and repeatedly rereads state through blocking workers. Since an immediately ready inner future can win even with an elapsed timeout, the loop loses its 30-second bound until a terminal transition or disconnect. Preserve and notify the original sender when installing reconciled state and handle closure explicitly. The existing live-reconcile code intentionally preserves pending attempts; this is not a restart-only hypothetical. Confidence: 0.98.
Also required:
- an ahead-of-current
after_revisionreplies immediately; - the tests synchronize on the waiter's first read, not on the receiver count;
- new tests for a mutex stall, live reconciliation with a waiter, and the ahead-of-current case.
Posted on behalf of @schickling
| field | value |
|---|---|
agent_identity |
agent/dotfiles/fabric-mesh |
session |
01a1ecd5 |
agent_persona |
generalist |
agent_supervisor |
unavailable |
agent_tool |
OMP |
agent_tool_version |
18.12.5 |
agent_runtime |
OMP 18.12.5 |
agent_model |
anthropic/claude-opus-5-5 |
worktree |
unknown |
agent-identity: agent/dotfiles/fabric-mesh agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol
Problem
A bound joining node can only discover pairing confirmation, rejection, cancellation, expiry, or restart recovery by repeatedly reading immediate status.
Goal
Expose a server-bounded reactive status wait on the restricted path and joining-daemon bridge.
Decisions
wait: {after_revision: <u64>}onstatus; omitted waits retain immediate behavior.pairing_remotepassthrough is included insrc/daemon/pairing.rs::remote: typed wait serialization is unchanged, with a 45-second total bridge budget for waiting calls. No separate remote-side file exists.exchange_lost, and strict decoder handling. Terminal response budgeting and its real QUIC regression are in prerequisite Preserve retained terminal pairing response write budget #353.Verification
Exact head:
41118e4814cd11d35c68a6d54c890680b93ebebe. Depends on #353 at25bb3c444a98747f347d0d210330674b4c7fbbb7, rooted at19e7f8964ce8305aeb8c200fb717967aa03f738f; dependency registered withgh stack linkin stack #354.cargo fmt --all -- --check19e7f896and at the preformat wait head. The repo declares no formatting gate or Rustfmt configuration; broad existing-file differences are advisory, not hidden.rustfmt --check --edition 2024 --config skip_children=true <five touched Rust files>which cargo rustc rustfmt cargo-clippy cc ldld.lldis not declared by the repo.cargo test --locked -p fabric --lib status_wait_observes_confirm_reject_cancel_and_immediate_revisions -- --nocapturecargo test --locked -p fabric --lib status_wait -- --nocapturecargo test --lockedcargo clippy --locked --workspace --all-targetsbin/check-public-text --self-testandbin/check-public-textRunner: approved fallback Linux build host (private identifier redacted). Alternate host had 234,991,235,072 bytes available but a saturated build queue (38 waiters, two holders). The fallback uses existing build admission/fences and jobs=4; no alternate-host Cargo target was created. Full check launcher:
CI=1 CARGO_BUILD_JOBS=4 gate-slot --lane build --max-wait 5400 -- nix develop --no-write-lock-file --command <proof runner>.Supported declared-shell paths from this exact-head run: cargo
/nix/store/l7v00m55rb130bhql2kr74pq8sdpl41c-cargo-1.97.0/bin/cargo; rustc/nix/store/h6c2mbpmxih3mfadhvl6jzf090n419yv-rustc-wrapper-1.97.0/bin/rustc; rustfmt/nix/store/i7qpcas4xd1kz9k98yh2c0w8ld0x288b-rustfmt-1.97.0/bin/rustfmt; cargo-clippy/nix/store/bijimpgbih6bwc8sykr5fijcjim2qfgr-clippy-1.97.0/bin/cargo-clippy; cc/nix/store/adcz0m6qq2flmshdf0zz2xwjr5zbq1gr-gcc-wrapper-15.3.0/bin/cc; ld/nix/store/adcz0m6qq2flmshdf0zz2xwjr5zbq1gr-gcc-wrapper-15.3.0/bin/ld.Before: immediate status only. After: bounded notification waits observe durable transitions without polling; unchanged replies permit reissue. Initial confirmation wake failure at
2c97b76exposed a dedicated commit-point bypass; the missing signal was corrected in98e578f, where separate wake and both focused tests passed.Complexity
One watch channel per runtime store and one event-driven waiting loop; no new dependency, persistent schema, or notification registry.
Concerns
Global notifications can wake unrelated waiters within the existing 32-connection cap. This wait draft is 356 changed lines: the original 272-line change grew solely from formatting added hunks. This size is explicitly approved to keep behavior and its required real tests together rather than splitting them.
Friction & bottlenecks
A dangling host-toolchain linker wrapper caused an initial exit 101 before product compilation; its environment defect was captured internally. The repo-declared GCC/binutils devShell avoids relying on that defective host toolchain without overrides. An unrestricted broad test run hit build-memory pressure and was cancelled; later runs use four Cargo jobs. Existing formatting failures were reproduced at the exact base; unrelated formatting was left untouched.
Follow-ups
The full suite remains failed on nine baseline-reproduced environment dependencies; attribution is recorded below. No product behavior omitted.
References
Depends on #353. See
docs/runtime-peer-api.md.Full-suite failure attribution
Each exact test below was run individually with
cargo test --locked -p fabric --lib <test> -- --exact --nocapture, in the same unmodified declared devShell,CI=1 CARGO_BUILD_JOBS=4, inside heavy build admission. Head results come from the original full suite, not a retry.41118e4819e7f89625bb3c44ca::tests::the_constraint_is_present_and_a_verifier_enforces_itsrc/ca.rs:363-368.daemon::tests::a_peer_returns_after_minutes_and_hours_without_errors_or_a_helpersrc/daemon.rs:12611.daemon::tests::interface_address_and_wake_changes_preserve_live_sessions_and_declarationssrc/daemon.rs:12514.update::supervisor_tests::a_stale_supervisor_does_not_revert_a_healthy_later_updatesrc/update.rs:1178-1189,3561.update::supervisor_tests::a_supervisor_without_a_generation_record_does_nothingsrc/update.rs:1178-1189,3561.update::supervisor_tests::an_interruption_after_replacement_restores_the_binary_latersrc/update.rs:1178-1189,3498,3518.update::supervisor_tests::the_macos_job_removes_itself_after_successsrc/update.rs:1178-1189,3473.update::tests::the_detached_restart_leads_its_own_process_groupsrc/update.rs:2227.update::tests::the_detached_restart_waits_for_the_updater_to_exitsrc/update.rs:2268.All nine reproduce at baseline and terminal head; none meets the baseline-pass/head-fail regression criterion. The full suite remains FAIL, not waived or green. Latest main CI test852 succeeded (Ubuntu deterministic and macOS jobs). Its workflow uses stable Rust directly on hosted OS images (
.github/workflows/test.yml:51-55,68,87-95), not the Nix devShell; it has no explicit OpenSSL/coreutils installation step. No host tools, paths, shims, or test exclusions were changed.Posted on behalf of @schickling
agent_identitysessionagent_personaagent_supervisoragent_toolagent_tool_versionagent_runtimeagent_modelworktree