# Architecture Review: 2026-01-23

> **Status: Historical** — Point-in-time snapshot from v2.2.0. Many findings have been resolved in subsequent versions (current: v2.26.1). See deprecation-pipeline.md for tracked resolutions.

**Reviewer:** System Architect (Claude Opus 4.6)
**Timestamp:** 2026-01-23 18:16:39 EST
**Repository:** nexus-agents v2.2.0

---

## CLAUDE.md Requirements Digest

Key requirements extracted from CLAUDE.md that govern this review:

1. **Prime Directive:** correctness > simplicity > performance > cleverness
2. **Timezone Authority:** All timestamps use America/New_York (ET)
3. **Version Currency:** Never use deprecated software
4. **Documentation Style:** Direct, honest, technically precise (no marketing fluff)
5. **Quality Gates:** `pnpm lint`, `pnpm typecheck`, `pnpm test` must pass
6. **Discovered Issue Protocol:** Create GitHub issues immediately when problems found
7. **Research Tracking:** Check docs/research/ before implementing new techniques
8. **Priority Definitions:** P1 (high impact), P2 (medium), P3 (lower), P4 (infrastructure)

---

## Phase 1: Naming Entropy Analysis

### Files with "Enhanced" Suffix

| File                                                        | Canonical                | Status                        |
| ----------------------------------------------------------- | ------------------------ | ----------------------------- |
| `src/cli-adapters/adapters/gemini-adapter-enhanced.ts`      | `gemini-adapter.ts`      | **Active naming entropy**     |
| `src/cli-adapters/adapters/gemini-adapter-enhanced.test.ts` | `gemini-adapter.test.ts` | **Test for enhanced variant** |

### Analysis

**gemini-adapter.ts vs gemini-adapter-enhanced.ts:**

- **Original (`gemini-adapter.ts`):** 125 lines, basic subprocess adapter, uses `GeminiResponseParser`
- **Enhanced (`gemini-adapter-enhanced.ts`):** 451 lines, adds tiered timeouts, circuit breaker, resilient parser, retry logic

**Current Usage:**

- `factory.ts` imports `EnhancedGeminiCliAdapter` (line 14) and creates it for all Gemini requests
- The original `GeminiCliAdapter` is exported but **only used in tests**
- Both are exported from `adapters/index.ts`

**Recommendation:** Merge enhanced features into canonical `gemini-adapter.ts`. The original file is effectively dead code in production.

### Other Naming Patterns Checked

- `*-v2*`: No matches in source code
- `*-new*`: No matches in source code (only in node_modules)
- `*-updated*`: No matches in source code (only in node_modules)
- `*-rewrite*`: No matches in source code (only husky hooks)

---

## Phase 2: Static Analysis Results

### ESLint (pnpm lint)

```
Status: PASSED (cache hit)
Errors: 0
Warnings: 0
```

### TypeScript (pnpm typecheck)

```
Status: PASSED
Duration: 28.16s
```

### Tests (pnpm test)

```
Status: FAILED
Test Files: 2 failed | 299 passed
Tests: 6 failed | 9401 passed | 11 skipped
```

**Failing Tests:**

| File                    | Test                                                             | Root Cause                                                   |
| ----------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------ |
| `codex-adapter.test.ts` | `getModelInfo() should return correct cost info for o3`          | Test expects model 'o3' but adapter defaults to empty string |
| `codex-adapter.test.ts` | `argument building > should build correct arguments`             | Test expects `-m o3` but adapter omits model when empty      |
| `codex-adapter.test.ts` | `argument building > should include task content as JSON string` | Test expects `JSON.stringify()` wrapping that was removed    |

**Root Cause Analysis:**

The `CodexCliAdapter` was refactored (shell: true removed, model defaults to empty) but tests were not updated. The adapter now:

- Uses `model ?? ''` instead of `model ?? 'o3'` (line 89)
- Doesn't specify `-m` flag when model is empty (lines 259-262)
- Passes task content directly without JSON.stringify (line 271)

### Circular Dependencies

```
Status: 10 circular dependencies found
```

| #   | Cycle                                                          | Severity |
| --- | -------------------------------------------------------------- | -------- |
| 1   | `expert-types.ts` <-> `expert-documentation-types.ts`          | P2       |
| 2   | `forest-result-types.ts` <-> `forest-types.ts`                 | P2       |
| 3   | `research-index-types.ts` <-> `research-index-stats-types.ts`  | P2       |
| 4   | `swarm-observer-types.ts` <-> `swarm-observer-payloads.ts`     | P2       |
| 5   | `swarm-observer-types.ts` <-> `swarm-observer-schemas.ts`      | P2       |
| 6   | `routing-metrics.ts` <-> `routing-metrics-helpers.ts`          | P2       |
| 7   | `orchestrate-command.ts` <-> `orchestrate-puppeteer.ts`        | P1       |
| 8   | `stpa-helpers.ts` <-> `stpa-analysis-helpers.ts`               | P2       |
| 9   | `agentic-memory-db-helpers.ts` <-> `agentic-memory-helpers.ts` | P2       |
| 10  | `result-comparator-helpers.ts` <-> `result-comparator.ts`      | P2       |

**Common Pattern:** Files import types from main module while main module imports helpers from the split file. Solution: Extract shared types to a `-types.ts` file that both can import.

---

## Phase 3: Architecture Inventory

### Core Subsystems

| Subsystem          | Path                 | Files | Purpose                                                      |
| ------------------ | -------------------- | ----- | ------------------------------------------------------------ |
| **Core**           | `src/core/`          | 27    | Types, Result<T,E>, logger, errors, tracing, artifacts       |
| **MCP Server**     | `src/mcp/`           | 60    | MCP protocol, tools, middleware, safety (STPA)               |
| **CLI Adapters**   | `src/cli-adapters/`  | 105   | Claude/Gemini/Codex subprocess adapters, routing             |
| **Model Adapters** | `src/adapters/`      | 36    | Claude/OpenAI/Gemini/Ollama API adapters                     |
| **Agents**         | `src/agents/`        | 116   | Orchestrator, experts, collaboration, skills, self-improving |
| **Workflows**      | `src/workflows/`     | 15    | Workflow engine, template registry, parallel executor        |
| **Context**        | `src/context/`       | 63    | Memory backends, token counting, belief memory               |
| **CLI Commands**   | `src/cli/`           | 101   | doctor, orchestrate, review, research, setup, etc.           |
| **Consensus**      | `src/consensus/`     | 22    | Voting protocols, weighted voting, higher-order              |
| **Observability**  | `src/observability/` | 23    | Swarm observer, routing metrics, dashboards                  |

### Key Architectural Boundaries

```
                    ┌──────────────────────────────┐
                    │         MCP Server           │
                    │   (tools, middleware)        │
                    └──────────────┬───────────────┘
                                   │
          ┌────────────────────────┼────────────────────────┐
          │                        │                        │
          ▼                        ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  CLI Adapters   │    │   Agents        │    │   Workflows     │
│ (subprocess)    │    │ (Orchestrator,  │    │ (template       │
│                 │    │  experts)       │    │  execution)     │
└────────┬────────┘    └────────┬────────┘    └────────┬────────┘
         │                      │                      │
         ▼                      ▼                      ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ Model Adapters  │    │   Context       │    │   Consensus     │
│ (API calls)     │    │ (memory, tokens)│    │ (voting)        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                      │                      │
         └──────────────────────┴──────────────────────┘
                                │
                                ▼
                    ┌─────────────────────────────┐
                    │          Core               │
                    │ (types, Result, logger)     │
                    └─────────────────────────────┘
```

### Adapter Duplication

There are **two adapter systems**:

1. **`src/adapters/`** - Direct API adapters (OpenAI SDK, Anthropic SDK, etc.)
2. **`src/cli-adapters/`** - Subprocess adapters wrapping CLI tools (claude, gemini, codex)

Both are valid for different use cases:

- API adapters: Direct integration, streaming, lower latency
- CLI adapters: Tool-based, sandboxed, uses local auth

---

## Phase 4: Findings

### P0 (Must Fix)

| #   | Finding                               | Evidence                             | Impact                           | Recommendation                                    | Effort |
| --- | ------------------------------------- | ------------------------------------ | -------------------------------- | ------------------------------------------------- | ------ |
| 1   | **Failing tests in CI-critical path** | `codex-adapter.test.ts` (6 failures) | Blocks releases, CI gates broken | Update tests to match refactored adapter behavior | S      |

### P1 (Should Fix)

| #   | Finding                                        | Evidence                                                | Impact                                     | Recommendation                                    | Effort |
| --- | ---------------------------------------------- | ------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------- | ------ |
| 2   | **Naming entropy: gemini-adapter-enhanced**    | `gemini-adapter-enhanced.ts` (451 lines)                | Confusing dual exports, maintenance burden | Merge enhanced into canonical, deprecate original | M      |
| 3   | **Circular dependency in orchestrate-command** | `orchestrate-command.ts` <-> `orchestrate-puppeteer.ts` | CLI execution at risk                      | Extract shared types to `-types.ts`               | S      |
| 4   | **10 circular dependencies total**             | `madge --circular` output                               | Build/bundle issues, testing complexity    | Systematic extraction of shared types             | M      |

### P2 (Nice to Have)

| #   | Finding                                    | Evidence                                        | Impact                             | Recommendation                                    | Effort |
| --- | ------------------------------------------ | ----------------------------------------------- | ---------------------------------- | ------------------------------------------------- | ------ |
| 5   | **Original GeminiCliAdapter is dead code** | Only referenced in tests, factory uses Enhanced | Unused code in bundle              | Remove after merge-back                           | S      |
| 6   | **Duplicate adapter systems**              | `src/adapters/` vs `src/cli-adapters/`          | Conceptual overlap, docs confusion | Document distinction clearly in architecture docs | S      |

---

## Phase 5: GitHub Issues to Create

### Issue 1: P0 - Fix failing Codex adapter tests

**Title:** `bug: Codex adapter tests fail after model default refactor`
**Labels:** `bug`, `P0`, `testing`
**Body:**

```markdown
## Problem

6 tests failing in `codex-adapter.test.ts` after recent refactoring:

- `getModelInfo() should return correct cost info for o3`
- `argument building should build correct arguments for basic task`
- `argument building should include task content as JSON string`

## Root Cause

The adapter was refactored to:

1. Default model to empty string instead of 'o3' (line 89)
2. Omit `-m` flag when model is empty (lines 259-262)
3. Pass task content without JSON.stringify (line 271)

Tests were not updated to match new behavior.

## Solution

Either:

1. Update tests to match new behavior (empty model default, no JSON wrapping)
2. Restore 'o3' as default model if that was unintended

## Files

- `/packages/nexus-agents/src/cli-adapters/adapters/codex-adapter.ts`
- `/packages/nexus-agents/src/cli-adapters/adapters/codex-adapter.test.ts`
```

### Issue 2: P1 - Merge gemini-adapter-enhanced into gemini-adapter

**Title:** `tech-debt: Merge gemini-adapter-enhanced.ts back into gemini-adapter.ts`
**Labels:** `tech-debt`, `P1`, `refactor`
**Body:**

```markdown
## Problem

Two Gemini adapters exist with confusing naming:

- `gemini-adapter.ts` (125 lines) - Basic implementation, **unused in production**
- `gemini-adapter-enhanced.ts` (451 lines) - Full implementation with circuit breaker, timeouts, resilient parser

The factory (`factory.ts` line 59) exclusively uses `EnhancedGeminiCliAdapter`. The original is dead code.

## Solution

1. Merge enhanced features into `gemini-adapter.ts`
2. Update exports to use single class name `GeminiCliAdapter`
3. Remove `gemini-adapter-enhanced.ts`
4. Update tests to use consolidated adapter

## Files

- `/packages/nexus-agents/src/cli-adapters/adapters/gemini-adapter.ts`
- `/packages/nexus-agents/src/cli-adapters/adapters/gemini-adapter-enhanced.ts`
- `/packages/nexus-agents/src/cli-adapters/adapters/index.ts`
- `/packages/nexus-agents/src/cli-adapters/factory.ts`

## References

- Issue #366 (original enhanced adapter)
```

### Issue 3: P1 - Fix 10 circular dependencies

**Title:** `tech-debt: Resolve 10 circular dependency cycles`
**Labels:** `tech-debt`, `P1`, `architecture`
**Body:**

```markdown
## Problem

`madge --circular` reports 10 circular dependency cycles:

1. `agents/experts/expert-types.ts` <-> `expert-documentation-types.ts`
2. `agents/reasoning/forest-result-types.ts` <-> `forest-types.ts`
3. `indexer/research-index/research-index-types.ts` <-> `research-index-stats-types.ts`
4. `observability/swarm-observer-types.ts` <-> `swarm-observer-payloads.ts`
5. `observability/swarm-observer-types.ts` <-> `swarm-observer-schemas.ts`
6. `observability/routing-metrics.ts` <-> `routing-metrics-helpers.ts`
7. `cli/orchestrate-command.ts` <-> `orchestrate-puppeteer.ts`
8. `mcp/safety/stpa-helpers.ts` <-> `stpa-analysis-helpers.ts`
9. `context/agentic-memory-db-helpers.ts` <-> `agentic-memory-helpers.ts`
10. `testing/storage/result-comparator-helpers.ts` <-> `result-comparator.ts`

## Impact

- Bundle size issues with tree-shaking
- Testing complexity
- Potential runtime issues with module initialization order

## Solution Pattern

For each cycle, extract shared types to a dedicated `-types.ts` file:

1. Identify types imported bidirectionally
2. Create new `*-shared-types.ts` file
3. Move shared types to new file
4. Update both original files to import from shared

## Priority Order

1. `orchestrate-command.ts` (P1 - CLI critical path)
2. `routing-metrics.ts` (P1 - observability)
3. Remaining 8 (P2 - lower impact)
```

---

## Summary

| Priority | Count | Status                                 |
| -------- | ----- | -------------------------------------- |
| P0       | 1     | **Requires immediate fix** - CI broken |
| P1       | 3     | Should fix in next sprint              |
| P2       | 2     | Nice to have                           |

**Test Health:** 98.6% pass rate (6 failures / 9418 tests)
**Lint Health:** Clean
**Type Health:** Clean
**Dependency Health:** 10 cycles to resolve

---

## Action Items

1. [x] Create GitHub issue for P0 test failures (#390)
2. [x] Create GitHub issue for gemini-adapter merge (#389)
3. [x] Create GitHub issue for circular dependencies (#392)
4. [x] Fix P0 test failures immediately (commit 7f82a84)
5. [ ] Schedule P1 work for next sprint

---

_Review completed: 2026-01-23 18:16:39 EST_
_Updated: 2026-01-23 18:30 EST - P0 fixed, issues created_
_Next review due: 2026-01-30 or when EPIC closed_
