Skip to content

arch(#12): split _send.py by responsibility (run / inject / stdin / probe)#375

Merged
voidfreud merged 1 commit intomainfrom
arch/send-split
Apr 14, 2026
Merged

arch(#12): split _send.py by responsibility (run / inject / stdin / probe)#375
voidfreud merged 1 commit intomainfrom
arch/send-split

Conversation

@voidfreud
Copy link
Copy Markdown
Owner

Summary

Splits `src/ita/_send.py` (600 LOC) into responsibility-separated modules. Public API preserved via re-exports.

Module boundaries:

File LOC Owns
`_send.py` 53 `send` command + back-compat re-exports (facade)
`_run.py` 277 `run` command, stdin-script assembly, echo-row scoping, escalation ladder
`_inject.py` 164 `inject` + `key` commands, `_KEY_MAP`, `_parse_key`, `_encode_inject_payload`
`_probe.py` 108 `_has_shell_integration`, `_prompt_is_back`, `_escalate_interrupt`, `_trim_output_lines`
`_stdin.py` 52 `_load_stdin_script` (CWD traversal rules from #325)
`_force.py` 19 Shared `@_force_options` decorator (breaks circular import)

Back-compat verified: `from ita._send import run, send, inject, key, _parse_key, _trim_output_lines, _encode_inject_payload, _load_stdin_script, _has_shell_integration` all still work.

Fast-lane: 580 pass / 14 fail → 587 pass / 12 fail (+7 pass, -2 fail; no regressions).

Flagged (minor): `_run.py` landed at 277 LOC, slightly above the ~250 target. The `run` Click body is inherently large (stdin prep, inner async closure with wrapper + scoping + ladder, plain/json output branches). Agent extracted `_build_wrapped_command` to trim ~25 LOC; further splitting would fracture the single pipeline unhelpfully.

Unblocks: task #13 (inject → @ita_command envelope) can now proceed in `_inject.py` in isolation.

Closes #12 (task, not issue).

Test plan

🤖 Generated with Claude Code

…robe)

Pure move. `_send.py` drops from 600 LOC to 53 LOC and now just holds the
`send` command plus re-exports. The run pipeline (run command, wrapper build,
echo-row scoping, timeout clamp, interrupt ladder) lives in `_run.py`; the
inject/key surface (encoder, key map, parser, both commands) lives in
`_inject.py`; `--stdin` path-traversal validation in `_stdin.py`; shell-
integration probe, prompt-is-back check, interrupt ladder, and output trim
in `_probe.py`; shared `--force-*` decorator in `_force.py`.

All existing imports (`from ita._send import run, send, inject, key,
_parse_key, _trim_output_lines, _encode_inject_payload, _load_stdin_script,
_has_shell_integration`) keep working via re-export. No behavior change;
fast-lane 587/12/195/56 (baseline 580/14/195/56, no regressions). Unblocks
#13 inject→envelope conversion as a single-file edit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@voidfreud voidfreud merged commit e629593 into main Apr 14, 2026
1 of 3 checks passed
@voidfreud voidfreud deleted the arch/send-split branch April 14, 2026 08:25
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.

Meta: defensive audit of iTerm2 API calls against actual SDK

1 participant