From 5327b25e1b26d035a3d704bc48f7c85c2b4c2621 Mon Sep 17 00:00:00 2001 From: goodboy Date: Mon, 24 Aug 2026 19:38:22 -0400 Subject: [PATCH] Factor `child_in_debug()` state sampling `_try_cancel_then_kill()` repeated the same child/tree debugger predicate before and after its cancel-RPC checkpoint. Inline duplication obscured that lock state must be sampled at both points. Factor the predicate into a local `child_in_debug()` sampler. Use it for initial hard-kill protection and re-run it after the await before debugger waiting, preserving dynamic lock-state behavior. Keep it local since one input is supervisor-owned nursery configuration. Review: PR #481 (goodboy) https://github.com/goodboy/tractor/pull/481#pullrequestreview-5012942328 Prompt-IO: ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.md (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`)) --- .../20260824T225356Z_2f86dd1a_prompt_io.md | 39 +++++++++++++++++++ ...20260824T225356Z_2f86dd1a_prompt_io.raw.md | 18 +++++++++ tractor/runtime/_supervise.py | 22 +++++++---- 3 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.md create mode 100644 ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.raw.md diff --git a/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.md b/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.md new file mode 100644 index 00000000..6baf40fb --- /dev/null +++ b/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.md @@ -0,0 +1,39 @@ +--- +model: openai/gpt-5.6-sol +service: opencode +session: d9d7df2c-7044-463f-8768-ec024718eac9 +timestamp: 2026-08-24T22:53:56Z +git_ref: 2f86dd1a +scope: code +substantive: true +raw_file: 20260824T225356Z_2f86dd1a_prompt_io.raw.md +--- + +## Prompt + +Continue PR #481 review remediation after committing the paired +`ActorNursery` reap-state invariant. The human selected "keep" for the +reviewer's request to factor a duplicated debugger predicate in +`_try_cancel_then_kill()`. + +## Response summary + +Factor the child/tree debugger predicate into a local sampler used both +before and after the cancel-RPC checkpoint. Preserve dynamic debugger +lock re-evaluation and its distinction from root-wide debug mode. + +## Files changed + +- `tractor/runtime/_supervise.py` - factor the duplicated debugger + predicate without changing cancellation behavior. + +## Human edits + +The human explicitly selected "keep" after receiving keep/defer/drop +options for this isolated review item. During commit-plan review, the +agent found that a single pre-checkpoint snapshot could become stale; +the human selected a local helper which re-evaluates the lock after the +cancel RPC. The human then considered moving the predicate into +`.devx.debug` and accepted keeping it local after confirming that no +existing helper shares its supervisor-owned semantics. No direct +source-line edits were made by the human. diff --git a/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.raw.md b/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.raw.md new file mode 100644 index 00000000..cb8b3b08 --- /dev/null +++ b/ai/prompt-io/opencode/20260824T225356Z_2f86dd1a_prompt_io.raw.md @@ -0,0 +1,18 @@ +--- +model: openai/gpt-5.6-sol +service: opencode +timestamp: 2026-08-24T22:53:56Z +git_ref: 2f86dd1a +diff_cmd: git diff HEAD~1..HEAD +--- + +Implement the approved PR #481 review refactor in +`_try_cancel_then_kill()` without changing debugger behavior. + +> `git diff HEAD~1..HEAD -- tractor/runtime/_supervise.py` + +Compute the child/tree debugger predicate once, reuse it in the broader +hard-kill protection predicate, and pass it directly to +`debug.maybe_wait_for_debugger()`. + +Run focused debugger/cancellation coverage and lint after the edit. diff --git a/tractor/runtime/_supervise.py b/tractor/runtime/_supervise.py index 080559e2..6e09c65f 100644 --- a/tractor/runtime/_supervise.py +++ b/tractor/runtime/_supervise.py @@ -130,12 +130,21 @@ async def _try_cancel_then_kill( # mutated by per-child `debug_mode=True`). ORing covers # every flavor without false-positively skipping # legitimate hard-kill paths in non-debug trees. + def child_in_debug() -> bool: + ''' + Sample child/tree debugger protection state. + + ''' + return ( + debug_mode_active + or + debug.Lock.ctx_in_debug is not None + ) + debug_protected: bool = ( - debug.Lock.ctx_in_debug is not None + child_in_debug() or _state._runtime_vars.get('_debug_mode', False) - or - debug_mode_active ) try: @@ -145,11 +154,8 @@ async def _try_cancel_then_kill( if not cancelled: if debug_protected: await debug.maybe_wait_for_debugger( - child_in_debug=( - debug_mode_active - or - debug.Lock.ctx_in_debug is not None - ), + # Re-sample after the cancel-RPC checkpoint. + child_in_debug=child_in_debug(), header_msg=( 'Delaying subproc hard-reap while ' 'debugger locked..\n'