Skip to content
Back to skills

512 2026 01 27 00 10 38 Issue 311 Core Types Layer Violation 11872dd0

ASecurity

**Date:** 2026-01-27 **Owner:** claude-agent **Phase:** Research **Issue:** https://github.com/alchemiststudiosDOTai/tunacode/issues/311

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 1, 2026
businessgogitdocumentation

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned June 1, 2026

npx -y skills add tools-only/X-Skills --skill 512-2026-01-27_00-10-38_issue-311-core-types-layer-violation_11872dd0 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 512 2026 01 27 00 10 38 Issue 311 Core Types Layer Violation 11872dd0?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 512 2026 01 27 00 10 38 Issue 311 Core Types Layer Violation 11872dd0
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-512-2026-01-27-00-10-38-issue-311-core-types-layer/badge)](https://www.skillsdirectory.com/skills/tools-only-512-2026-01-27-00-10-38-issue-311-core-types-layer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Research - Issue #311: core → types Layer Violation

**Date:** 2026-01-27
**Owner:** claude-agent
**Phase:** Research
**Issue:** https://github.com/alchemiststudiosDOTai/tunacode/issues/311

## Goal

Understand the scope and implications of the `core → types` layer violation reported in issue #311, and determine the correct remediation approach.

## Findings

### The Reported Problem

Issue #311 proposes a strict 5-layer hierarchy:

```
ui (Layer 0) → core (Layer 1) → tools/indexing/lsp (Layer 2) → utils (Layer 3) → types/configuration (Layer 4)
```

Under this model, `core` should NOT directly import from `types` (skips Layer 2 and 3).

### Current Architecture (DEPENDENCY_MAP.md)

The frozen baseline (2026-01-26) shows a different model:

```
ui          → outer layer (TUI)
core        → business logic
tools       → agent tools
indexing    → code indexing infrastructure
lsp         → language server protocol
─────────────────────────────────
utils       ┐
types       │ utils-level (importable from anywhere)
configuration│
constants   ┘
```

**Key difference:** Types is classified as "utils-level" - a horizontal layer that ANY vertical layer can import from. This is consistent with CLAUDE.md Gate 2.

### Architectural Contradiction

| Document | Position | Status |
|----------|----------|--------|
| Issue #311 | types is Layer 4, core cannot import | Proposed change |
| DEPENDENCY_MAP.md | types is utils-level, importable anywhere | Frozen baseline |
| CLAUDE.md Gate 2 | types/ is utils-level module | Authoritative |

The frozen baseline marks `core → types: 26 imports` as "✅ valid".

### Import Inventory (17 files, 26 imports)

#### State Management (5 imports)
| File | Types Imported |
|------|----------------|
| `core/state.py:17` | ConversationState, InputSessions, ModelName, RuntimeState, SessionId, UserConfig |
| `core/state.py:27` | UsageMetrics |
| `core/user_configuration.py:5-6` | UserConfig, StateManagerProtocol |
| `core/lsp_status.py:3` | UserConfig |

#### Core Types Re-export (2 imports)
| File | Types Imported |
|------|----------------|
| `core/types.py:5` | ModelName, ToolArgs, ToolCallback, ToolName, ToolResultCallback, ToolStartCallback |
| `core/types.py:14` | UsageMetrics |

#### Configuration (1 import)
| File | Types Imported |
|------|----------------|
| `core/configuration.py:31` | ModelPricing |

#### Logging (1 import)
| File | Types Imported |
|------|----------------|
| `core/logging/manager.py:10` | StateManagerProtocol |

#### Agent Core (1 import)
| File | Types Imported |
|------|----------------|
| `core/agents/main.py:22` | AgentRun, ModelName, NoticeCallback, StateManagerProtocol, StreamingCallback, ToolCallback, ToolResultCallback, ToolStartCallback |

#### Agent Components (8 imports)
| File | Types Imported |
|------|----------------|
| `core/agents/agent_components/agent_config.py:23` | ModelName, PydanticAgent, SessionStateProtocol |
| `core/agents/agent_components/agent_helpers.py:5` | CanonicalToolCall |
| `core/agents/agent_components/response_state.py:6` | AgentState |
| `core/agents/agent_components/state_transition.py:7` | AgentState |
| `core/agents/agent_components/streaming.py:16` | StreamingCallback |

#### Orchestrator (4 imports)
| File | Types Imported |
|------|----------------|
| `core/agents/agent_components/orchestrator/orchestrator.py:5-6` | AgentState, StreamingCallback, ToolCallback, ToolResultCallback, ToolStartCallback |
| `core/agents/agent_components/orchestrator/tool_dispatcher.py:12-13` | AgentState, ToolArgs, ToolCallId, ToolCallback, ToolResultCallback, ToolStartCallback |
| `core/agents/agent_components/orchestrator/usage_tracker.py:6-7` | UsageMetrics, normalize_request_usage |

#### Resume/Sanitization (4 imports)
| File | Types Imported |
|------|----------------|
| `core/agents/resume/sanitize.py:18-20` | ToolCallId, CanonicalMessage, MessageRole, SystemPromptPart, ToolCallRegistry |
| `core/agents/resume/sanitize_debug.py:10` | ToolCallId |

### Types Layer Analysis

The `src/tunacode/types/` directory contains 9 files with types in three categories:

#### Category A: Valid Utils-Level (Should Stay)

These types are used across multiple layers and are correctly placed:

| File | Types | Used By |
|------|-------|---------|
| `base.py` | 42 primitive aliases (ModelName, ToolArgs, etc.) | core, tools, utils |
| `pydantic_ai.py` | PydanticAgent, MessageHistory, NormalizedUsage | core, utils |
| `canonical.py` | CanonicalMessage, UsageMetrics, MessageRole, etc. | core, utils/messaging/adapter |
| `callbacks.py` | ToolCallback, StreamingCallback, etc. | core (dependency injection) |

#### Category B: Core-Specific (Candidates for Move)

These types are ONLY used by core and should not be in utils-level:

| File | Types | Reason |
|------|-------|--------|
| `dataclasses.py` | ResponseState | Only used in core/agents/agent_components/response_state.py |
| `dataclasses.py` | AgentState | Only used in core agent state transitions |
| `state.py` | SessionStateProtocol | Protocol for core's SessionState |
| `state.py` | StateManagerProtocol | Protocol for core's StateManager |
| `state_structures.py` | ConversationState, TaskState, RuntimeState, UsageState | Only compose core's SessionState |
| `tool_registry.py` | ToolCallRegistry | Stateful business logic, only used in RuntimeState and sanitize.py |

#### Category C: Dead Code (Delete)

| File | Types | Reason |
|------|-------|--------|
| `dataclasses.py` | CommandContext | Never imported anywhere |
| `callbacks.py` | ProcessRequestCallback | Only referenced in dead CommandContext |

### Key Patterns Found

**Pattern 1: Core Facade** (commit 10b48c30)
- When UI needed LSP functionality, a facade was created in core
- Pattern: `ui → core/facade.py → tools/implementation.py → lsp/`

**Pattern 2: Move to Utils** (commit be735754)
- Shared constants moved from tools to `utils/system/ignore_patterns.py`
- Both tools and indexing import from there

**Pattern 3: Central Re-export** (current)
- `types/__init__.py` re-exports everything, hiding internal structure
- `core/types.py` already re-exports a subset for core's use

## Knowledge Gaps

1. **Architectural Intent Unclear**: Is issue #311's strict layering the desired target state, or is the current "types as utils-level" the correct model?

2. **Migration Strategy**: If we adopt strict layering, do we:
   - Move core-specific types to `core/types/`?
   - Create re-exports in utils layer?
   - Use dependency injection?

3. **Backward Compatibility**: How do we handle the 26 existing imports without breaking changes?

## Recommendations

### Option A: Keep Current Architecture (Minimal Change)

If types/ remains "utils-level":
- Close issue #311 as "works as designed"
- Delete dead code (CommandContext, ProcessRequestCallback)
- Update documentation to clarify the model

### Option B: Strict Layer Enforcement (Issue #311's Proposal)

If we adopt strict layering:

**Phase 1: Move Core-Specific Types**
1. Create `src/tunacode/core/types/` directory
2. Move: ResponseState, AgentState, StateManagerProtocol, SessionStateProtocol
3. Move: ConversationState, TaskState, RuntimeState, UsageState
4. Move: ToolCallRegistry
5. Update 17 files in core to import from `core/types/`

**Phase 2: Cleanup**
1. Delete dead code: CommandContext, ProcessRequestCallback
2. Update `types/__init__.py` to only export utils-level types

**Phase 3: Verify**
1. Run grimp to confirm zero violations
2. Update DEPENDENCY_MAP.md

### My Recommendation

**Option B is the correct path forward**, but with nuance:

The current architecture has types/ as utils-level because it evolved organically. Issue #311 correctly identifies that core-specific types (protocols, state structures) should live in core, not in a shared layer.

However, the issue's proposed fix (re-exports through utils/tools) adds indirection. The cleaner fix is:

1. **Move core-specific types to `core/types/`** - types that describe core's internal structure belong in core
2. **Keep shared types in `types/`** - primitives, callbacks, canonical message types remain utils-level
3. **Result**: core imports its own types directly (no indirection), and shared types from utils-level (valid)

This maintains the "utils-level is importable anywhere" principle while moving core-specific implementation details out of the shared layer.

## References

- Issue: https://github.com/alchemiststudiosDOTai/tunacode/issues/311
- `docs/architecture/DEPENDENCY_MAP.md` - Current baseline
- `CLAUDE.md` Gate 2 - Dependency direction rules
- `src/tunacode/types/` - Types layer (9 files)
- `src/tunacode/core/types.py` - Existing core re-export pattern

Files in this skill

  • README.md1.1 KB
  • skill.md8.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.