# How to Debug Issues in LoopX: A Step-by-Step Troubleshooting Guide

> Debug LoopX effectively with this step-by-step guide. Learn to use dry-run flags, inspect runtime projection routes, and monitor health with the HTTP status server for seamless troubleshooting.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: how-to-guide
- Published: 2026-08-14

---

**To debug LoopX effectively, use `--dry-run` flags to preview changes without modifying files, inspect the runtime projection route for registry sync issues, and leverage the HTTP status server for real-time health monitoring.**

LoopX is a modular AI-agent orchestration framework built around a **runtime directory**, **global registry**, and CLI commands that manage goal state. When debugging loopx issues, understanding this layered architecture allows you to trace problems from CLI invocation through state resolution to projection output.

## Understanding LoopX Architecture for Debugging

LoopX organizes functionality into distinct components. Knowing which file handles which responsibility accelerates troubleshooting loopx problems significantly.

- **Runtime Manager** ([`loopx/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/runtime.py)): Resolves the active runtime root, validates goal IDs, and archives completed goals via `archive_runtime_goal`.

- **State Refresh** ([`loopx/state_refresh.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/state_refresh.py)): Reads goal markdown state files, updates the *Next Action* section, and builds refresh records through `refresh_state_run`.

- **State Projection** ([`loopx/state_projection.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/state_projection.py)): Detects gaps between public-safe and active state representations using `state_projection_gap_warning`.

- **Registry** ([`loopx/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/registry.py)): Stores goal metadata and resolves state-file locations via `registry_goals` and `load_registry`.

- **Status Server** ([`loopx/status_server.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/status_server.py)): Exposes HTTP endpoints reporting runtime and registry health through its `main` entry point.

- **CLI Front-Ends** ([`loopx/cli.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli.py)): Thin wrappers invoking all above services for commands like `loopx refresh-state` and `loopx status`.

## Tracing Debug Loopx Issues Through the Stack

When something fails, follow this diagnostic path:

### 1. Verify CLI Arguments and Early Validation

The CLI performs input validation before any business logic runs. Functions like `validate_goal_id_path_segment` and `validate_public_safe_text` catch malformed input early.

```bash

# Check if your goal ID passes validation

loopx refresh-state --goal-id "my-goal-123" --dry-run

```

Errors here indicate user input problems, not runtime failures.

### 2. Confirm Runtime Path Resolution

LoopX derives the runtime root from the registry via `resolve_runtime_root`. Missing goal directories typically stem from incorrect registry entries.

```bash

# See resolved paths in verbose output

loopx status --verbose

```

The runtime manager raises `FileNotFoundError` only after failing to locate `runtime/goals/<goal-id>`.

### 3. Inspect State File Parsing

The refresh pipeline uses `parse_frontmatter`, `extract_section_lines`, and `replace_next_action_section` to manipulate markdown. Common failures include:

- Malformed YAML frontmatter
- Missing `## Next Action` headings

- Improperly formatted todo bullet points

### 4. Analyze Projection Gaps and Warnings

The `state_projection_gap_warning` function returns structured data about state inconsistencies. Look for these fields in the output:

- `requires_todo_expansion`: Missing or unparsable todos in the Agent Todo section
- `user_open`: Unresolved user-facing tasks
- `agent_open`: Pending agent responsibilities

### 5. Query the Status Server for Runtime Health

The HTTP `/status` endpoint mirrors `loopx status` output but as JSON:

```bash

# Start the server in background

loopx status-server &

# Get JSON snapshot of runtime, registry, and projection route

curl http://localhost:8000/status | jq .

```

## Practical Debugging Scenarios

### Unexpected Classification Results

Run with `--dry-run` to see the classification logic without file mutation:

```bash
loopx refresh-state \
    --registry /path/to/registry.json \
    --goal-id my-goal \
    --dry-run \
    --classification "state_refreshed"

```

Inspect `/tmp/loopx/run-*/refresh-state.md` for the determined classification value.

### Goal Directory Not Found

1. Verify registry entry exists: check `registry_goals` output
2. Confirm runtime root resolution via `resolve_runtime_root`
3. Use `loopx status --verbose` to print fully resolved paths

### Next Action Section Not Updating

The `replace_next_action_section` function returns `(new_text, updated_flag)`. Check this tuple:

- If `updated_flag` is `False`, the section already matches the desired action
- When `dry_run=True`, the function returns updated text without writing it

### Persistent Projection Gaps

Examine the warning object from `state_projection_gap_warning`. Resolve missing todos or fix malformed bullet lines—the projection logic collapses gaps only after parsing todos cleanly.

### Global Registry Sync Failures

Check the `runtime_projection_route` object via `compact_runtime_projection_route`. If `route.status` is `"missing"` or `"single_runtime"`, global sync is intentionally disabled and not an error condition.

### Performance Bottlenecks

```bash

# Enable status server for continuous monitoring

loopx status-server &

# Check timing statistics

loopx status --metrics

```

The `runtime_projection_route.projection_enabled` flag indicates whether shared runtime projection is active.

## Essential Debug Loopx Code Examples

```bash

# Dry-run a state refresh – preview all decisions safely

loopx refresh-state \
    --registry /path/to/registry.json \
    --goal-id my-goal \
    --dry-run \
    --classification "state_refreshed"

# Inspect generated markdown output

cat /tmp/loopx/run-20231101T120000Z/refresh-state.md | less

# Run status server and query health endpoint

loopx status-server &
curl http://localhost:8000/status | jq .

# Archive workflow: dry-run first, then execute

loopx archive-goal \
    --registry /path/to/registry.json \
    --goal-id my-goal \
    --dry-run

loopx archive-goal \
    --registry /path/to/registry.json \
    --goal-id my-goal \
    --execute

```

## Key Source Files for Debugging

| File | Primary Function | Link |
|------|---------------|------|
| [`loopx/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/runtime.py) | Goal ID validation, runtime root resolution, archiving | [runtime.py](https://github.com/huangruiteng/loopx/blob/main/loopx/runtime.py) |
| [`loopx/state_refresh.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/state_refresh.py) | Markdown parsing, refresh records, output generation | [state_refresh.py](https://github.com/huangruiteng/loopx/blob/main/loopx/state_refresh.py) |
| [`loopx/state_projection.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/state_projection.py) | Gap detection and action recommendations | [state_projection.py](https://github.com/huangruiteng/loopx/blob/main/loopx/state_projection.py) |
| [`loopx/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/registry.py) | Global registry loading and goal metadata | [registry.py](https://github.com/huangruiteng/loopx/blob/main/loopx/registry.py) |
| [`loopx/status_server.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/status_server.py) | HTTP health endpoint implementation | [status_server.py](https://github.com/huangruiteng/loopx/blob/main/loopx/status_server.py) |
| [`loopx/cli.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli.py) | Command-line argument parsing and routing | [cli.py](https://github.com/huangruiteng/loopx/blob/main/loopx/cli.py) |
| [`loopx/paths.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/paths.py) | Directory location helpers | [paths.py](https://github.com/huangruiteng/loopx/blob/main/loopx/paths.py) |
| [`loopx/feedback.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/feedback.py) | Public-safe vs. local-control text validation | [feedback.py](https://github.com/huangruiteng/loopx/blob/main/loopx/feedback.py) |

Start debugging at the CLI wrapper in [`cli.py`](https://github.com/huangruiteng/loopx/blob/main/cli.py), follow calls into `state_refresh.run`, then trace into lower-level helpers. The combination of **dry-run flags**, **status server JSON**, and **explicit exception messages** provides complete visibility into LoopX behavior.

## Summary

- Use `--dry-run` flags to preview changes and inspect classification logic without modifying files
- Trace issues through five layers: CLI validation → runtime resolution → state parsing → projection gaps → status server health
- Query `curl http://localhost:8000/status` for JSON snapshots of runtime and registry state
- Check `replace_next_action_section` return values and `state_projection_gap_warning` objects for specific failure modes
- Monitor `runtime_projection_route.projection_enabled` to diagnose sync and performance issues

## Frequently Asked Questions

### What is the fastest way to debug a failing refresh-state command?

Run with `--dry-run` and inspect the generated markdown in `/tmp/loopx/run-*/`. This shows the classification, parsed frontmatter, and next action determination without any file mutations. According to the loopx source code, the dry-run bypasses all write operations in `refresh_state_run`.

### Why does my goal directory exist but LoopX cannot find it?

The runtime manager uses `resolve_runtime_root` from the registry, not the filesystem directly. Run `loopx status --verbose` to see resolved paths. If the registry entry in `registry_goals` points to a different location or the goal ID fails `validate_goal_id_path_segment`, LoopX will raise `FileNotFoundError` before checking the actual directory.

### How do I know if global registry sync is working?

Query the status server or run `loopx status` and examine `runtime_projection_route`. If `route.status` equals `"missing"` or `"single_runtime"`, the global sync is intentionally disabled per `compact_runtime_projection_route` logic. Only when `projection_enabled` is `true` does the shared runtime projection write to the global registry.