Skip to content

feat(executors): add Aider adapter behind the Executor protocol - #96

Merged
bkd-dotcom merged 1 commit into
mainfrom
feat/aider-executor
Aug 18, 2026
Merged

feat(executors): add Aider adapter behind the Executor protocol#96
bkd-dotcom merged 1 commit into
mainfrom
feat/aider-executor

Conversation

@bkd-dotcom

Copy link
Copy Markdown
Member

Closes #53. Ports @adity982's work from #55, with credit in CONTRIBUTORS.md.

Why a port instead of a rebase

#55 could not be rebased. It predates the umbra_coresignetry_core rename (#90), so every file it touched had movedumbra_core/executors/aider.py, umbra_core/registry.py, umbra_core/cli.py. Git would have seen the whole package as deleted-and-re-added.

The adapter design is @adity982's and is preserved as written:

  • the flag set (--no-auto-commits, --no-dirty-commits, --no-suggest-shell-commands, --yes-always, --dry-run for read-only)
  • deriving the result from the repository diff, not from Aider's own claim of success
  • redacting the prompt from the replay command
  • reporting model_resolved as unavailable rather than back-filling the request

What this port changes: package path, env prefix (UMBRA_ENABLE_AIDERSIGNETRY_ENABLE_AIDER, UMBRA_AIDER_MODELSIGNETRY_AIDER_MODEL), and the test suite.

Security model

property how
off by default SIGNETRY_ENABLE_AIDER=true and the CLI must answer --version — two independent conditions
no commit authority --no-auto-commits + --no-dirty-commits — edits the working tree, never commits, so admission still governs the change
no shell suggestion --no-suggest-shell-commands
read-only means read-only --dry-run on read_only=True
no prompt leak on the receipt prompt replaced with a redaction marker in command
honest provenance a non-zero exit records executor="unavailable", never a green run

On model_identity: Aider does not echo the provider model it resolved, so model_resolved is "unavailable". Back-filling it from the request would put an unverified value on a signed receipt — the one thing this codebase's honesty rule forbids.

Verification

275 tests pass, ruff clean. 13 new tests:

  • fail-closed gating: flag missing, and CLI missing (OSError)
  • protocol conformance + registry membership
  • diff capture through a real temp git repo
  • the safety-flag contract — asserts all three flags are on the invocation and that no commit exists in the repo afterwards
  • --dry-run present on read_only=True
  • prompt redaction
  • executor == "unavailable" on a failed run
  • the disabled result (empty diff, tests_passed is None)
  • model pass-through + model_resolved == "unavailable"
  • registration does not let aider be auto-selected ahead of a configured preference

Two incidental changes: test_registry_lists_and_resolves pinned the exact executor set so it needed aider added, and FakeRunner learned to simulate an aider --message edit. Also tidied a line wrap I left in the README during the Kotlin change.


@adity982 — thank you for this, and sorry it sat. The rename made your branch unrebasable through no fault of yours, so I ported it rather than asking you to redo the work. If you'd prefer to carry it yourself instead, say so and I'll close this in favour of a fresh branch from you.

Closes #53.

Ports @adity982's implementation from PR #55. That PR could not be
rebased: it predates the umbra_core -> signetry_core rename (#90), so
every file it touched had moved. The adapter design is theirs — the flag
set, deriving the result from the repository diff rather than from Aider's
own claim, and redacting the prompt from the replay command. This port
updates the package path, the env-var prefix (UMBRA_ -> SIGNETRY_), and
adds the safety tests.

Registered as `aider`. Fail-closed on two independent conditions:
SIGNETRY_ENABLE_AIDER=true AND the CLI actually responding to --version.

Commit authority stays with the pipeline: --no-auto-commits and
--no-dirty-commits mean Aider edits the working tree but never creates a
commit, so the change stays governable by admission.
--no-suggest-shell-commands keeps it from proposing shell execution, and
--dry-run is used for read-only (reason) runs.

model_identity reports model_resolved as "unavailable" rather than
back-filling the requested model, because Aider does not echo the
provider model it resolved — claiming otherwise would put an unverified
value on a receipt.

13 tests: fail-closed gating (flag missing, CLI missing), protocol +
registry membership, diff capture, the safety-flag contract (asserting no
commit is created in a real temp repo), --dry-run on read_only, prompt
redaction, honest "unavailable" on a failed run, the disabled result,
model pass-through, and that registration does not let aider be
auto-selected ahead of a configured preference.

Also updates the pre-existing registry test, which pinned the exact
executor set, and tidies a line wrap left in README by the Kotlin change.
@github-actions

Copy link
Copy Markdown

Signetry Reviewer — 🟡 Needs human review

A human should decide — the required check is pending.

Deterministic gates (the authority)

Gate Status
Required status check ⏳ pending
Secret scan ✅ clean
CI permission / OIDC ✅ no forbidden change
Dependency skew ✅ ok
All green

Findings

No issues found by the deterministic scanners.

Merge

A human should review and merge.

This review is advisory. It never merges on its own judgement — the deterministic gates + a human are the authority. Findings can have false negatives; a green bot verdict is not a guarantee.

@bkd-dotcom
bkd-dotcom merged commit e6e95c2 into main Aug 18, 2026
8 checks passed
@bkd-dotcom
bkd-dotcom deleted the feat/aider-executor branch August 18, 2026 19:48
bkd-dotcom added a commit that referenced this pull request Aug 18, 2026
@adity982 never signed the CLA. Verified against the authoritative store —
signatures/cla.json on the cla-signatures branch lists exactly one signed
contributor (AdvaitVarhade, from #73). The two "I have read the CLA"
strings on #55 are the bot's own instruction text and a quote of it in a
maintainer comment, not a signature.

CONTRIBUTORS.md states that the people listed are acknowledged "for
contributions accepted under the Contributor License Agreement", so an
unsigned contribution does not belong in that list.

NOTE — this leaves an open provenance question, not resolved here. The
Aider adapter merged in #96 is a port of their #55, and aider.py still
records that derivation in its module docstring. Without a signed CLA the
copyright assignment never happened, so the repo now contains code derived
from an unassigned contribution. That needs a decision (reimplement from
the sibling adapters, or obtain a signature) — flagged rather than settled
by this commit.
bkd-dotcom added a commit that referenced this pull request Aug 18, 2026
@adity982 never signed the CLA. Verified against the authoritative store —
signatures/cla.json on the cla-signatures branch lists exactly one signed
contributor (AdvaitVarhade, from #73). The two "I have read the CLA"
strings on #55 are the bot's own instruction text and a quote of it in a
maintainer comment, not a signature.

CONTRIBUTORS.md states that the people listed are acknowledged "for
contributions accepted under the Contributor License Agreement", so an
unsigned contribution does not belong in that list.

NOTE — this leaves an open provenance question, not resolved here. The
Aider adapter merged in #96 is a port of their #55, and aider.py still
records that derivation in its module docstring. Without a signed CLA the
copyright assignment never happened, so the repo now contains code derived
from an unassigned contribution. That needs a decision (reimplement from
the sibling adapters, or obtain a signature) — flagged rather than settled
by this commit.

Co-authored-by: Binay <bkd-dotcom@users.noreply.github.com>
bkd-dotcom added a commit that referenced this pull request Aug 18, 2026
Resolves the provenance question flagged in #99.

The version merged in #96 was a port of an unsigned contribution (#55).
Without a signed CLA the copyright assignment never happened, so keeping
derived code — especially after removing the attribution — was the least
defensible combination. This rewrites the adapter from the sibling
adapters (codex.py / claude_code.py, both owner-authored) so nothing in
the tree derives from an unassigned contribution, and drops the
attribution from the module docstring and the v0.7.0 changelog entry.

Behaviour is unchanged: all 33 executor tests written against the previous
implementation pass without modification, because they assert behaviour
rather than structure.

Two things the rewrite adds, both from house patterns the port lacked:

  * --model is validated before use, like the Codex adapter's -m value, so
    a caller-supplied string cannot smuggle shell metacharacters or extra
    arguments into the command. The first character must be alphanumeric —
    my own test caught that a naive character class accepts
    "--dangerously-x", since "-" is legal inside a model name, and an
    argument parser may read a leading dash as a new option rather than as
    --model's value.
  * The withheld-authority flags are a named constant, so removing one
    shows up in review instead of disappearing into the command
    construction. A test asserts the set, not just individual flags.

Also logs a non-zero exit like claude_code.py does, which the port did not.

Co-authored-by: Binay <bkd-dotcom@users.noreply.github.com>
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.

Executor: add an Aider adapter behind the Executor protocol

1 participant