Skip to content

refactor(execution): reduce complexity across execution handlers - #5034

Merged
Trecek merged 23 commits into
developfrom
impl-execution-complexity-4995-20260912
Sep 14, 2026
Merged

Trecek merged 23 commits into
developfrom
impl-execution-complexity-4995-20260912

Conversation

@Trecek

@Trecek Trecek commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Execution parsers, process monitors, and result/publication handlers repeat branch logic and mix separate responsibilities. This refactor separates validation, process observation and race coordination, headless launch/result preparation, and GitHub/runtime/quota handling while preserving existing outcomes and ordering.

All 60 candidates in #4995 are accounted for: 55 have lower complexity scores, four are simplified with unchanged scores, and C05 retains its original implementation. The bookkeeping sum for the original functions is 1,163 → 795; the 58 new helpers and 21 moved/renamed identities are measured separately. The issue body contains the complete measurements and rationale.

  • Split evidence-reader contracts and protocol validation into execution/evidence/reader/ to meet existing size limits, preserving facade aliases and filesystem/process ownership.
  • Consolidate repeated parsing, retry, cancellation coordination, reconciliation and polling decisions. Preserve error precedence, cleanup ownership, descriptor handling, model identity and launch-preparation values.
  • Update source-inspection and retention checks for the extracted responsibilities, and extend the disappearing-process characterization with the demonstrated root-disappearance case. No policy, size limit or complexity exemption was relaxed.

Validation at e97dbcec94e813742d9e61d686ed3b9ceda87b9b:

  • test_check / task test-all, full configured suite (full_run_reason=large_changeset): 43,634 passed, 615 skipped, 29 xfailed.
  • pre-commit run --all-files and the complete diff whitespace check passed.
  • The unchanged captured complexity checker reports seven helper warnings above CC 10. Their responsibility boundaries and retention rationale are documented in Complexity debt: execution process & session lifecycle, evidence collection #4995; no original candidate's score increased.

C05 was implemented and tested, then restored: its extraction left CC 39 unchanged, exceeded the executor's existing line budget, and moved logger calls out of handlers where ARCH-003 requires them. Retaining the original follows the plan's explicit allowance for a clearer implementation with a documented deviation.

Closes #4995.

_assert_agent_safe_skill_frontmatter caught bare Exception around load_yaml,
wider than the documented YAML loader failure mode. Every other load_yaml
call site in the codebase catches YAMLError specifically (core/io/yaml_io.py
explicitly re-exports it for this purpose); narrow this one to match.
…al_direct_leader

The bare `pass` lacked the same disappearance-race justification other
predicates in this module already document explicitly. Kept as a trailing
comment (not a new line) since the file sits at the REQ-CNST-010 750-line cap.
…m to Literal

stage was a bare str used to build log-event names via f-string, so a typo
in a caller's stage argument would silently produce an unknown log key.
Both call sites already only ever pass "term"/"kill"; no behavior change.
_tether_record_from_dict already raises TypeError for data is None, and the
surrounding except (ValueError, KeyError, TypeError) already catches it —
the explicit pre-check was dead weight duplicating detection sweep_orphaned_tethers
already consolidated into the helper.
…robes

The old name only described the run path, but the function also writes the
probe cache on both the success and failure paths — matching the naming
precision of its sibling helpers in this module.
The old _validate_ prefix was inconsistent with this module's other
_validate_* helpers (e.g. _validate_credential_parent), which are pure
validation and return None. This one validates AND derives/returns the
bare tool tuple in one pass — kept as-is (the derivation is itself part of
validating definition.reader_tools), just renamed to match its real scope.
…unters

_consecutive_process_state_anomalies returned three independent counters
positionally coupled to the records list, unlike its sibling anomaly
helpers (_oom_anomalies, _signal_transition_anomalies) which return records
plus a single value. Bundle the counters into a frozen dataclass so the
shape mirrors those siblings.
_stale_suppression_reason returned prose strings that _continue_stale_suppression
then string-matched on to select behavior, so the same string served as both a
branch key and a log-template fragment. Introduce a StaleSuppressionReason
Literal for the control-flow tokens; the human-readable phrasing stays local to
each logger.warning() call site, unchanged. No test asserts on the raw return
value of _stale_suppression_reason (only on log event names and structured
fields), so this is a pure internal refactor.
…lResultContext

_build_stall_result duplicated ~16 of _build_skill_result's own keyword-only
params, forwarded 1:1 by name. Bundle the shared fields into a frozen,
slotted _SkillResultContext constructed once in _build_skill_result; keep
stall_spec as its own kwarg (test_infra_exit_retry_policy_exhaustive.py
inspects call sites for stall_spec=_STALE_SPEC/_IDLE_STALL_SPEC by name).
_build_skill_result's external signature is unchanged, so its other callers
are unaffected.
…ssLaunchPreparation

The bare 4-tuple (backend, model identity, launch preparation, add_dirs) is one
cohesive launch context, mirroring the existing PostSessionMetrics precedent in
_headless_helpers.py for the same pattern. Return-value change only — the
16-parameter input surface is left as-is (no single grouping was found that
reduces real complexity for this function's sole caller; see DISCUSS writeup).
_termination.py::_drain_before_escalation and _process_monitor.py's
_stale_suppression_reason both combined the same 3 liveness predicates
(api_connection, child_processes, dispatch_marker) into a defer/kill
decision, duplicated inline on one side. Extract the predicate
evaluation into _active_liveness_signals (_process_monitor.py, alongside
the predicates it wraps); each site keeps its own ceiling/priority/
logging/pending-tasks semantics unchanged on top — no behavior change,
only the literal predicate-combination logic is deduplicated. Update the
two AST-based arch guards in test_watcher_signal_consistency.py to hop
through the new indirection, mirroring the pattern already used for
_session_log_monitor's existing indirection through
_stale_suppression_reason.

Per DISCUSS investigation: deliberately does NOT unify the two sites'
differing ceiling values, priority order, or pending-tasks awareness —
that remains an open product decision (whether a completed-but-still-
active session's kill should also wait on pending async obligations),
tracked separately, not decided here.
CI caught this: commit 9dc8a86 replaced _termination.py's inline
predicate-OR logic with a call to the shared _active_liveness_signals
helper, but three tests in this file still monkeypatched the old
individual _has_active_child_processes/_has_active_api_connection
bindings on the _termination module. _has_active_api_connection is no
longer imported there at all (AttributeError on patch), and patching
_has_active_child_processes there is now a no-op for the deferral path
since it only reaches the real predicate via _process_monitor's own
_active_liveness_signals. Repoint all three at the new seam; verified by
hand that the expected call counts and clock values are unchanged.
@Trecek
Trecek added this pull request to the merge queue Sep 14, 2026
Merged via the queue into develop with commit 856c9cb Sep 14, 2026
8 checks passed
@Trecek
Trecek deleted the impl-execution-complexity-4995-20260912 branch September 14, 2026 20:01
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