Skip to content

[codex] migrate codexd into a self-contained Culture agent#7

Open
OriNachum wants to merge 18 commits into
mainfrom
codex/culture-agent-migration-local
Open

[codex] migrate codexd into a self-contained Culture agent#7
OriNachum wants to merge 18 commits into
mainfrom
codex/culture-agent-migration-local

Conversation

@OriNachum
Copy link
Copy Markdown
Contributor

Summary

  • migrate the Codex Culture daemon and shared harness internals into codexd as a self-contained runtime
  • add daemon and managed repo workflow commands, including workspace validation, Git helpers, and Codex app-server orchestration
  • package Codex Culture assets, update docs, and add focused tests to validate the migrated surface

Why

codexd previously only contained package metadata, docs, and scaffold-level CLI behavior. This change lands the runnable Codex-only daemon and the delegated remote-repository workflow described in the migration plan.

Validation

  • uv run pytest -n auto --cov=codexd
  • uv run black --check codexd tests
  • uv run isort --check-only codexd tests
  • uv run flake8 codexd tests
  • uv run bandit -c pyproject.toml -r codexd
  • markdownlint-cli2 "**/*.md"
  • uv build
  • uv run python -m codexd --version

@github-actions
Copy link
Copy Markdown

Version not bumped: pyproject.toml still has 0.1.2 (same as main). Bump before merging to avoid a failed PyPI publish.

@OriNachum OriNachum marked this pull request as ready for review May 22, 2026 15:17
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Migrate Codex Culture daemon into self-contained codexd runtime with harness orchestration

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Migrate Codex Culture daemon and shared harness internals into codexd as a self-contained
  runtime
• Implement universal BaseDaemon orchestrator managing IRC transport, socket server, agent runner,
  and webhook client for all four backends (claude/codex/copilot/acp)
• Add daemon lifecycle management with attention-based polling, crash recovery with circuit breaker,
  and IPC request dispatch
• Implement CodexAgentRunner for managing Codex app-server subprocess via JSON-RPC with turn
  execution, token tracking, and OpenTelemetry instrumentation
• Add daemon and managed repo workflow commands including workspace validation, Git helpers, and
  Codex app-server orchestration
• Implement shared harness modules: IRC transport client with tracing, Unix socket IPC server,
  webhook alerting, message buffering, and room metadata parsing
• Add OpenTelemetry integration with tracer/meter initialization, audit JSONL sink with rotation,
  and W3C trace-context propagation for IRC messages
• Implement per-target attention state machine with stimulus-driven promotion and time-based decay
  for poll-loop scheduling
• Add PID file management for daemon process lifecycle tracking and server listing
• Implement repo workflow orchestration for clone, run, commit, and push operations with workspace
  validation
• Package Codex Culture assets (culture.yaml, SKILL.md) and update documentation
• Add comprehensive test coverage for all migrated components including daemon config, attention
  tracking, telemetry, Git operations, and CLI dispatch
Diagram
flowchart LR
  CLI["CLI<br/>daemon/repo commands"]
  BaseDaemon["BaseDaemon<br/>universal orchestrator"]
  CodexDaemon["CodexDaemon<br/>Codex-specific"]
  IRC["IRC Transport<br/>async client"]
  SocketServer["Socket Server<br/>IPC"]
  AgentRunner["AgentRunner<br/>JSON-RPC"]
  Supervisor["Supervisor<br/>behavior eval"]
  Telemetry["Telemetry<br/>OTEL/audit"]
  RepoWorkflow["Repo Workflow<br/>Git ops"]
  Attention["Attention<br/>state machine"]
  
  CLI -->|start/repo| CodexDaemon
  CodexDaemon -->|extends| BaseDaemon
  BaseDaemon -->|uses| IRC
  BaseDaemon -->|uses| SocketServer
  BaseDaemon -->|uses| Attention
  CodexDaemon -->|uses| AgentRunner
  CodexDaemon -->|uses| Supervisor
  BaseDaemon -->|uses| Telemetry
  CLI -->|repo run/push| RepoWorkflow
  RepoWorkflow -->|executes| AgentRunner

Loading

File Changes

1. codexd/harness/base_daemon.py ✨ Enhancement +1047/-0

Universal daemon orchestrator with lifecycle and IPC management

• Implements BaseDaemon class as the universal orchestrator for all four backend daemons
 (claude/codex/copilot/acp), managing IRC transport, socket server, agent runner, and webhook client
• Provides shared lifecycle methods (start, stop), polling loops (legacy and attention-based),
 crash recovery with circuit breaker, and IPC request dispatch
• Includes attention tracking, pause/resume scheduling, status querying, and supervisor integration
 for agent lifecycle management
• Implements comprehensive IRC command handlers (send, read, join, part, threads, topics) and agent
 message routing with optional queuing for backends

codexd/harness/base_daemon.py


2. tests/test_telemetry_audit.py 🧪 Tests +685/-0

Audit sink lifecycle and rotation test coverage

• Comprehensive unit tests for codexd.telemetry.audit module covering AuditSink lifecycle, record
 building, and rotation logic
• Tests disabled behavior, queue overflow handling, JSONL writing, file rotation on size/date
 boundaries, and error scenarios
• Validates init_audit idempotency, writer task management, and graceful shutdown with drain
 timeout
• Covers edge cases like stat errors, open failures, serialization errors, and token usage caching

tests/test_telemetry_audit.py


3. codexd/harness/config.py ✨ Enhancement +592/-0

Shared configuration dataclasses and YAML persistence layer

• Defines shared config dataclasses (BaseServerConnConfig, BaseSupervisorConfig,
 BaseAgentConfig, BaseTelemetryConfig, BaseDaemonConfig) used by all four backends
• Implements YAML I/O functions (load_config, save_config) with atomic writes and
 backend-specific field filtering
• Provides attention band parsing, validation, and per-agent override merging with legacy poll
 interval migration
• Includes agent/server management operations (add, rename, remove, archive/unarchive) that preserve
 backend-specific fields via raw YAML manipulation

codexd/harness/config.py


View more (68)
4. codexd/agent/agent_runner.py ✨ Enhancement +548/-0

Codex app-server JSON-RPC runner with turn management

• Implements CodexAgentRunner to manage Codex app-server subprocess via JSON-RPC over stdio with
 isolated environment
• Handles turn execution with configurable timeout, token usage tracking, and auto-approval of
 permission requests
• Manages prompt queue, notification dispatch (turn lifecycle, token usage, errors), and graceful
 process termination
• Integrates OpenTelemetry tracing and metrics recording for LLM calls with outcome tracking
 (success/timeout/error)

codexd/agent/agent_runner.py


5. codexd/telemetry/metrics.py ✨ Enhancement +276/-0

OpenTelemetry metrics initialization and instrument registry

• Implements init_metrics() function for idempotent OpenTelemetry MeterProvider bootstrap with
 gRPC OTLP exporter configuration
• Defines MetricsRegistry dataclass aggregating all Plan-3 server-side instruments (message flow,
 events, federation, clients, audit, bots)
• Handles disabled telemetry by binding instruments to OTEL proxy meter, and manages global provider
 installation with reuse logic
• Provides test reset functionality and compression configuration for gRPC exporters

codexd/telemetry/metrics.py


6. tests/agent/test_packaged_assets.py 🧪 Tests +22/-0

Packaged Culture assets validation tests

• Validates that packaged Codex skill documentation mentions codexd paths and culture channel
 references
• Verifies pyproject.toml hatch build configuration includes culture.yaml and SKILL.md in
 wheel force-include list

tests/agent/test_packaged_assets.py


7. codexd/harness/irc_transport.py ✨ Enhancement +405/-0

Async IRC transport client with tracing and reconnection

• Implements async IRC client for agent harnesses with connection management, message routing, and
 OTEL tracing support
• Handles IRC protocol operations (PRIVMSG, NOTICE, TOPIC, ROOMINVITE) with message buffering and
 mention detection
• Supports automatic reconnection with exponential backoff and W3C traceparent tag injection for
 distributed tracing
• Provides callbacks for mention/ambient message handling and optional per-message metrics
 instrumentation

codexd/harness/irc_transport.py


8. tests/agent/test_agent_runner.py 🧪 Tests +436/-0

Agent runner telemetry and metrics instrumentation tests

• Comprehensive test suite for CodexAgentRunner OTEL instrumentation covering success, timeout, and
 error paths
• Tests token usage metrics recording with late delivery scenarios and missing token data handling
• Validates configurable turn timeout and callback execution during failures
• Uses mocked JSON-RPC to avoid requiring live codex binary in CI

tests/agent/test_agent_runner.py


9. codexd/telemetry/audit.py ✨ Enhancement +381/-0

Audit JSONL sink with rotation and metrics tracking

• Implements async JSONL audit sink with daily rotation and size-based file splitting
• Provides bounded queue-based writer task to avoid blocking event loop on disk I/O
• Tracks audit writes metrics (ok/error outcomes) and enforces 0600 file permissions
• Idempotent initialization and graceful shutdown with configurable drain timeout

codexd/telemetry/audit.py


10. codexd/harness/telemetry.py ✨ Enhancement +322/-0

Harness-side OpenTelemetry initialization and metrics registry

• Bootstraps OpenTelemetry TracerProvider and MeterProvider for agent harnesses with idempotent
 initialization
• Registers LLM metrics instruments (tokens, call duration, call count) and attention metrics
• Provides record_llm_call helper to record metrics for LLM calls with optional token usage data
• Supports no-op proxy mode when telemetry is disabled and per-backend service identification via
 Resource

codexd/harness/telemetry.py


11. codexd/harness/skill_irc_client.py ✨ Enhancement +342/-0

Skill IRC client library and CLI for daemon communication

• Async client library for connecting to culture daemon Unix socket with JSON Lines protocol
• Provides high-level IRC methods (send, read, ask, join, part, channels, who, topic) and agent
 commands (compact, clear)
• Includes CLI entry point with subcommand routing and environment-based socket path resolution
• Handles response correlation by ID and routes whisper notifications to pending list

codexd/harness/skill_irc_client.py


12. tests/harness/test_daemon_config.py 🧪 Tests +345/-0

Daemon configuration management and YAML serialization tests

• Tests for daemon configuration loading, saving, and manipulation (add/rename/remove/archive agents
 and servers)
• Validates YAML round-trip serialization, unknown field stripping, and default value application
• Covers attention config merging with per-agent overrides and agent name sanitization
• Tests collision detection and error handling for duplicate operations

tests/harness/test_daemon_config.py


13. codexd/harness/attention.py ✨ Enhancement +249/-0

Per-target attention state machine with decay and polling

• Pure state machine for per-target attention tracking with four bands (HOT, WARM, COOL, IDLE)
• Implements stimulus-driven promotion (direct/ambient) and time-based decay with configurable hold
 windows
• Provides due_targets method for poll-loop driver to identify targets needing attention and apply
 decay
• Supports manual band override and target seeding for quiet channels; fully deterministic (clock
 passed in)

codexd/harness/attention.py


14. tests/harness/test_attention.py 🧪 Tests +206/-0

Attention tracker state machine unit tests

• Unit tests for AttentionTracker state machine covering stimulus promotion, decay, and poll
 scheduling
• Tests band transitions (direct/ambient/decay), hold window expiration, and clock jump handling
• Validates per-target isolation, manual override, and seeding behavior for quiet channels
• Confirms decay walks one band per hold and IDLE is terminal

tests/harness/test_attention.py


15. tests/test_pidfile.py 🧪 Tests +227/-0

PID file management and process tracking tests

• Tests for PID file management (write/read/remove) and port file operations with round-trip
 validation
• Covers process liveness checks, culture process identification via /proc/cmdline, and safe name
 sanitization
• Tests server listing with filtering for dead PIDs and non-culture processes
• Validates default server tracking and PID file renaming

tests/test_pidfile.py


16. codexd/telemetry/tracing.py ✨ Enhancement +156/-0

Culture daemon OpenTelemetry tracer initialization

• Bootstraps OpenTelemetry TracerProvider for Culture daemon with idempotent initialization
• Parses sampler configuration (parentbased_always_on, traceidratio, always_off) and gRPC
 compression settings
• Returns no-op tracer when telemetry disabled; reuses first enabled provider for subsequent calls
• Includes test reset helper to clear global provider state between test runs

codexd/telemetry/tracing.py


17. tests/harness/test_rooms.py 🧪 Tests +54/-0

Room metadata parsing function unit tests

• Tests for parse_room_meta function covering key-value pair parsing with semicolon delimiters
• Validates whitespace stripping, special handling for instructions field with embedded semicolons
• Tests edge cases (empty input, missing equals, trailing semicolons, values with equals signs)

tests/harness/test_rooms.py


18. codexd/repo/__init__.py Miscellaneous +1/-0

Remote repository workflows package marker

• Package initialization file for remote repository workflows module

codexd/repo/init.py


19. tests/test_telemetry_tracing.py 🧪 Tests +183/-0

Telemetry tracing initialization and sampler tests

• Comprehensive unit tests for codexd.telemetry.tracing.init_telemetry covering sampler building
 and enabled/disabled paths
• Tests validate OTLP exporter configuration, gRPC compression handling, and idempotent provider
 initialization
• Includes fixtures for module state reset and stub exporter classes to avoid network traffic

tests/test_telemetry_tracing.py


20. tests/test_protocol_message.py 🧪 Tests +171/-0

IRC protocol message parsing and formatting tests

• Unit tests for IRC message parsing and formatting with IRCv3 tag support
• Validates tag value escape/unescape sequences, message component parsing, and round-trip
 serialization
• Tests edge cases like malformed input, empty parameters, and trailing parameter handling

tests/test_protocol_message.py


21. tests/test_telemetry_metrics.py 🧪 Tests +180/-0

Telemetry metrics initialization and provider tests

• Unit tests for codexd.telemetry.metrics.init_metrics covering disabled and enabled paths
• Validates MeterProvider installation, OTLP exporter configuration, and idempotent initialization
• Tests compression handling and error recovery in provider shutdown

tests/test_telemetry_metrics.py


22. codexd/pidfile.py ✨ Enhancement +167/-0

Daemon process lifecycle and PID file management

• PID and port file management for culture daemon instances in ~/.culture/pids
• Provides safe name sanitization, process liveness checking, and server listing functionality
• Includes helpers for reading/writing PID/port files and renaming daemon entries

codexd/pidfile.py


23. codexd/agent/supervisor.py ✨ Enhancement +161/-0

Codex supervisor for agent behavior evaluation

CodexSupervisor class that evaluates agent productivity using codex exec subprocess
• Implements windowed turn observation, supervisor prompt templating, and verdict processing
• Handles escalation thresholds and dispatches whisper/escalation callbacks

codexd/agent/supervisor.py


24. tests/repo/test_workflow.py 🧪 Tests +153/-0

Repository workflow integration tests

• End-to-end tests for repo workflow commands (clone, run, commit, push)
• Validates workspace validation, Git operations, and app-server turn execution
• Tests error handling and no-op scenarios when no changes are made

tests/repo/test_workflow.py


25. codexd/telemetry/context.py ✨ Enhancement +121/-0

W3C trace context propagation for IRC messages

• W3C trace-context extraction and injection for IRCv3 message tags
• Implements extract_traceparent_from_tags and inject_traceparent for distributed tracing
• Validates traceparent format and handles oversized tracestate values per protocol spec

codexd/telemetry/context.py


26. codexd/agent/daemon.py ✨ Enhancement +129/-0

Codex agent daemon with queue-based routing

CodexDaemon class bridging Codex agent to IRC network via queue-based mention routing
• Integrates CodexAgentRunner and CodexSupervisor with meta-response stripping
• Implements system prompt building and relay line cleaning for IRC output

codexd/agent/daemon.py


27. codexd/harness/queued_base_daemon.py ✨ Enhancement +133/-0

Queued mention routing for agent daemons

• FIFO mention-queue routing variant of BaseDaemon used by codex/copilot/acp backends
• Implements queue-shape hooks for mention/poll/status/roominvite enqueuing
• Handles turn-error recovery with consecutive failure tracking and agent pausing

codexd/harness/queued_base_daemon.py


28. codexd/harness/supervisor.py ✨ Enhancement +124/-0

Shared supervisor framework for all backends

• Shared supervisor primitives including SupervisorVerdict dataclass and Supervisor class
• Implements deque-windowed turn observation with injected evaluation function
• Handles escalation thresholds and failure tracking across all backends

codexd/harness/supervisor.py


29. codexd/cli.py ✨ Enhancement +117/-6

CLI expansion with daemon and repo commands

• Expanded CLI with daemon start, repo run/push/clean subcommands
• Implements config loading, agent selection, and daemon lifecycle management
• Adds signal handling for graceful shutdown and error reporting with hints

codexd/cli.py


30. codexd/harness/socket_server.py ✨ Enhancement +139/-0

Unix socket IPC server for harness communication

• Unix-domain socket server for harness IPC with request/response and whisper messaging
• Implements client connection handling, queued whisper delivery, and error responses
• Shared harness module used by all backends

codexd/harness/socket_server.py


31. tests/agent/test_daemon_cli.py 🧪 Tests +124/-0

Daemon CLI command dispatch and integration tests

• CLI dispatch tests for daemon start, repo run/push/clean commands
• Validates argument parsing, config loading, error reporting, and daemon lifecycle
• Tests signal handling and daemon startup/shutdown ordering

tests/agent/test_daemon_cli.py


32. tests/harness/test_message_buffer.py 🧪 Tests +108/-0

Message buffer ring storage and filtering tests

• Tests for MessageBuffer ring buffer with per-channel message storage
• Validates read cursor tracking, thread filtering, and nick collection
• Tests ring buffer eviction and limit enforcement

tests/harness/test_message_buffer.py


33. codexd/protocol/message.py ✨ Enhancement +128/-0

IRC protocol message parsing and formatting

• IRC protocol message dataclass with RFC 2812 and IRCv3 tag support
• Implements tag value escape/unescape, message parsing, and wire format serialization
• Handles prefix, command, params, and trailing parameter conventions

codexd/protocol/message.py


34. tests/test_telemetry_context.py 🧪 Tests +107/-0

Trace context extraction and injection tests

• Unit tests for W3C trace-context extraction and injection in IRC messages
• Validates traceparent format validation, tracestate handling, and context building
• Tests round-trip serialization and current span context retrieval

tests/test_telemetry_context.py


35. codexd/repo/workflow.py ✨ Enhancement +114/-0

Repository workflow orchestration for Codex

• Repo command workflows for clone, run, commit, and push operations
• Implements run_repo_task, push_workspace, and clean_workspace entry points
• Integrates Git operations with CodexAgentRunner for delegated task execution

codexd/repo/workflow.py


36. codexd/agent/config.py ✨ Enhancement +80/-0

Codex backend configuration and defaults

• Codex backend configuration with thin shim over shared harness config
• Defines backend-specific defaults: agent="codex", model="gpt-5.4", telemetry service name
• Re-exports stable surface from shared config module

codexd/agent/config.py


37. codexd/harness/message_buffer.py ✨ Enhancement +76/-0

Message buffer with thread detection and ring storage

• Per-target message buffer with thread-prefix detection and ring eviction
• Implements read cursor tracking for incremental message retrieval
• Provides thread filtering and nick collection across channels

codexd/harness/message_buffer.py


38. tests/repo/test_workspace.py 🧪 Tests +84/-0

Workspace and Git reference validation tests

• Validation tests for managed workspace paths, branch names, and remote URLs
• Tests path traversal prevention, home directory protection, and checkout name derivation
• Validates HTTPS/SSH remote acceptance and local path rejection

tests/repo/test_workspace.py


39. codexd/repo/workspace.py ✨ Enhancement +67/-0

Workspace path and Git reference validation

• Managed workspace validation for repo commands with path traversal prevention
• Implements branch name validation, remote URL parsing, and checkout name derivation
• Enforces workspace containment and prevents home directory usage

codexd/repo/workspace.py


40. tests/repo/test_git_ops.py 🧪 Tests +61/-0

Git operations integration tests

• Integration tests for Git operations (clone, checkout, commit, push)
• Validates dirty worktree detection, commit SHA retrieval, and branch operations
• Tests with seeded bare repositories and working copies

tests/repo/test_git_ops.py


41. codexd/harness/webhook.py ✨ Enhancement +71/-0

Webhook alerting for harness events

• HTTP webhook client for harness alert events with IRC fallback
• Implements async event firing with configurable event filtering
• Shared harness module used by all backends

codexd/harness/webhook.py


42. codexd/repo/git.py ✨ Enhancement +59/-0

Git command wrapper for repo workflows

• Small Git command wrapper for managed repo workflows
• Implements clone, checkout, commit, push, and status operations
• Raises GitError on command failures with stderr/stdout details

codexd/repo/git.py


43. codexd/harness/ipc.py ✨ Enhancement +46/-0

IPC message framing and serialization

• JSON line-framing helpers for harness IPC (whispers and responses)
• Implements message encoding/decoding, request/response factories, and whisper construction
• Shared harness module used by all backends

codexd/harness/ipc.py


44. tests/test_package_metadata.py 🧪 Tests +38/-0

Package metadata and dependency validation

• Validates runtime dependencies include harness requirements (pyyaml, agentirc, opentelemetry)
• Checks pytest-asyncio availability in dev dependencies
• Verifies .codexd/ is in .gitignore

tests/test_package_metadata.py


45. codexd/harness/rooms.py ✨ Enhancement +43/-0

Room metadata parsing helper

• Managed-room helpers for parsing room metadata with key=value pairs
• Handles special instructions field that captures remaining text verbatim
• Shared harness module moved from bundled IRCd in culture 9.0.0

codexd/harness/rooms.py


46. tests/agent/test_daemon_surface.py 🧪 Tests +38/-0

Codex daemon public API surface tests

• Public daemon surface tests for CodexDaemon constructor and class attributes
• Validates documented kwargs, backend name, coroutine signatures, and unknown kwarg rejection

tests/agent/test_daemon_surface.py


47. tests/test_utility_modules.py 🧪 Tests +37/-0

Utility module constants and async helpers tests

• Unit tests for migrated utility modules (_constants, aio, constants)
• Validates default timeouts, system constants, event patterns, and async helpers

tests/test_utility_modules.py


48. codexd/telemetry/__init__.py ✨ Enhancement +39/-0

Telemetry module public API and re-exports

• OpenTelemetry integration public surface with re-exports from submodules
• Exports audit, context, metrics, and tracing initialization functions
• Provides TRACEPARENT_TAG, TRACESTATE_TAG, and related context helpers

codexd/telemetry/init.py


49. codexd/_constants.py ✨ Enhancement +21/-0

Cross-backend constants and timeout defaults

• Project-wide constants for cross-backend use (default turn timeout)
• Documents timeout configuration strategy and backend-specific constant locations
• Provides foundation for future YAML-driven runtime configuration

codexd/_constants.py


50. codexd/harness/webhook_types.py ✨ Enhancement +32/-0

Shared webhook configuration types

• Shared WebhookConfig dataclass for alert event configuration
• Defines webhook URL, IRC channel, and event type filtering
• Byte-identical across all four backends with no backend-specific behavior

codexd/harness/webhook_types.py


51. tests/agent/test_supervisor.py 🧪 Tests +22/-0

Codex supervisor verdict processing tests

• Unit test for CodexSupervisor verdict processing and whisper dispatch
• Validates correction verdict triggers whisper callback with correct parameters

tests/agent/test_supervisor.py


52. codexd/agent/constants.py ✨ Enhancement +17/-0

Codex backend timeout constants

• Codex backend timeout constants (inner request, process termination, kill grace periods)
• Re-exports cross-backend DEFAULT_TURN_TIMEOUT_SECONDS from _constants

codexd/agent/constants.py


53. codexd/agent/skill/irc_client.py ✨ Enhancement +20/-0

IRC skill client re-export wrapper

• IRC Skill Client re-export preserving per-backend import path
• Delegates to shared codexd.harness.skill_irc_client implementation
• Maintains subprocess entry point python -m codexd.agent.skill.irc_client

codexd/agent/skill/irc_client.py


54. codexd/__main__.py 📝 Documentation +1/-1

Module docstring clarification

• Minor docstring update from "Entry point" to "Run codexd as a module"

codexd/main.py


55. AGENTS.md Additional files +4/-6

...

AGENTS.md


56. CHANGELOG.md Additional files +8/-0

...

CHANGELOG.md


57. README.md Additional files +22/-4

...

README.md


58. codexd/agent/__init__.py Additional files +1/-0

...

codexd/agent/init.py


59. codexd/agent/culture.yaml Additional files +29/-0

...

codexd/agent/culture.yaml


60. codexd/agent/skill/SKILL.md Additional files +194/-0

...

codexd/agent/skill/SKILL.md


61. codexd/agent/skill/__init__.py Additional files +0/-0

...

codexd/agent/skill/init.py


62. codexd/aio.py Additional files +12/-0

...

codexd/aio.py


63. codexd/constants.py Additional files +17/-0

...

codexd/constants.py


64. codexd/harness/__init__.py Additional files +6/-0

...

codexd/harness/init.py


65. codexd/protocol/__init__.py Additional files +0/-0

...

codexd/protocol/init.py


66. docs/superpowers/plans/2026-05-22-codexd-culture-agent-migration.md Additional files +1697/-0

...

docs/superpowers/plans/2026-05-22-codexd-culture-agent-migration.md


67. docs/superpowers/specs/2026-05-22-codexd-culture-agent-migration-design.md Additional files +211/-0

...

docs/superpowers/specs/2026-05-22-codexd-culture-agent-migration-design.md


68. pyproject.toml Additional files +40/-3

...

pyproject.toml


69. tests/agent/test_config.py Additional files +17/-0

...

tests/agent/test_config.py


70. tests/test_cli.py Additional files +2/-1

...

tests/test_cli.py


71. tests/test_readme.py Additional files +13/-0

...

tests/test_readme.py


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 22, 2026

Code Review by Qodo

🐞 Bugs (5) 📘 Rule violations (2)

Context used
✅ Compliance rules (platform): 11 rules

Grey Divider


Action required

1. culture-irc skill file misplaced 📘 Rule violation ⌂ Architecture
Description
A new Codex skill definition file was added at codexd/agent/skill/SKILL.md instead of under
.agents/skills/, which violates the required repository-local skills layout. This can break skill
discovery and creates a non-standard skill location in the repo.
Code

codexd/agent/skill/SKILL.md[R1-14]

Evidence
PR Compliance ID 725779 requires repository-local Codex skill files to live under .agents/skills/.
The added codexd/agent/skill/SKILL.md contains skill metadata front-matter (name: culture-irc)
and is packaged from that non-standard location.

Rule 725779: Place repository-local Codex skills in .agents/skills directory
codexd/agent/skill/SKILL.md[1-14]
pyproject.toml[41-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A repository-local Codex skill definition (`SKILL.md` with skill front-matter) was introduced outside `.agents/skills/`.

## Issue Context
The repo already uses `.agents/skills/<skill>/SKILL.md` for skill discovery/standardization. The new skill file is currently located under the Python package path and is also explicitly included in the wheel build.

## Fix Focus Areas
- codexd/agent/skill/SKILL.md[1-194]
- pyproject.toml[41-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Package version not bumped 📘 Rule violation § Compliance
Description
This PR adds significant production functionality (daemon/runtime and new CLI workflows) but the
package version in pyproject.toml remains 0.1.2. Compliance requires updating the version (and
maintaining the changelog entry) for PRs that change published runtime behavior.
Code

CHANGELOG.md[R8-14]

Evidence
PR Compliance ID 725780 requires version updates for production/published changes. The changelog
documents new added functionality under [Unreleased], but the package version in pyproject.toml
is still 0.1.2, indicating no version bump occurred alongside these changes.

Rule 725780: Require version and changelog updates in applicable PRs
CHANGELOG.md[8-14]
pyproject.toml[2-4]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Production code and CLI behavior changed, but the distribution version was not updated.

## Issue Context
`CHANGELOG.md` has new entries under `[Unreleased]` describing newly added daemon and repo-work functionality, while `pyproject.toml` still declares `version = "0.1.2"`.

## Fix Focus Areas
- pyproject.toml[2-4]
- CHANGELOG.md[8-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Git base option injection 🐞 Bug ⛨ Security
Description
checkout_branch() forwards the user-supplied base directly into git checkout -B ... base, so a
base starting with - is interpreted as a git option and can change behavior or fail
unexpectedly. This is reachable from repo run --base via run_repo_task() with no validation.
Code

codexd/repo/git.py[R39-44]

Evidence
The CLI-exposed base is forwarded into checkout_branch() and then used as a positional argument
to git checkout -B without validation, enabling option-style injection into git’s argument
parsing.

codexd/repo/workflow.py[48-66]
codexd/repo/git.py[39-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`codexd.repo.git.checkout_branch()` passes `base` directly to `git checkout -B`, allowing option-style values (e.g., starting with `-`) to be parsed as git flags.

### Issue Context
`base` originates from the CLI (`codexd repo run --base`) and is forwarded through `codexd.repo.workflow.run_repo_task()`.

### Fix Focus Areas
- codexd/repo/workspace.py[36-56]
- codexd/repo/workflow.py[48-66]
- codexd/repo/git.py[39-44]

### Suggested fix
- Add a `validate_base_ref()` (or reuse a generalized ref validator) that rejects:
 - leading `-`
 - whitespace/control chars
 - `..`, trailing `.lock`, `@{`, etc. (same class of checks as branch safety)
- Call it in `run_repo_task()` before invoking `checkout_branch()`.
- Optionally, also validate inside `checkout_branch()` as defense-in-depth.
- Consider verifying the ref exists (e.g., `git rev-parse --verify <base>^{commit}`) and raise a clear `GitError` if not.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. Git commands can hang 🐞 Bug ☼ Reliability
Description
run_git() and clone() call subprocess.run(...) with no timeout and default environment, so
clone/fetch/push can block indefinitely and wedge repo workflows. This can leave the CLI stuck
with no recovery path besides external interruption.
Code

codexd/repo/git.py[R13-33]

Evidence
The repo workflow’s git operations rely on subprocess.run with no timeout, so any non-terminating
git invocation will block the entire command indefinitely.

codexd/repo/git.py[13-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Git subprocesses are invoked without timeouts and with an inherited environment, so they can block forever (network stall, credential prompts).

### Issue Context
`codexd repo run/push` relies on these helpers to complete; a hang wedges the whole workflow.

### Fix Focus Areas
- codexd/repo/git.py[13-37]
- codexd/repo/workflow.py[48-83]

### Suggested fix
- Add a timeout parameter (configurable; e.g., 300s) to `run_git()` / `clone()`.
- Disable interactive prompts by setting env overrides (at least):
 - `GIT_TERMINAL_PROMPT=0`
 - optionally `GIT_ASKPASS=` and/or `SSH_ASKPASS=`
- Catch `subprocess.TimeoutExpired` and raise `GitError` with a clear message including the git args.
- Consider emitting a hint that the remote may require credentials when prompt is disabled.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Killed process not reaped 🐞 Bug ☼ Reliability
Description
CodexAgentRunner._terminate_process() calls kill() on timeout but never awaits process.wait(),
which can leave a zombie subprocess and leak resources. Over repeated failures/timeouts this can
exhaust process table resources and destabilize the daemon.
Code

codexd/agent/agent_runner.py[R164-176]

Evidence
The terminate path awaits wait(), but the kill-on-timeout path returns without awaiting wait(),
meaning the subprocess may not be reaped.

codexd/agent/agent_runner.py[164-176]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
On terminate timeout, the code sends SIGKILL but does not await `wait()`, so the child may not be reaped.

### Issue Context
This path is reachable whenever the codex app-server becomes unresponsive during shutdown.

### Fix Focus Areas
- codexd/agent/agent_runner.py[164-177]

### Suggested fix
- After `self._process.kill()`, always `await self._process.wait()` (optionally under a short timeout).
- Ensure `_process` is cleared/reset after shutdown to avoid reuse of a dead handle.
- Consider logging when escalation to kill occurs so operators can spot repeated unclean terminations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Signal handler startup crash 🐞 Bug ☼ Reliability
Description
_run_daemons() unconditionally registers SIGINT/SIGTERM handlers via loop.add_signal_handler(),
which raises at runtime on event loops/platforms that do not support signal handlers. This prevents
daemon startup in those environments and provides no fallback shutdown path.
Code

codexd/cli.py[R113-121]

Evidence
The code calls loop.add_signal_handler without any error handling, so any unsupported runtime will
raise and abort the daemon run.

codexd/cli.py[113-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Daemon startup assumes `loop.add_signal_handler` is available; when it is not, startup fails.

### Issue Context
This is used for `codexd daemon start` lifecycle control.

### Fix Focus Areas
- codexd/cli.py[113-124]

### Suggested fix
- Wrap `add_signal_handler` registration in `try/except (NotImplementedError, RuntimeError)`.
- If unsupported, fall back to a shutdown strategy that still works (e.g., rely on `KeyboardInterrupt` around `asyncio.run(...)`, or use a different cross-platform cancellation mechanism).
- Emit a clear log/hint when falling back so users understand behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

7. Codex stderr discarded 🐞 Bug ◔ Observability
Description
The codex app-server subprocess is spawned with stderr=DEVNULL, so startup/runtime errors emitted
on stderr are lost and failures become difficult to diagnose. This reduces observability when the
app-server fails before producing valid JSON-RPC on stdout.
Code

codexd/agent/agent_runner.py[R109-116]

Evidence
The subprocess is explicitly created with stderr redirected to DEVNULL, guaranteeing that stderr
diagnostics are not available to logs or callers.

codexd/agent/agent_runner.py[96-116]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The codex subprocess stderr is discarded, removing critical diagnostics.

### Issue Context
Stdout is used for JSON-RPC, so stderr is the natural channel for non-protocol errors.

### Fix Focus Areas
- codexd/agent/agent_runner.py[96-120]

### Suggested fix
- Change `stderr=DEVNULL` to `stderr=PIPE`.
- Add a background task to read stderr lines and log them (rate/size limited) without mixing into the JSON-RPC stdout stream.
- Ensure the stderr reader task is cancelled/awaited during `stop()` to avoid leaks.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@OriNachum OriNachum deployed to testpypi May 22, 2026 15:22 — with GitHub Actions Active
@sonarqubecloud
Copy link
Copy Markdown

Comment on lines +1 to +14
---
name: culture-irc
description: >
Communicate over IRC on the Culture network. Use when the user asks to
read messages, send messages, check who's online, join/part channels, or
interact with other agents on the IRC mesh.
---

# IRC Skill for Culture

This skill lets you communicate over IRC through the culture daemon.
The daemon runs as a background process and maintains a persistent IRC connection.

## Setup
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. culture-irc skill file misplaced 📘 Rule violation ⌂ Architecture

A new Codex skill definition file was added at codexd/agent/skill/SKILL.md instead of under
.agents/skills/, which violates the required repository-local skills layout. This can break skill
discovery and creates a non-standard skill location in the repo.
Agent Prompt
## Issue description
A repository-local Codex skill definition (`SKILL.md` with skill front-matter) was introduced outside `.agents/skills/`.

## Issue Context
The repo already uses `.agents/skills/<skill>/SKILL.md` for skill discovery/standardization. The new skill file is currently located under the Python package path and is also explicitly included in the wheel build.

## Fix Focus Areas
- codexd/agent/skill/SKILL.md[1-194]
- pyproject.toml[41-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread CHANGELOG.md Outdated
Comment on lines +8 to +14
## [Unreleased]

### Added

- Migrated the Codex Culture daemon into `codexd` as a self-contained runtime.
- Added `codexd repo run` for managed clone, Codex app-server execution, commit,
and branch push workflows.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Package version not bumped 📘 Rule violation § Compliance

This PR adds significant production functionality (daemon/runtime and new CLI workflows) but the
package version in pyproject.toml remains 0.1.2. Compliance requires updating the version (and
maintaining the changelog entry) for PRs that change published runtime behavior.
Agent Prompt
## Issue description
Production code and CLI behavior changed, but the distribution version was not updated.

## Issue Context
`CHANGELOG.md` has new entries under `[Unreleased]` describing newly added daemon and repo-work functionality, while `pyproject.toml` still declares `version = "0.1.2"`.

## Fix Focus Areas
- pyproject.toml[2-4]
- CHANGELOG.md[8-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread codexd/repo/git.py
Comment on lines +39 to +44
def checkout_branch(repo: Path, branch: str, *, base: str | None = None) -> None:
if base:
run_git(repo, "fetch", "origin")
run_git(repo, "checkout", "-B", branch, base)
return
run_git(repo, "checkout", "-B", branch)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Git base option injection 🐞 Bug ⛨ Security

checkout_branch() forwards the user-supplied base directly into git checkout -B ... base, so a
base starting with - is interpreted as a git option and can change behavior or fail
unexpectedly. This is reachable from repo run --base via run_repo_task() with no validation.
Agent Prompt
### Issue description
`codexd.repo.git.checkout_branch()` passes `base` directly to `git checkout -B`, allowing option-style values (e.g., starting with `-`) to be parsed as git flags.

### Issue Context
`base` originates from the CLI (`codexd repo run --base`) and is forwarded through `codexd.repo.workflow.run_repo_task()`.

### Fix Focus Areas
- codexd/repo/workspace.py[36-56]
- codexd/repo/workflow.py[48-66]
- codexd/repo/git.py[39-44]

### Suggested fix
- Add a `validate_base_ref()` (or reuse a generalized ref validator) that rejects:
  - leading `-`
  - whitespace/control chars
  - `..`, trailing `.lock`, `@{`, etc. (same class of checks as branch safety)
- Call it in `run_repo_task()` before invoking `checkout_branch()`.
- Optionally, also validate inside `checkout_branch()` as defense-in-depth.
- Consider verifying the ref exists (e.g., `git rev-parse --verify <base>^{commit}`) and raise a clear `GitError` if not.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread codexd/repo/git.py
Comment on lines +13 to +33
def run_git(cwd: Path, *args: str) -> subprocess.CompletedProcess[str]:
result = subprocess.run(
["git", *args],
cwd=cwd,
text=True,
capture_output=True,
check=False,
)
if result.returncode != 0:
detail = result.stderr.strip() or result.stdout.strip() or "git command failed"
raise GitError(detail)
return result


def clone(remote: str, checkout_path: Path) -> None:
result = subprocess.run(
["git", "clone", remote, str(checkout_path)],
text=True,
capture_output=True,
check=False,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Git commands can hang 🐞 Bug ☼ Reliability

run_git() and clone() call subprocess.run(...) with no timeout and default environment, so
clone/fetch/push can block indefinitely and wedge repo workflows. This can leave the CLI stuck
with no recovery path besides external interruption.
Agent Prompt
### Issue description
Git subprocesses are invoked without timeouts and with an inherited environment, so they can block forever (network stall, credential prompts).

### Issue Context
`codexd repo run/push` relies on these helpers to complete; a hang wedges the whole workflow.

### Fix Focus Areas
- codexd/repo/git.py[13-37]
- codexd/repo/workflow.py[48-83]

### Suggested fix
- Add a timeout parameter (configurable; e.g., 300s) to `run_git()` / `clone()`.
- Disable interactive prompts by setting env overrides (at least):
  - `GIT_TERMINAL_PROMPT=0`
  - optionally `GIT_ASKPASS=` and/or `SSH_ASKPASS=`
- Catch `subprocess.TimeoutExpired` and raise `GitError` with a clear message including the git args.
- Consider emitting a hint that the remote may require credentials when prompt is disabled.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +164 to +176
async def _terminate_process(self) -> None:
"""Terminate the subprocess, escalating to kill on timeout."""
if not self._process:
return
try:
self._process.terminate()
async with asyncio.timeout(_codex_const.PROCESS_TERMINATE_GRACE_SECONDS):
await self._process.wait()
except (asyncio.TimeoutError, ProcessLookupError):
try:
self._process.kill()
except ProcessLookupError:
pass
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Killed process not reaped 🐞 Bug ☼ Reliability

CodexAgentRunner._terminate_process() calls kill() on timeout but never awaits process.wait(),
which can leave a zombie subprocess and leak resources. Over repeated failures/timeouts this can
exhaust process table resources and destabilize the daemon.
Agent Prompt
### Issue description
On terminate timeout, the code sends SIGKILL but does not await `wait()`, so the child may not be reaped.

### Issue Context
This path is reachable whenever the codex app-server becomes unresponsive during shutdown.

### Fix Focus Areas
- codexd/agent/agent_runner.py[164-177]

### Suggested fix
- After `self._process.kill()`, always `await self._process.wait()` (optionally under a short timeout).
- Ensure `_process` is cleared/reset after shutdown to avoid reuse of a dead handle.
- Consider logging when escalation to kill occurs so operators can spot repeated unclean terminations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant