Fix:goal continuation cadence fix - part a - #5591
Conversation
Host-managed engines have no cross-turn scheduler, so the configured [goal] continuation_delay_seconds quiet period was never applied: the intra-turn continuation dispatch in turn_loop.rs continued immediately. - goal_loop.rs: shared continuation_wait(delay) computation (None = immediate, capped at MAX_GOAL_CONTINUATION_DELAY_SECONDS) plus await_continuation_wait with biased cancellation — the cancel token always wins over a racing expiry (same semantics as Hmbown#5508). - turn_loop.rs: goal_continuation_message_if_needed now decides before spending the quiet period, awaits the cancellable wait for host-managed turns only, and re-decides on the live goal state after the wait so pause/clear or a terminal update_goal cancels the pending pass. Failed or interrupted turns never continue. Interactive engines keep their existing cross-turn cadence untouched. Verified: cargo test -p codewhale-tui goal_loop (15/15, incl. new delay>0, zero-delay-immediate, cancellation-wins tests), 454 goal-named engine/tool/UI tests, cargo clippy -p codewhale-tui --lib, cargo fmt. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
The v1 fix awaited the quiet period inside the intra-turn ladder (turn_loop.rs), which is not the dispatch path for host-managed sessions: the engine never calls schedule_goal_continuation there (gated on !host_managed_turns), and the host injects Op::ContinueGoal (engine_schedule_id None) into the engine mailbox instead. The run() arm for that token dispatched immediately with no delay. Now the Op::ContinueGoal arm awaits the shared cancellable quiet period for host-injected tokens before dispatching: biased cancellation (Esc/steer/host cancel) always wins over a racing expiry, and the live goal is re-read only after the wait so pause/clear/complete/blocked cancels the pass and failures never continue. Engine-owned tokens (engine_schedule_id Some) keep the scheduler's ready_at semantics untouched. Tests: host-injected ContinueGoal with delay>0 waits out the quiet period before the provider request, delay=0 dispatches immediately, and cancellation during the wait never dispatches. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
…essions goal_continuation_message_if_needed gated the between-continuation quiet period on host_managed_turns(); the else-None branch assumed the cross-turn scheduler covered non-host-managed sessions, so a session resumed via `codewhale resume --last` (runtime_services.active_thread_id None) dispatched goal continuation instantly. This within-turn hook is the only dispatch site, so the wait is now unconditional: continuation_wait(goal_continuation_delay_seconds) for every session, keeping the biased-cancellable await, the post-wait re-decision on live state, and the GoalContinuationWaiting/WaitEnded events unchanged. Tests (turn_loop): a non-host-managed engine with a positive delay emits the wait receipt, does not dispatch before the quiet period elapses, and dispatches (one recorded continuation) afterwards; a zero delay still continues immediately with no wait receipt; a host-managed engine keeps the same wait contract. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
Production intentionally caps terminal motion over SSH (in_ssh_session -> low_motion), and four tests assert the un-capped state without neutralizing SSH_CLIENT/SSH_TTY — deterministic failures whenever the suite runs over SSH (the normal test-bed pattern). Each test now removes SSH_CLIENT, SSH_CONNECTION, and SSH_TTY via EnvVarGuard under the env lock, restoring them on drop. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
On hosts with a system-wide rustup (cargo/rustc are rustup proxies), the env-cleared doctor probe defaults RUSTUP_HOME to the sealed fixture HOME and materializes toolchain state there, failing the read-only assertion. Mirror the TUI integration test's preserve_host_rustup_home guard. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
… for V4 trigger and prompt prefix-leak tests route_budget::tests::v4_trigger_uses_window_percent_when_it_fits_spendable_input asserts no-override output-budget values but read the process-global CODEWHALE_MAX_OUTPUT_TOKENS/DEEPSEEK_MAX_OUTPUT_TOKENS without holding lock_test_env(), so a concurrent sibling writer could flip the value mid-assertion. The test now holds the barrier and removes both overrides, matching every sibling test with the same dependency; assertions unchanged. Full-suite verification under --test-threads=1 exposed the same class of bug in prompts::tests::system_prompt_prefix_never_leaks_private_content: it read the real home via HOME/USERPROFILE, so ~/.codewhale/instructions.md leaked its absolute path into the prompt and failed the no-private-paths assertion unless a sibling's temporary HOME guard happened to be live. It now holds the barrier and pins HOME/USERPROFILE to a scratch dir. Assertions unchanged. Verified: 4 consecutive full cargo test -p codewhale-tui --lib runs green (10891 passed / 0 failed / 13 ignored each; 2 x default threads, 2 x --test-threads=1); fmt clean; clippy clean. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
…mbown#5534) and the flake hardening Move the flake-hardening entry out of the released 0.9.11 section into Unreleased (0.9.11 already shipped without it) and add the Hmbown#5534 entry. Regenerated crates/tui/CHANGELOG.md via scripts/sync-changelog.sh. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
docs/changelog/changelog-0076.md is an ecosystem-internal per-session build log (session-numbered convention); upstream keeps its changelog in the root CHANGELOG.md, where the flake-hardening entry already lives. Signed-off-by: M-Maciej <130112810+M-Maciej@users.noreply.github.com>
|
Thanks @M-Maciej for taking the time to contribute. This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered. Please read |
Hmbown
left a comment
There was a problem hiding this comment.
Reviewed and independently verified locally on your branch:
-
The core design is right. Decision split from dispatch (
goal_continuation_allowed), decide-before-wait so a terminal goal never spends the quiet period, biased-cancel wait (Esc/steer/host cancel win over a racing expiry), and — the part I'd call load-bearing — the re-decide on live state after the wait, so a/goal pause,/goal clear, or terminalupdate_goallanding during the quiet period cancels the pass instead of dispatching a provider request. TheOp::ContinueGoalarm correctly gates only host-injected tokens (engine_schedule_id.is_none()); engine-owned tokens keep their scheduler semantics. -
Ran the focused suite on your branch:
goal_continuation12/12 (host-managed waits, non-host-managed waits, zero-delay immediate, cancellation paths). -
Ran the repo's single-turn-loop guard (
crates/core/tests/single_turn_loop.rs): 2/2 — the turn_loop.rs changes stay inside the one loop. -
Clippy on
codewhale-tui--all-targets on your branch: 0 warnings under the CI allow list. -
Merge interaction with the 0.9.12 integration branch (#5576):
git merge-tree --write-treebetween it and this branch exits clean — we also modifiedturn_loop.rs(compaction decisions, step budget), but in different regions; no conflicts expected either merge order.
The split provenance note and the honest "live-verified before split, not after" checkbox are exactly the review shape we wanted out of #5535 — thank you. Holding the merge for the maintainer's go and for the remaining CI checks to finish.
Refresh the goal-continuation cadence branch on current main. Preserve all eight contributor commits and their authorship; resolve only the expected synchronized Unreleased changelog overlap. Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Hmbown
left a comment
There was a problem hiding this comment.
Re-approved at exact head 0903bf6 after the current-main refresh.
Verified locally: all eight M-Maciej commits and their authorship are unchanged; only the expected synchronized Unreleased changelog overlap was resolved. Formatting is clean; workspace/all-targets clippy is clean; goal_continuation passes 12/12; the single-turn-loop guard passes 2/2; the contribution-credit checker passes 11/11 plus the live 8/8 range check. Fresh GitHub CI is green across required Linux, Windows, macOS, lint, and version lanes, with safety, OpenHarmony, DCO, credit/metadata, and advisory checks also green. The PR now closes the exact bug issue #5534.
Integrate PR #5591 and current main release/CI documentation changes. Adapt the host-managed continuation regression fixture to the release branch's max_steps=0 unbounded contract by using a deterministic scripted model client instead of a dummy loopback endpoint. Entire-Checkpoint: 01M0S73RG3JN20J2V8SS9F34GF
…ntities Twenty external contributions landed after the v0.9.11 band closed and none were credited: the newest band in docs/CONTRIBUTORS.md was still v0.9.11 while main shipped 0.9.12 work. Adds the v0.9.12 band covering all twenty (#5591, #5599, #5604, #5610, #5613, #5621-#5624, #5629, #5650, #5657, #5669, #5682, #5683, #5685, #5687, #5688, #5689, #5692) and demotes v0.9.11 so only the newest band stays expanded. AUTHOR_MAP gains numeric-noreply entries for musichen, M-Maciej, and serephus so future harvested credit is graph-mappable, plus a comment recording that wangfengcsu@qq.com (21 commits on main via #704) has no resolved login yet. AUTHOR_MAP is a project convention consumed by scripts/check-coauthor-trailers.py for new commits; GitHub does not read it, so it grants no retroactive contribution-graph credit for history already on main. No-Issue: contributor credit hygiene; no issue tracks it Signed-off-by: CodeWhale Bot <bot@codewhale.net>
The contribution gate leaves an unlisted contributor's workflow runs at `action_required`, so their CI never starts and the PR sits looking stalled through no fault of theirs. whp233's #5714 and #5716 had SEVEN workflows each parked that way; I approved those runs by hand, but the allowlist is the actual fix. Added (all five have landed or open work): whp233 open PRs #5714, #5716 — the runs that were parked musichen merged #5689 (DeepSeek configured-view picker) M-Maciej merged #5591 (goal continuation cadence) serephus merged #5669 (nixpkgs update) Pinvou fork owner behind #5686 (Moonshot/Kimi native search) Entries use `all:` to match the existing convention for active contributors. No-Issue: contribution-gate hygiene; no issue tracks it Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Summary
[goal] continuation_delay_seconds(the goal-continuation cadence, added in#5508) was wired into only one of the two goal-continuation dispatch paths.
The within-turn dispatch hook (
goal_continuation_message_if_neededin theengine) had no wait at all, so a model step that ended with the goal still
active immediately emitted the next continuation prompt. That made the
configured cadence dead on two kinds of sessions:
codewhale resume --last) — they dispatchcontinuation passes through the within-turn hook.
next durable claim, so these sessions never reach the cross-turn scheduler;
every pass goes through the un-waited hook.
Measured (before split) live with a 300 s delay configured: continuation passes fired at
model latency before the fix (~9 s gaps, instant-fire through the within-turn
hook). After the fix, consecutive passes are separated by the configured
quiet window — the observed cadence became ~5 minutes (300 s quiet window
plus the turn itself), versus ~9 s instant-fire before.
This branch applies the wait on the within-turn path, unconditionally:
goal_continuation_message_if_needednow awaitsgoal_loop::await_continuation_waitbefore dispatching (biased cancel:Esc / steer / host cancel / terminal
update_goalall win over a racingexpiry, and the live goal is re-read only after the wait).
Op::ContinueGoalarm — for host-managed sessions this arm is their only dispatch site.
pending pass.
The flake-hardening test fixes (env-barrier isolation for the route-budget V4
trigger and the prompt prefix-leak tests, SSH-marker neutralization in the
terminal-motion suite, RUSTUP_HOME preservation in the read-only diagnostic
test) are grouped here per the #5535 review guidance (the cadence fix plus the
flake hardening as one small slice).
Rebase note
Rebased onto current
main(v0.9.11, merged in #5542). v0.9.11 rewrotecore/engine/turn_loop.rsand the engine event loop; the fix has beenre-verified against the new loop by the regression tests below.
Split provenance
This PR is one slice of a mechanical split: the original combined branch was
rebased onto v0.9.11 and then partitioned along commit boundaries, then each
slice was re-verified independently with the full gate suite. The combined
rebased tree (the union of all slices) also passes the full suite
(13,441 / 0). Partition boundaries worth review attention: the engine
dispatch paths shared with the outbox emit-site work, and the Windows
cfg-gating.
Split map and merge order
The four pieces of the original combined branch are filed as four PRs. All
four are standalone — each is cut from current
mainand passes its fullgate suite alone:
lines; builds and passes 13,403 / 0 without this PR. A trivial rebase is
expected after this merges.
/relaunch(Feature: /relaunch — switch a running session to the current binary #5532) — the control socket'srelaunchverb (d)dispatches the
/relaunchcommand through the generic command seam, so(d) has no compile dependency on (c): without it the verb returns
command_error; with it, the verb becomes functional.direction; no dependency.
One coupling no slice escapes: all four add entries to the same
## [Unreleased]changelog section, so each merge is followed by a smallchangelog rebase for the PRs still open. Independently reviewable and
buildable — yes; mergeable with zero follow-up — no.
Testing
<!-- Exact gate commands (including the clippy allow list) are in
CONTRIBUTING.md → "Pre-push verification". -->
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features --locked(warning-free under the CI allow list)cargo test --workspace --all-features --lockedResults: clippy clean on stable 1.98.0 under the CONTRIBUTING.md allow
list; full suite 13,375 passed / 0 failed. Focused
goal_continuationsuite 13/13 (host-managed sessions wait, non-host-managed sessions wait,
zero-delay dispatch is immediate, cancellation paths).
Checklist
exercised live on running sessions ( yes before split, not after split )
every commit is authored under
130112810+M-Maciej@users.noreply.github.comSigned-off-by(DCO)Unreleased(and the flake-hardening entrymoved out of the released 0.9.11 section, where an earlier rebase had
placed it)
/relaunch, and control-socket slices from Supervised operation stack: lifecycle outbox, /relaunch, per-session control socket, and the goal-continuation quiet-period fix #5535 followas separate PRs after this one lands
Closes #5534