← Ascendy 한국어

meta

How to reject a feature — an AI pair cut its own roadmap, on the record

· Ascendy Engineering


TL;DR

Source note. Distilled from a redteam-team intake. It’s all public OSS (AscendyProject/redteam, Apache-2.0), so the issue/PR numbers and statuses were checked directly with gh on the public repo. Same adversarial pair vein as the post where one AI reviewed another AI’s PRs and caught four HIGH defects.

Not only building is progress

Add a feature and commits stack up, a PR merges, progress shows. But “we decided not to build this”? Usually you quietly close the issue, let it rot in the backlog, or decide it only in your head. No trace. So six months later someone proposes the same thing, and runs the same analysis from scratch.

redteam closed issue #37 differently. #37 was the work of splitting “how do we run the adversarial reviewer behind an adapter seam” into three steps:

The result: the #37 umbrella is fully closed — one of three steps shipped, two rejected. And that rejection decision was merged only after a different-provider model (Codex) cross-reviewed it (opening the actual branch code in a read-only sandbox; approved in one round).

Why reject it — marginal gain vs. the cost you take on

The only benefit of step 5 (the sub-agent adapter) was visibility — seeing the review run inside the session and steering it mid-way. But the headless reviewer (claude -p --permission-mode plan) already covered the “Claude comes in as a cross-provider reviewer” case.

For that marginal gain, you’d take on two things:

  1. A new execution surface. Spinning up a sub-agent inside the session pushes directly against the harness’s two invariants — it runs on any project (project-agnostic) and zero runtime dependencies.
  2. A thorny security precondition (below).

Small gain, large cost. So they rejected it. Rejecting is a legitimate engineering decision — that’s the point of this post — as long as the rejection leaves a trace. YAGNI (“you aren’t gonna need it”) written into a decision record, with the guardrails you’d have to re-clear to revive it pinned alongside.

The security trap that justified the rejection — identifier normalization

The detail that sank step 5 is small and general. redteam has a guard against self-review collapse — it fail-closed refuses to let a model from the same provider review its own code (an adversarial pair must stay cross-provider).

The problem was that the guard compared the two sides in different formats. One side (the worker that wrote the code) was identified by a normalized provider family, while the other (the reviewer) was identified by a raw adapter identifier. With a format-mismatched comparison, introducing a new adapter could let that identity check pass as if it were cross-provider — letting a same-provider self-review slip past the guard. Attaching the sub-agent adapter would have opened exactly this gap. It was caught as a HIGH in plan review, and pinned into the decision record as a hard precondition: normalize both sides to the same canonical form (family) before comparing.

Generalized: in an equality/identity check, comparing a normalized form on one side against a raw value on the other means a single input exploiting that format gap can defeat the check. Normalize both sides to the same canonical form before comparing. It applies everywhere you compare identifiers — auth, permissions, dedup, self-review guards.

Honestly — there was no fierce debate this time

The recurring thread in redteam posts is “Claude and Codex split over several rounds.” Not this cycle. Codex’s cross-review of the rejection record approved in a single round, with no substantive disagreement. So rather than dress it up as a “heated debate,” I’ll just leave it blank — inventing tension that wasn’t there is worse.

Takeaways

Repo: github.com/AscendyProject/redteam (Apache-2.0).


Authorship & citation: Written by Ascendy Engineering; quotable with attribution. Found something wrong? Let us know via a GitHub issue.


Tags: decision-record, oss, agent-pair, yagni, trust