refactor(backends): decompose execution-authority files (#4664) - #4676
Merged
Trecek merged 52 commits intoAug 18, 2026
Conversation
…ntory re-export Extract ClaudeStreamParser + ClaudeResultParser to _claude_parse.py and ClaudeSessionLocator to _claude_session_locator.py. Re-export from claude.py so the public surface is unchanged. Also re-add _validate_codex_mcp_inventory to the _codex_probes re-export block (it was dropped by the linter since the import was not used inside codex.py itself; evidence_reader imports it via the canonical codex path). Refs: #4664
…torage.py Move stateless filesystem primitives (lexists/fsync/atomic_json/write_reconciliation_audit/ read_bounded/ensure_directory_chain/decode_mount_path/filesystem_mount_root/ filesystem_type/replace_symlink) to _codex_fs_atomic.py. The transaction- boundary core (CodexSessionStore, CodexInteractiveSessionLease, _FileLease) remains in _codex_session_storage.py. Update DURABLE_ARTIFACT_WRITERS registry and AST-target guard in test_durable_artifact_writers_guard.py to point at the new module location. Narrow E13 exemption to 1500 lines to accommodate the remaining core after extraction. Refs: #4664
…_poster_finalize.py Move post-attempt finalize/reconcile helpers out of poster.py (997 → 854 lines) into _poster_finalize.py as module-level functions. The mutation authority remains in GitHubReviewLedger — these are pure shaping helpers that operate on receipts/result tuples post-attempt. _EXPECTED_REMOTE_STATES and _FINAL_STATES constants move with the helpers that consume them. Refs: #4664
Move _SCHEMA_VERSION/_DIRECTORY_MODE/_DATABASE_MODE/_SCHEMA + dataclasses ReviewOperationRecord/ReviewAttemptRecord/MutationSlot from ledger.py (868 → 772 lines) into _ledger_schema.py. ledger.py imports them and re-exports for sibling modules; existing test imports keep working. Refs: #4664
…ation.py Move _resolve_skill_session_id/_parse_stdout/_build_api_retry_outcome/ _make_terminated_result/_has_out_of_cwd_file_change/_apply_post_session_adjudication/ _validate_declared_artifact from _headless_result.py (1030 → 846 lines) to _headless_adjudication.py. _build_skill_result remains as the headless orchestration authority. Re-export the moved symbols so existing imports keep working. Narrow E25 line-cap to acknowledge the residual 846-line _headless_result.py. Refs: #4664
Move decide_termination_action (pure decision function) and execute_termination_action (sole authorized async kill executor) from process/__init__.py (942 → 821 lines) to process/_termination.py. The public process.__init__ facade re-exports both so existing callers keep working; _EXPECTED_PROCESS_SYMBOLS test continues to pass. Refs: #4664
Move per-record creation/projection/anchor helpers to _records.py, runner observation helpers to _runner.py, and index path helpers to _indexes.py. _managed_headless_session_lineage.py retains the conflict/CAS mismatch errors and the DefaultManagedHeadlessSessionLineageStore class plus the unaccounted _validate_anchor_identity/_require_cas/ _read_bounded helpers. Existing canonical-path imports keep working via re-export facade. Refs: #4664
…codec.py Move validation, source/exploration-vector/execution-identity serialization, contract to/from dict, manifest construction, and _digest_json helper from _skill_session_contract_store.py (907 → 393 lines) into _skill_session_contract_codec.py. The parent re-exports _digest_json and all other moved symbols so existing imports keep working — notably tests/server/test_run_skill_resume.py:640 and tests/execution/test_skill_session_contract_store.py which import _digest_json from the canonical path. Refs: #4664
Final pass to make pre-commit (ruff, mypy, contract checks) pass on all decomposed files. Adds missing imports for _skill_session_contract_codec extracted types (SkillSource, RepositoryProfileId, ChildExecutionIdentity, etc.) and re-adds _validate_codex_mcp_inventory to codex.py re-export block after linter removed it. Refs: #4664
Per review finding #3 in PR #4676: the post-decomposition module was re-exporting adjudication helpers that had moved to _headless_adjudication.py only so stale import paths would still resolve. AGENTS.md §3.1 forbids backward-compatibility hacks, so delete the shim, replace it with a direct sibling import inside _headless_result, and update the public headless/__init__.py re-export surface plus the two test files that imported the moved names from the canonical _headless_result path.
Per review findings #5 (warning) and #15 (info) in PR #4676: replace bare `except Exception` with the failure set the call site actually produces (`OSError`, `UnicodeDecodeError`, `zstandard.ZstdError`), and parameterize the empty `list[dict]` return annotation as `list[dict[str, Any]]` since the entries parsed from each JSONL line are string-keyed dictionaries.
…port Per review finding #6 (warning) and concurrent failure discovered in tests/contracts/test_skill_semantic_authenticity.py:130 (the test imports CODEX_SPAWNABLE_BUILT_IN_AGENT_NAMES from the canonical `autoskillit.execution.backends.codex` path; the constant was moved out during decomposition and never re-exported on the new path). Delete the dead alias and the now-unused `_codex_config as _codex_cfg` import in _explorer_projection.py, and add a single explicit re-export of CODEX_SPAWNABLE_BUILT_IN_AGENT_NAMES plus __all__ entry in codex.py so the test can collect again.
…n for_each prompt Per review finding #7 cohesion (DISCUSS, resolved as ACCEPT) and a related consistency gap uncovered during DISCUSS investigation of finding #6: - Rename src/autoskillit/execution/github_review/_poster_finalize.py to _poster_post_attempt.py to match the file's actual ownership of both the reconcile_payload and finalize helpers (the docstring already calls them 'post-attempt helpers'). Update the three references in poster.py (import + two call sites). - Update the for_each branch at codex.py:1109 to use the same 'retain every returned child terminal result before parent synthesis' wording as the spawned-count branch and the wait_agent prompt at line 1122, so all three Codex prompt fragments agree.
…backend name string
Per adversarial validation sub-agent findings: - Restore capability-flags dispatch in _headless_adjudication._parse_stdout (was reverted in 1022ea1 due to cascading mock-backend failures). Update tests/execution/conftest.py::_mock_backend to default supports_claude_format_stdout=True so the mock's capability set matches its hardcoded name="claude-code" value, and update the 5 inline Mock backend setups in tests/execution/test_headless_result.py to add supports_claude_format_stdout=True (and the one negative-test mock to set it to False). The arch constraint that motivated the original capability switch is a real one and the mock-fixture asymmetry was the only reason it cascaded. - Remove redundant "Extracted from _headless_result.py" sentence from _headless_adjudication docstring (now matches the trimmed style established for _termination in 8499def). - Rephrase the claude.py docstring to distinguish ownership of ClaudeEnvPolicy / _claude_host_attestation_env / ClaudeCodeBackend from re-export of ClaudeResultParser, ClaudeStreamParser, ClaudeSessionLocator, and the flag vocabulary. The decompose PR moved those symbols out, so the previous wording overstated what the module owns. - Clean up unused imports in execution/process/__init__.py (assert_never, cast, KillReason, ProcessCleanupResult, TerminationAction, ProcessObservationSnapshot) left behind by the decompose PR removal of decide_termination_action and execute_termination_action. Move the _termination re-export shim from bottom-of-file (E402) up next to the other process module imports so it satisfies ruff/arch rules. - Drop the unused 'import structlog' (TYPE_CHECKING block) from execution/process/__init__.py. Ruff F401 violations now: 0 in process/__init__.py, _headless_adjudication.py, claude.py. Remaining E402 violations are pre-existing in session/_managed_headless_session_lineage.py and session/_skill_session_contract_store.py and require the leaf-constants extraction that the validate-review sub-agent recommended for the arch pattern flagged by review findings #12/#21/#22.
…format_stdout capability
… to import from canonical module
…date test consumers
…ackage and update test consumers
…projection docstring
… canonical module
…ols from _codex_probes
… for _CODEX_PROBE_STREAM_LIMIT and _run_bounded_codex_probe
…architectural rule
…mount_root from canonical _codex_fs_atomic module
…t actual circular-import resolution
…up patch probes consistently Switch the module-attribute patches from codex.subprocess/codex.os to probes.subprocess/probes.os so the test is coupled to the canonical probe module after the #4664 decomposition. Other probe tests in this file were already using the probes module; this single test still referenced the parent module. Refs: round 3 review finding (tests: test_codex_config_validation.py:126) Co-Authored-By: Claude <noreply@anthropic.com>
…purpose, not refactor history Drop the refactor-narrating sentences from the module docstrings added during the #4664 decomposition. Each module now describes its functional role and responsibilities instead of how it came to be split out. Also unify CodexSessionLocator.read_session internal annotation (result: list[dict[str, Any]] = []) with the public return type. Refs: round 3 review findings (slop: 5 files; defense: type annotation consistency) Co-Authored-By: Claude <noreply@anthropic.com>
…laude sibling modules Each sibling module's docstring now states what it owns rather than how it was extracted from the parent file during the #4664 decomposition. The claudeparse sibling also drops the exposes-them-via-its-public-surface sentence that narrated consumer relationship instead of the module's purpose. Refs: round 3 review findings (slop: 5 backend modules) Co-Authored-By: Claude <noreply@anthropic.com>
…ocstrings and comments Replace the refactor-narrating comment blocks above the post-class import sections with concise statements of why the imports are deferred. The codec module's docstring now states which parent-module constants it imports instead of describing the import-order workaround. Refs: round 3 review findings (slop: 3 session modules) Co-Authored-By: Claude <noreply@anthropic.com>
…and conftest fixture Drop the change-log narrative from the codex.py line-limit exemption rationale; the exemption now states only what the backend class owns and why the cap was lowered. Trim the _mock_backend docstring to describe the fixture's contract without narrating the test-failure mode it prevents. Refs: round 3 review findings (slop: 2 test files) Co-Authored-By: Claude <noreply@anthropic.com>
Adversarial validation of the previous docstring rewrite flagged that
the new sentence claimed the module owns 'file lease, atomic write,
and macOS quarantine helpers' — but _FileLease lives in
_codex_session_storage.py and there is no quarantine helper here.
The module actually exposes atomic-write, bounded-read,
directory-sync, mount/filesystem-type detection, symlink replacement,
and directory-chain helpers.
Refs: round 3 review finding (slop: _codex_fs_atomic.py:3) +
adversarial re-validation pass
Co-Authored-By: Claude <noreply@anthropic.com>
Resolves conflicts between the execution-authority file decomposition and develop's #4641/#4644 cleanup-evidence, #4575 join-contract, and #4657 MCP-timeout fixes. Develop's fixes are preserved verbatim and relocated into the modules the decomposition moved their code to: - _codex_probes.py receives settle_evidence(), the cleanup_incomplete field, and the _validate_mcp_probe diagnostic warning. - _headless_adjudication.py receives _should_flag_cleanup_incomplete and the _make_terminated_result infra= wiring; _headless_result.py imports it. - process/_termination.py receives the settle_evidence() swap and the int | None return type; _coalesce_returncode stays in process/__init__.py where run_managed_async/run_managed_sync consume it. - Two develop-added probe tests retargeted from codex to _codex_probes so monkeypatching reaches the module that owns the symbol. Line-limit exemption entries keep the narrowed caps (codex.py 1300, _headless_result.py 900) with counts updated for develop's additions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The merged tree failed 36 tests that the decomposition had broken by moving symbols without following their consumers. Each fix points the consumer at the module that now owns the symbol: - test_claude_result_parser / test_claude_session_locator patched parse_session_result and claude_code_project_dir on claude.py, but the consumers resolve them in _claude_parse and _claude_session_locator. A re-export would have silenced the AttributeError while leaving the patch inert, so the patch targets move instead. - _poster_post_attempt.py imported ReviewResponseClass from core.types._type_github_review, violating REQ-IMP-001/002; it is exported from autoskillit.core. - The fcntl allowlist and the _has_active_child_processes AST caller scan follow the lock context and execute_termination_action to their new modules. - _headless_adjudication.py is registered in EXPECTED_CROSS_LAYER_GUARDS. - The plugin mutation ratchet gates on plugin-lifecycle symbol references, so _codex_explorer_projection.py fell out of scan scope when it was split from codex.py. It is named explicitly to keep its staged session-root swaps classified rather than silently losing that coverage. task test-check: 39860 passed, 23 failed — the 23 are identical to the upstream/develop baseline in this environment (ambient CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT and cli probes-fixture paths), so the branch introduces no regression. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Trecek
deleted the
impl-decompose-execution-authority-files-20260817-123010
branch
August 18, 2026 22:59
Trecek
added a commit
that referenced
this pull request
Aug 19, 2026
…er develop merge Merging origin/develop (#4676, #4679 decomposed execution/backends and server/_lifespan.py into directory packages) shifted the file:line locations this registry hardcodes for known forwarding sites and unresolved dynamic reads, without changing the sites themselves. - server/_lifespan.py:747 -> server/_lifespan/_session_boots.py:455 (file split, same EVIDENCE_READER_ENV_FORWARD_VARS dict comprehension) - claude.py/codex.py _HEADLESS_EXCLUSIVE_VARS / _INTERACTIVE_ENV_EXCLUSIONS forwarding sites shifted within their files; codex.py's maintenance/ version-probe dict(os.environ) site moved into the new execution/backends/_codex_probes.py module Verified each new site against the live source before updating its justification; all four ambient-env-surface pincer tests pass locally after the merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Decomposed 10 execution-authority files (12,385 LOC) at 750/1000-line decomposition seams per issue #4664. 10 of 11 groups shipped in this PR; evidence_reader.py (#4) is deferred to follow-up issue #4674 due to circular-dependency risk in the launch/probe/auth decomposition. E9 (codex.py), E13 (_codex_session_storage.py), and E25 (_headless_result.py) line-cap exemptions were narrowed to acknowledge the residual after extraction.
pre-commit run --all-files(ruff, mypy, contract checks, doc count, version consistency, stub completeness, merge-conflict check, secret detection) all pass.Decomposition seams:
codex.py(2444) →codex.py(1216) +_codex_cmd_builders.py(411) +_codex_probes.py(375) +_codex_explorer_projection.py(599)claude.py(1234) →claude.py(931) +_claude_parse.py(231) +_claude_session_locator.py(117)_codex_session_storage.py(1600) →_codex_session_storage.py(1408) +_codex_fs_atomic.py(225)poster.py(997) →poster.py(854) +_poster_finalize.py(242)ledger.py(868) →ledger.py(773) +_ledger_schema.py(137)_headless_result.py(1030) →_headless_result.py(846) +_headless_adjudication.py(247)process/__init__.py(942) →process/__init__.py(821) +_termination.py(177)_managed_headless_session_lineage.py(911) →_managed_headless_session_lineage.py(611) +_records.py(167) +_runner.py(137) +_indexes.py(76)_skill_session_contract_store.py(907) →_skill_session_contract_store.py(393) +_codec.py(571)evidence_reader.py(1452) → deferred to Investigate evidence_reader.py decomposition (1452 lines, E25 still applies) #4674Requirements
Issue #4664: Decompose execution backend authority files (10 files, 12,385 LOC).
Closes #4664
Implementation Plan
Plan file:
/home/talon/projects/generic_automation_mcp/.autoskillit/temp/make-plan/issue-4664-decompose-execution-authority-files_plan_2026-08-17_000000.md🤖 Generated with Claude Code via AutoSkillit