Skip to main content

ADR-021: Disposition of the legacy AI execution layer

Statusโ€‹

Accepted

Disposition recorded 2026-08-26 by the repository owner (#1414). The evidence below was gathered before the decision, not assembled to justify it afterwards.

Dateโ€‹

2026-08-26

Contextโ€‹

The server carries two overlapping execution strategies:

  • Legacy AI execution โ€” src/utils/ai-executor.ts calls OpenRouter directly and returns generated text. Introduced before ADR-014.
  • CE-MCP directives โ€” ADR-014's design, where a tool returns an OrchestrationDirective and the host LLM does the work. No external API call.

ADR-014 was accepted and the migration was started. It was never finished, and both paths are still live. This ADR exists to settle which one the project keeps.

Measured stateโ€‹

All figures re-measured on main at 0993d0d8 (2026-08-26). The earlier v3.0 PRD quoted figures from 787ef912, a commit that never reached main; where the two disagree, the numbers below supersede it.

tools exposed over the wire75
tools with a real CE-MCP directive12
tools claiming hasCEMCPDirective: true in TOOL_CATALOG70
files importing ai-executor5
external runtime dependencies of the AI layer1 (openai)

The twelve with genuine directives:

analyze_environment analyze_project_ecosystem deployment_readiness
generate_adrs_from_prd generate_rules interactive_adr_planning
mcp_planning perform_research smart_score
suggest_adrs tool_chain_orchestrator troubleshoot_guided_workflow

So 58 of the catalog's 70 claims are false. That field is what search_tools reports to callers, so the discovery surface advertises a capability most tools do not have.

Footprintโ€‹

pathLOC
src/prompts/ (11 files)6,498
src/**/*reflexion*1,780
src/**/*knowledge-generation*1,257
src/**/*ape*707
src/utils/ai-executor.ts457
src/utils/prompt-execution.ts453
total11,152 of 114,281 (โ‰ˆ9%)

The PRD estimated ~18,200 LOC (~16%). This narrower figure counts only what a removal would actually delete; treat 9% as the defensible lower bound.

What a user gets today, out of the boxโ€‹

executionMode defaults to 'ce-mcp' (src/config/ai-config.ts:152), and isAIExecutionEnabled() requires 'full' or 'hybrid' and an API key (:240). With no key configured, legacy AI execution is off.

That is the intended design. But the diagnostic tool contradicts it. Calling check_ai_execution_status on a clean checkout returns:

> Note: As of Phase 5, this server uses CE-MCP mode by default.
> In CE-MCP mode, tools return orchestration directives that the host LLM
> executes directly, eliminating the need for external API calls.

## Current Configuration
- AI Execution Enabled: NO
- Has API Key: NO
- Execution Mode: ce-mcp

## Issue Detected
Problem: Missing OPENROUTER_API_KEY environment variable

## Solution
1. Get an OpenRouter API key from https://openrouter.ai/keys

It states that no external API call is needed, then reports the absence of an external API key as a problem, and directs the user to go and buy one. This is observed behaviour over the MCP protocol, not inference. Whatever is decided below, this output is wrong and misleads every new user who runs it.

Deprecation that never took effectโ€‹

ai-executor.ts:8 and every prompt-execution.ts export already carry:

@deprecated ... use OrchestrationDirective returns instead. See ADR-014

They have been marked deprecated while remaining reachable. A deprecation notice that nothing enforces is documentation, not a migration.

Decision driversโ€‹

  1. Two live paths is the actual defect. Whichever is kept, keeping both is what produced the current state โ€” false catalog claims, a self-contradicting diagnostic, and deprecated code on the default path.
  2. Coupling is small. Five files import ai-executor; openai is the only external dependency. The bulk is deletable string-building.
  3. #1416 depends on the answer. The registry refactor must decide what a ToolDefinition carries. If ~30 tools change shape or disappear, doing #1416 first means doing it twice.
  4. Removal cannot currently be cleared by governance. retirement.py src/prompts returns a blocking NO_RETIREMENT_EVIDENCE: no retirement provider is bound in .repo-governor.json (INV-013). REMOVAL_READY is unreachable until one is, which is a manifest change and a human act โ€” required for options B and C.

Options consideredโ€‹

A โ€” Keep both, fix the honesty problems onlyโ€‹

Correct the 58 false hasCEMCPDirective claims, fix check_ai_execution_status, leave both paths live.

For: smallest change; no capability lost. Against: does not address driver 1. The two-path condition persists, and #1416 still has to model both. This is the status quo with better labelling.

B โ€” Complete the ADR-014 migration, then delete the legacy layerโ€‹

Give the remaining ~63 tools directives (or deterministic behaviour), then remove ai-executor, prompt-execution, src/prompts/, and the APE / Reflexion / Knowledge-Generation frameworks. Drop the openai dependency.

For: one path; ~11,152 LOC and one external dependency removed; finishes what ADR-014 started; simplifies #1416 substantially. Against: largest effort, and it is not a mechanical deletion โ€” each of the 63 tools needs a decision about what it should return instead. Requires a bound retirement provider before the engine will clear it.

C โ€” Delete the legacy layer now, without completing the migrationโ€‹

Remove the AI path immediately; tools without directives return deterministic output or an explicit "not implemented".

For: fastest route to one path. Against: ~63 tools lose their current behaviour at once, with no replacement designed. Ships a regression to anyone relying on prompt-mode returns.

D โ€” Keep legacy AI execution, retire CE-MCP insteadโ€‹

Supersede ADR-014; make full mode the default and invest in the OpenRouter path.

For: honest about what most tools actually do today. Against: reintroduces a hard external-API dependency and a key requirement for every user; contradicts an Accepted ADR with a working 12-tool implementation. Listed for completeness โ€” no evidence gathered here supports it.

Recommendationโ€‹

B, staged โ€” but see the caveat.

The evidence supports one path, and CE-MCP is the one with an accepted ADR and a working implementation. B is the only option that both removes the duplication and leaves the 63 tools with designed behaviour.

The caveat is scope. "Give 63 tools directives" is a research task, not a checklist, and this project has twice this month mistaken one for the other. B should be admitted as its own milestone with per-batch acceptance criteria, not as a single issue.

Regardless of A/B/C/D, two things should be fixed immediately because they are wrong under every option:

  • the 58 false hasCEMCPDirective: true claims
  • check_ai_execution_status telling users to buy a key they do not need

Decisionโ€‹

Option B โ€” finish the ADR-014 migration, then delete the legacy AI execution layer.

Recorded by the repository owner on 2026-08-26 (#1414).

The remaining ~63 tools get CE-MCP directives or deterministic behaviour. Once they do, src/utils/ai-executor.ts, src/utils/prompt-execution.ts, src/prompts/, and the APE / Reflexion / Knowledge-Generation frameworks are removed, and the openai dependency is dropped.

This is admitted as its own milestone with per-batch acceptance criteria, not as a single issue. "Give 63 tools directives" is a research task wearing a checklist's clothes, and this project has twice mistaken one for the other inside a single month.

What changed since the options were writtenโ€‹

Two things made B cheaper than it looked when drafted:

  • ADR-022 adopted MADR. Structured front matter means "what should this tool return instead of a prompt" has a deterministic answer for a meaningful share of the ADR tools, rather than 63 independent judgement calls.
  • The catalog now reports honestly. #1456 corrected 58 false hasCEMCPDirective claims, so the 12-of-75 reality is visible rather than hidden behind a claim of 70.

And one thing made A less tenable: the prompt-only fallback is not merely dead weight. adr-suggestion-tool.ts:1101 writes [ADR_CONTENT_PLACEHOLDER] into the user's real ADR directory and returns a prompt telling the caller to fill it in. That path exists because prompt-only is live.

Consequencesโ€‹

Good

  • One execution path. The condition that produced false catalog claims, a self-contradicting diagnostic, and deprecated code on the default path is removed rather than relabelled.
  • ~11,152 LOC and the openai dependency go once the migration completes.
  • #1416's ToolDefinition shape no longer has to model two return contracts.

Bad

  • The migration is the expensive part and is not mechanical. Sixty-three tools each need a decision about what they return instead.
  • Until it completes both paths remain live, so the repository carries the transition cost on top of the cost of the old state.

Neutral

  • Nothing is deleted by this decision. It sets direction; removal is gated on the migration and on the retirement provider below.

Confirmationโ€‹

Verifiable now:

  • This ADR's ## Status reads Accepted.
  • A retirement provider is bound in .repo-governor.json, so retirement.py no longer returns a blocking NO_RETIREMENT_EVIDENCE.

Verifiable at completion, and deliberately not claimed yet:

  • grep -rl "ai-executor" src/ returns nothing
  • src/prompts/ does not exist
  • openai is absent from package.json
  • every tool in TOOL_CATALOG either has a directive or returns a computed result

Binding a retirement provider does not authorise deletion. The retirement-analysis adapter advertises dynamic_references, runtime_usage, public_contracts and migration_obligations as false, and autonomous_deletion as false always. Static analysis therefore yields RETIREMENT_REVIEW, never REMOVAL_READY โ€” the correct outcome, not a limitation to route around.

  • ADR-014 (CE-MCP architecture) โ€” Accepted; this ADR determines whether it is finished or superseded
  • ADR-015 (APE optimization strategy) โ€” Accepted; its subject is inside the removal scope of B and C
  • #1414 โ€” this decision
  • #1416 โ€” the registry refactor, whose scope depends on the answer
  • The aggregator (~2,600 LOC, opt-in SaaS) is explicitly out of scope; it is a separate commercial question