# Raw Types that Should Be Typed Primitives in the mngr library (identified on 2026-01-19)

## 1. AgentInfo.type uses plain str instead of AgentTypeName

Description: In `libs/mngr/imbue/mngr/api/list.py:43`, `AgentInfo.type` is declared as `type: str = Field(description="Agent type (claude, codex, etc.)")`. However, `AgentTypeName` already exists in `primitives.py` as a `NonEmptyStr` subclass specifically for agent type names.

Recommendation: Change `type: str` to `type: AgentTypeName` to ensure type consistency and validation across the codebase. This will prevent invalid empty strings and maintain consistency with how agent types are used elsewhere (e.g., in `BaseAgent` which uses `AgentTypeName`).

Decision: Accept

## 2. CertifiedHostData.image uses plain str instead of ImageReference

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py:185-188`, the `image` field is declared as `image: str | None = Field(...)`. The codebase already has `ImageReference` in `primitives.py` which is specifically designed to represent container or VM image references.

Recommendation: Change `image: str | None` to `image: ImageReference | None`. This ensures that the image reference stored in certified host data has the same validation (non-empty) as when images are specified elsewhere.

Decision: Accept

## 3. HostInfo.name uses plain str instead of HostName

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py:257`, `HostInfo.name` is declared as `name: str = Field(description="Host name")`. The codebase has `HostName` in `primitives.py` which provides non-empty validation and useful methods like `provider_name` and `short_name` properties.

Recommendation: Change `name: str` to `name: HostName`. This ensures consistency with how host names are handled in the rest of the codebase (e.g., in `Host.create_host()` which takes `HostName`).

Decision: Accept

## 4. VolumeInfo uses plain int instead of SizeBytes for size_bytes

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py:216`, `VolumeInfo.size_bytes` is declared as `size_bytes: int = Field(...)`. The codebase already has `SizeBytes` (extending `NonNegativeInt`) in the same file for this exact purpose.

Recommendation: Change `size_bytes: int` to `size_bytes: SizeBytes`. Other similar data types like `WorkDirInfo`, `LogFileInfo`, and `BuildCacheInfo` already use `SizeBytes`, so this would make `VolumeInfo` consistent.

Decision: Accept

## 5. SnapshotInfo.size_bytes uses plain int instead of SizeBytes

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py:201-204`, `SnapshotInfo.size_bytes` is declared as `size_bytes: int | None = Field(...)`. The codebase has `SizeBytes` specifically for this purpose.

Recommendation: Change `size_bytes: int | None` to `size_bytes: SizeBytes | None`. This provides automatic validation that the size cannot be negative.

Decision: Accept

## 6. HookDefinition.command uses plain str instead of CommandString

Description: In `libs/mngr/imbue/mngr/config/data_types.py:70`, `HookDefinition.command` is declared as `command: str = Field(...)`. The codebase has `CommandString` in `primitives.py` which ensures commands are non-empty.

Recommendation: Change `command: str` to `command: CommandString`. This validates that hook commands cannot be empty strings, which would cause runtime failures.

Decision: Accept

## 7. Plugin interfaces use plain str instead of PluginName

Description: Multiple methods in the interfaces use `plugin_name: str` as a parameter type:
- `interfaces/host.py:169` - `get_plugin_data(self, plugin_name: str)`
- `interfaces/host.py:174` - `set_plugin_data(self, plugin_name: str, ...)`
- `interfaces/host.py:183` - `get_reported_plugin_state_file_data(self, plugin_name: str, ...)`
- `interfaces/host.py:198` - `get_reported_plugin_state_files(self, plugin_name: str)`
- `interfaces/agent.py:172-196` - Multiple similar methods
- `agents/base_agent.py:351-375` - Implementations of the above

The codebase has `PluginName` in `primitives.py` which validates that plugin names are non-empty.

Recommendation: Change all `plugin_name: str` parameters to `plugin_name: PluginName`. This ensures consistency and prevents bugs from empty plugin names.

Decision: Accept

## 8. Agent registry functions use plain str instead of AgentTypeName

Description: In `libs/mngr/imbue/mngr/agents/agent_registry.py`:
- Line 57: `def get_agent_class(agent_type: str) -> type[AgentInterface]:`
- Line 65: `def get_agent_config_class(agent_type: str) -> type[AgentTypeConfig]:`

The codebase has `AgentTypeName` for this exact purpose.

Recommendation: Change `agent_type: str` to `agent_type: AgentTypeName` in both functions. The internal lookup can still use `str()` conversion if needed, but the interface should accept the typed parameter.

Decision: Accept

## 9. AgentInfo.idle_mode uses plain str instead of IdleMode enum

Description: In `libs/mngr/imbue/mngr/api/list.py:58`, `idle_mode` is declared as `idle_mode: str | None = Field(...)`. The codebase has `IdleMode` enum in `primitives.py` with all valid idle modes.

Recommendation: Change `idle_mode: str | None` to `idle_mode: IdleMode | None`. This provides type safety and ensures only valid idle modes are represented.

Decision: Accept

## 10. NamedCommand.command uses plain str instead of CommandString

Description: In `libs/mngr/imbue/mngr/interfaces/host.py:480-481`, `NamedCommand` has:
```python
command: str = Field(description="Command to run in new window")
```

The codebase has `CommandString` which validates non-empty commands.

Recommendation: Change to `command: CommandString = Field(...)`. Commands should never be empty, so the type system should enforce this.

Decision: Accept

## 11. ConnectionOptions.attach_command uses plain str instead of CommandString

Description: In `libs/mngr/imbue/mngr/api/data_types.py:172-175`, `attach_command` is declared as `attach_command: str | None = Field(...)`.

Recommendation: Change to `attach_command: CommandString | None`. When specified, attach commands should be non-empty.

Decision: Accept

## 12. Provider/Plugin config registry functions use plain str

Description: Several config registry functions use plain `str`:
- `config/plugin_registry.py:19` - `def get_plugin_config_class(plugin_name: str)`
- `config/provider_registry.py:47` - `def get_provider_config_class(backend: str)`

Recommendation:
- Change `plugin_name: str` to `plugin_name: PluginName`
- Change `backend: str` to `backend: ProviderBackendName`

Decision: Accept

## 13. EnvVar should use typed keys for environment variable names

Description: In `libs/mngr/imbue/mngr/config/data_types.py:54-55`, `EnvVar` has `key: str` and `value: str`. While values can be arbitrary strings (including empty), environment variable names should follow certain rules (e.g., non-empty, valid identifier characters).

Recommendation: Create an `EnvVarName` type (extending `NonEmptyStr`) for the key field. This ensures environment variable names are non-empty and could later be extended to validate naming conventions (e.g., no spaces, starts with letter or underscore).

Decision: Accept

## 14. ModalProviderInstance uses plain str for app_name

Description: In `libs/mngr/imbue/mngr/providers/modal/instance.py:84`, `app_name` is declared as `app_name: str = Field(...)`.

Recommendation: Create a `ModalAppName` type (extending `NonEmptyStr`) for Modal-specific naming, or at minimum change to `app_name: NonEmptyStr`. This prevents empty app names which would cause Modal API errors.

Decision: Accept

## 15. GitOptions branch-related fields use plain str

Description: In `libs/mngr/imbue/mngr/interfaces/host.py:346-358`, several git-related fields use plain strings:
- `base_branch: str | None`
- `new_branch_name: str | None`
- `new_branch_prefix: str`

Recommendation: Create a `GitBranchName` type (extending `NonEmptyStr`) for branch names. The prefix could remain as `str` since empty prefix is valid (meaning no prefix).

Decision: Accept

## 16. Various timeout/duration fields use plain int instead of typed durations

Description: Multiple places use `int` for timeouts/durations:
- `interfaces/data_types.py:157,171` - `idle_timeout_seconds: int`
- `interfaces/host.py:392` - `idle_timeout_seconds: int | None`
- `interfaces/host.py:612` - `message_delay_seconds: float`
- `config/data_types.py:201,205` - `max_log_files: int`, `max_log_size_mb: int`
- `providers/modal/instance.py:85` - `default_timeout: int`

Recommendation: Consider creating domain-specific types like `Seconds(NonNegativeInt)` for timeouts, `SizeMegabytes(NonNegativeInt)` for sizes in MB, and `Count(PositiveInt)` for counts that must be positive. However, this is lower priority than the semantic types above since the meaning is clear from field names.

Decision: Accept (lower priority)

## 17. Resource counts use plain int without validation

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py`:
- Line 113: `count: int = Field(description="Number of CPUs allocated")`
- Line 123: `count: int = Field(default=0, description="Number of GPUs allocated")`

CPU count should never be negative, and typically should be at least 1. GPU count can be 0 but never negative.

Recommendation: Change CPU `count` to use `PositiveInt` and GPU `count` to use `NonNegativeInt`. Alternatively, create domain-specific `CpuCount` and `GpuCount` types.

Decision: Accept

## 18. recency_idx uses plain int without validation

Description: In `libs/mngr/imbue/mngr/interfaces/data_types.py:205-208`, `recency_idx` is `int` with a default of 0. This index should never be negative.

Recommendation: Change to `recency_idx: NonNegativeInt = Field(default=NonNegativeInt(0), ...)`. This ensures the index cannot become negative through bugs.

Decision: Accept

## 19. API find.py uses plain str for agent/host/path

Description: In `libs/mngr/imbue/mngr/api/find.py:27-29`, `LocationSpec` uses:
```python
agent: str | None = Field(description="Agent ID or name")
host: str | None = Field(description="Host ID or name")
path: str | None = Field(description="File path")
```

Recommendation: These are intentionally union types (could be ID or name), so they cannot simply use `AgentId` or `AgentName`. Consider creating a `AgentRef` type that can hold either, or leave as `str` with clear documentation. Lower priority as the current design is intentional.

Decision: Defer (intentional design for flexibility)

## 20. ConnectionOptions.message uses plain str

Description: In `libs/mngr/imbue/mngr/api/data_types.py:160-163`, `message` is `str | None`.

Recommendation: This is acceptable as messages can legitimately be any string content. No change needed.

Decision: Reject (messages can be arbitrary content)
