Skip to content

remove the claude-interactive harness - #804

Merged
max-sixty merged 2 commits into
mainfrom
restore-headless-harness
Aug 2, 2026
Merged

remove the claude-interactive harness#804
max-sixty merged 2 commits into
mainfrom
restore-headless-harness

Conversation

@max-sixty

Copy link
Copy Markdown
Owner

Deletes the claude-interactive harness, leaving claude and codex. −1152 lines, +86.

Why

It was built for one reason: Anthropic's 2026-06-15 change would have metered claude -p against Agent SDK credits while leaving interactive terminal sessions on the subscription, and running the binary under a PTY sidestepped that. That reason is gone twice over. Anthropic paused the change and still lists it paused ("Claude Agent SDK, claude -p, and third-party app usage still draw from your subscription's usage limits"), and the default claude harness was since rewritten to run the same binary headless rather than going through the SDK at all — so the thing the PTY was avoiding is no longer on either path.

Nothing selected it. No adopter config sets harness:, tend's own dogfooding moved off it at the rollback, and the last caller anywhere was review-reviewers.yaml, which had it by accident and was fixed in #803.

What it cost to keep: a 667-line parallel composite action, a second smoke workflow, a three-way branch in the generator, a pre-commit hook whose entire job was policing the duplication, and prose across nine files — which had already drifted, since the action's own description still advertised itself as the alternative to claude-code-action.

Restoring it

CLAUDE.md records the removal with a pointer to 036f9c4, the last commit containing the harness, so it can be recovered if the metering resumes.

Shape of the diff

Deletedclaude-interactive/action.yaml, .github/workflows/interactive-smoke.yaml, the claude-action-input-parity pre-commit hook (it existed only to keep the two actions' inputs aligned), four test_claude_interactive_* tests, test_claude_interactive_runs_claude_auth_check, test_per_workflow_harness_same_family_no_model_clash, and the now-orphaned regtest snapshot.

CollapsedCLAUDE_FAMILY_HARNESSES was a two-element set consulted at six sites across config.py, checks.py, and workflows.py. Rather than leave a set of one, the sites now test harness == "claude" directly. Same for the template's {% if cfg.harness in ('claude', 'claude-interactive') %} guards and the "Claude-family" phrasing in adopter-facing comments.

Reparameterizedtest_per_workflow_harness_override_targets_only_named_workflow used claude-interactive as its override target. It now overrides to codex, which exercises the feature harder: the override has to carry its own secret shape, so the test additionally asserts openai_api_key appears and claude_code_oauth_token does not.

Also here — a nightly task in tend's running-tend overlay for restamping action refs in hand-maintained workflows. init only rewrites the generated tend-*.yaml files, which is precisely how review-reviewers.yaml sat on the wrong harness for three releases without anyone noticing.

Testing

284 pass (291 before; the 7-test drop is the deleted tests plus one parametrize case). Beyond the suite, tend init --dry-run was run for real on both remaining harnesses: claude stamps max-sixty/tend/claude@0.1.12 across all eight workflows, codex stamps codex@0.1.12 with openai_api_key.

The gap: no CI run has executed against a workflow generated by this code. The regtests assert the YAML text, not that GitHub accepts it — though the action refs and input names are unchanged for both surviving harnesses, so there's nothing new for GitHub to reject.

If this is wrong

Paused is not cancelled, and Anthropic said it would give notice before shipping a revised version. If the metering returns, this has to be rebuilt or reverted rather than toggled. The bet is that notice plus a commit reference beats carrying a 667-line duplicate that had already started to rot.

No CHANGELOG entry: that section is drafted at release time from the commit range.

This was written by Claude Code on behalf of max-sixty

Its only reason to exist was avoiding the metered Agent SDK. That reason
is gone twice over: Anthropic paused the metering, and the default claude
harness now runs the same binary rather than the SDK. No adopter config
selected it.

Also adds a nightly task to tend's overlay for restamping the action refs
in hand-maintained workflows, which is how the harness went unnoticed on
review-reviewers.yaml for three releases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@tend-agent tend-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generator collapse (CLAUDE_FAMILY_HARNESSESharness == "claude") is mechanically equivalent now that KNOWN_HARNESSES == {"claude", "codex"}, the test reparameterization exercises the override harder, and uv run pytest gives 284 passing here. One gap: the harness-count prose cleanup is incomplete, and in two spots the PR left the comment internally inconsistent.

The two files the PR touched now disagree with themselves — the parenthetical was updated but the count word wasn't:

  • shared/steps/security-preflight.shShared verbatim by all three harness actions (claude/, codex/). — says "three", lists two.
  • shared/steps/validate-claude-auth.shShared by the two Claude harness action (claude/). — "two ... action", now a single Claude action.

And the same drift survives untouched in nine more places:

  • "all three harness actions" (now two — claude, codex): shared/steps/ensure-uv.sh, mark-notification-read.sh, rate-limit-preflight.sh, report-failure.sh, and claude/action.yaml (so the three harness actions can't drift).
  • "the two Claude harness actions" (now one): shared/steps/compose-system-prompt.sh, install-agent-toolchain.sh, install-tend-plugins.sh, restore-sensitive-config.sh, sandbox-setup.sh.

Separately, claude/action.yaml still carries The two Claude actions are swap-in compatible — keep their input surfaces in sync (enforced by the claude-action-input-parity pre-commit hook) — but this PR deletes both the second Claude action and that hook, so the comment now points at two things that no longer exist. Given the PR's premise is retiring prose that had already drifted, this reads as exactly the kind of line worth catching.

These are all outside the diff hunks, so I've left them in the body rather than as inline suggestions. The fix is mechanical (three→two; "the two Claude harness actions"→"the Claude harness action"; drop the input-parity sentence) — happy to push a single sweep commit if you'd like, just say the word.

The deletion left 'all three harness actions' and 'the two Claude harness actions' across shared/steps/, plus a claude/action.yaml comment pointing at the removed second action and its input-parity hook.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@max-sixty
max-sixty merged commit ccd301f into main Aug 2, 2026
7 checks passed
@max-sixty
max-sixty deleted the restore-headless-harness branch August 2, 2026 01:22
@max-sixty max-sixty mentioned this pull request Aug 3, 2026
max-sixty added a commit that referenced this pull request Aug 3, 2026
Bumps the generator to 0.1.13, syncs the lockfile, and adds the
CHANGELOG section the release workflow publishes verbatim as the GitHub
Release notes.

13 commits since 0.1.12. The release's substance is the security work:
the operational secrets move into a gated `tend` deployment environment,
with a secretless review-event relay in `tend-mention` and two new `tend
check` checks ([#810](#810)), and
`tend check` now verifies the bot cannot bypass the merge restriction
([#795](#795)). Alongside those:
the `claude-interactive` harness is removed
([#804](#804)), `tend-review` runs
the adopter's `setup:` on the base tree rather than the PR's
([#806](#806)), tend's uv is
pinned and isolated from the adopter's
([#807](#807)), and the proxy
readiness check waits for the port instead of trusting the CA file
([#811](#811)).

Adopters have manual work after this ships: the environment gate is
inert until each repo's regenerated workflows name the environment and
its secrets are re-minted into it. `TODO.md` carries the per-repo
recipe.

Once this merges: tag `0.1.13`, which publishes to PyPI and creates the
GitHub Release, then regenerate tend's own workflows against the
published version.

> _This was written by Claude Code on behalf of max-sixty_
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.

2 participants