03 · Engineering Practice: How to Understand, Debug, and Modify LoopX
Baseline: LoopX
v2.1.1. This chapter turns the previous models into actionable working methods.
1. First, establish a ‘evidence-first’ debugging habit
Section titled “1. First, establish a ‘evidence-first’ debugging habit”Many issues in LoopX appear to be model behavior problems, but in reality, they are control plane state issues. When encountering anomalies, do not change the prompt first; instead, locate:
Command not registered? → entrypoint / cli.pyCan't find Goal/project? → registry / runtime root / state_fileshould-run selected wrong? → quota / todo projection / gate / claimTurn Not started? → route / admission / host adapterExecution result rejected? → result kind / validation / receipt bindingWriteback or recovery failed? → journal / settlement / authorityPage data is incorrect? → projection / history / cache1.1 Read JSON First, Don’t Guess the Code
Section titled “1.1 Read JSON First, Don’t Guess the Code”The recommended troubleshooting entry for the repository docs/development/project-code-tour.zh-CN.md is:
loopx status --format jsonloopx quota should-run --goal-id <goal-id> --agent-id <agent-id> --format jsonloopx history --format jsonloopx commands --format jsonIf there are differences in versions/parameters, first use loopx commands --format json to check the command interface, do not write parameters from memory.
When reading should-run, at least record:
effective_actionselected_todo.todo_idscheduler_hintinteraction_contractrequires_user_actionnext_cli_actions- reason / blocker / gate fields
Then only follow the modules actually read by this decision, do not blindly read from the repository root.
1.2 When encountering duplicate/stale effects, first look at identity
Section titled “1.2 When encountering duplicate/stale effects, first look at identity”Priority check:
goal_idagent_idtodo_idturn_instance_idturn_keyeffect_idcompleted_phasesfailed_phasereceipt identityThese fields determine whether “this is the same Turn or a new Turn.” If the identity does not match, even the smartest retry may produce duplicate side effects.
2. Local Environment
Section titled “2. Local Environment”pyproject.toml Requires Python 3.11, TypeScript control plane requires Node.js 22.22.3. The contribution guide uses uv:
uv sync --extra testnpm ciBefore running the Python architecture test for the first time, you need to npm ci, because they will parse the TypeScript control plane. The command line can be used:
uv run --extra test python -m pytest -q <test files>npm run -s typecheck:control-planenpm run -s test:control-planeStatic Check:
uv run --extra test python -m ruff check tests loopx/canary loopx/control_plane loopx/domain_packs loopx/presentationuv run --extra test python -m mypyDon’t run the full suite the first time. The LoopX repository is very large. The correct order is:
- Unit tests corresponding to the points of change;
- Adjacent contract / recovery tests;
- Architecture boundary tests;
- Typecheck;
- Finally, the full suite.
3. Experiment A: Follow a should-run decision once
Section titled “3. Experiment A: Follow a should-run decision once”Understand why the system chose an action, rather than just looking at the final JSON.
- Choose a test fixture or a local Goal that you own; do not perform the experiment on a real production Goal.
- Run
quota should-run --format json. - Divide the output into four parts:
state facts: goal / todo / gate / quotadecision: effective_action / route / selected_todoboundary: interaction_contract / allowed/blocked scopecontinuation: scheduler_hint / next_cli_actions / terminal- Use
rg -n "<field-name>" loopx/control_planeto reverse-check the assembly point. - Draw the field flow from status → quota → should-run packet.
Verification Questions
Section titled “Verification Questions”- If
should_run=false, is it in waiting, gate, throttle, pause, or health block? - If
selected_todois empty, why can’t it directly report “no work”? - Is
next_cli_actionsthe only valid action set?
Experiment A Reference Answers
Section titled “Experiment A Reference Answers”should_run=falsecannot be judged by Boolean alone; one must readeffective_action, route/reason, quota state, gate, attention, and health. It may be in: waiting for monitor/external conditions, operator gate, throttle/budget window, manual pause, health block, or require repair/replan.selected_todobeing empty does not mean “no work.” It could be that all work is blocked by gate/claim/scope, that only safe read-only actions are allowed currently, or that re-planning is needed among several Goals/priorities. Must check the blocked scope and attention reasons.next_cli_actionsis not the only valid set, just the steering. Validity is determined by typed authority, transition contract, preflight, and receipt binding; recommended actions must also be re-verified.
4. Experiment B: Following the Seven Phases of a Turn
Section titled “4. Experiment B: Following the Seven Phases of a Turn”Align completed_phases with the real effect.
- Construct a fake host/validator/writeback/spend in the test; do not use real external writes.
- Call
turn planor directly callbuild_loopx_turn_plan()to confirm the plan does not produce effects. - Call
run_loopx_turn_once(), simulating separately:- host success validation success;
- validation failure;
- writeback failure;
- spend failure;
- terminal closeout failure.
- Each time, read the journal using
turn inspect-journal --goal-id ... --agent-id ... --turn-key .... - Mark on paper which phases are committed and which effects have readback but are not yet checkpointed.
Experiment B Reference Observations
Section titled “Experiment B Reference Observations”The following five points are the reference conclusions for this question:
- When host returns, phases reach at most
typed_result; - Only after validation does material writeback qualification exist;
- Spend can occur only after writeback checkpoint;
terminal_closeout_failedoccurs after the first five phases are completed;- Recovery must not repeat already committed effects.
Recommended Test Files
Section titled “Recommended Test Files”Look for adjacent tests from these directions:
tests/test_loopx_turn_executor.pytests/control_plane_ts/*turn*.test.tstests/architecture/test_control_plane_import_boundaries.pyDon’t just assert ‘the function returns 200’; assert the journal’s phase, receipt, effect flags, and recovery behavior.
5. Experiment C: Looking at Domain Boundaries from the Perspective of Capability
Section titled “5. Experiment C: Looking at Domain Boundaries from the Perspective of Capability”Pick a real Capability, such as issuing a fix or PR review, and go through it:
CLI handler → capability contract → provider observe/effect → normalized evidence → typed transition proposal → Kernel validation / writebackAsk at every step:
- Which step only returns the proposal and doesn’t write the durable state?
- Which step must be readback?
- Which steps can be retried, and which steps must be idempotent?
- Which step will change Todo/Turn/quota?
- Did this capability secretly import presentation or kernel private internals?
If the business capability directly changes the Goal file, this is a boundary error; If the provider marks Todo as done, that is also a boundary error.
Experiment C Reference Answer
Section titled “Experiment C Reference Answer”A typical Capability chain should be divided into:
| Steps | Product | Can be written canonical state | Restore focus |
|---|---|---|---|
| CLI/command | Parameter and Object identity | No | Idempotent request, parameter validation |
| Capability contract | Success conditions, allowed transition, error taxonomy | No | Contract version and lineage |
| Provider observe/effect | External observation/effect receipt | No (only typed proposals can be submitted) | readback, idempotent key |
| normalized evidence | Facts with source, time, and scope | No | Freshness and verifiability |
| typed transition proposal | Desired changes | No | Bind Goal/Todo/Turn |
| Kernel validation/writeback | accepted state and durable receipt | Yes | CAS, lease, journal, readback |
Therefore: before proposal, you cannot directly change Goal/Todo; Any external effect must have a readback or idempotent identity; Retry can only redo the “unacknowledged” step. Capability: If you directly import the presentation or write kernel private state, it is a boundary error; If the provider marks Todo as done itself, it also swaps observation for transition.
6. Failure matrix: What to do when you see the result
Section titled “6. Failure matrix: What to do when you see the result”| Results/Symptoms | Check First | Handle Correctly | Wrong Practices |
|---|---|---|---|
contract_error |
TurnEnvelope schema/signature/lineage | Revise the contract or regenerate envelope | Forcibly change route |
blocked |
gate/claim/scope/capability | etc. or supplementing prerequisites | Treat blocked as host_failure |
wait |
monitor/resume condition | Scheduling the next observation | Hot polling, repeated flower quotas |
host_failure |
host executable/session/admission | Fix the host or try again according to the strategy | Directly change the status and say it succeeded |
validation_failed |
validator, evidence Freshness | Re-foraging/reconciliation results | Skipping validation and writing back |
writeback_failed |
authority/lock/schema | Fix writeback to preserve host results | Rerunning host causes repeated external side effects |
quota_spend_failed |
spend receipt | Read receipt, make up for any missed steps | Repeat spend |
terminal_closeout_failed |
closeout receipt | Only add closeout | Redo writeback/spend |
| Two rounds with no progress | Stall/self-repair conditions | Check projection/claim/gate/budget | Change a prompt to continue burning quota |
| Page expired | runtime projection/history | Re-derivate or modify projection | Treat the UI as the source |
7. Four boundaries when modifying LoopX
Section titled “7. Four boundaries when modifying LoopX”7.1 First, determine which layer is being changed
Section titled “7.1 First, determine which layer is being changed”| What do you want to change | Where should it be changed | Where should it be changed |
|---|---|---|
| Acceptance Rules for a Business | Capability | Kernel General-Purpose State Machine |
| External System Calls | Provider | Todo Lifecycle |
| New Host | goal-mode / adapter | Copy a set of quota/scheduler |
| Display Sorting | presentation/projection | canonical state |
| Turn Phase/Idempotency | Kernel contract tests | Only change the CLI copywriting |
| Permissions/Scope | typed authority/transition | Add a sentence like “Don’t” to the prompt |
7.2 Any new effect must answer five questions
Section titled “7.2 Any new effect must answer five questions”- What is Stable Identity?
- How to identify duplicate requests?
- How to readback when it has already occurred but not yet checkpointed?
- After failure, which checkpoint decides whether to retry?
- Does it change the semantics of quota/claim/gate/terminal?
If you can’t answer, don’t add the effect to the execution path.
7.3 Don’t Use Free Text to Carry Machine Facts
Section titled “7.3 Don’t Use Free Text to Carry Machine Facts”- Use enum for result classification;
- Use typed contracts for permissions;
- Recommend actions with the advisory field;
- Evidence uses stable references;
- closeout uses explicit receipt.
Natural language can explain “why,” but it cannot be the sole basis for “whether to permit” or “whether to complete.”
7.4 Modification of the contract must simultaneously modify the evidence
Section titled “7.4 Modification of the contract must simultaneously modify the evidence”When the following matters are involved, supplementary testing and compatibility explanations are required:
- schema version;
- transaction phase;
- result kind;
- receipt binding;
- quota state;
- Todo status;
- scheduler ack;
- public/private projection.
If you only change the implementation but not the contract, you will encounter the problem of “testing passed, but old journals cannot be restored.”
8. Design review checklist
Section titled “8. Design review checklist”Before submitting a LoopX change, ask each question one by one:
- Which canonical state is the real source of this change?
- Is it just a projection? If so, is it read-only?
- Has implicit permission been added or is suggestions whitelisted?
- Has an irreversible effect been added? Where are identity and idempotent?
- At what stage does the collapse point occur? What can journals prove?
- Will writeback/spend/closeout be repeated during recovery?
-
should_run=falseIs each cause still distinguishable? - Does it touch the public/private boundary?
- Is there a focused test that overrides the happy path and a recovery path?
- Is the CLI fallback maintained?
- Does the control plane depend on CLI/capability/presentation?
- Is an RFC or migration note needed?
9. Graduation project: Build a mini control plane
Section titled “9. Graduation project: Build a mini control plane”Don’t rewrite LoopX. Make a minimal implementation to verify if you truly understand it.
Minimum Features
Section titled “Minimum Features”- Registry with a Goal;
- The four states of Todo;
- claim/lease with a clear workspace scope;
- Quota state machine, at least covering eligible / waiting / paused;
- should-run output selected todo reason continuation;
- Turn plans and seven-stage affairs;
- One host, one capability, one provider;
- durable writeback, quota spend, scheduler ack;
- journal with collapse recovery;
- A read-only status projection;
- At least five recovery tests: writeback not acknowledged, spend unacknowledged, closeout failed, duplicate request, stale identity.
Must be explainable
Section titled “Must be explainable”- Why the model context is not long-term;
- Why observation is not the same as transition;
- Why write back before spend;
- Why can’t a submitted effect be redone?
- Why can’t projections have write permissions;
- Why claim is not a permanent leader;
- Why recommending actions doesn’t equal permission.
By this point, you are no longer “memorizing the LoopX API,” but have mastered a control plane design method that can migrate to any long-range Agent system.
Capstone Project “Must Be Explainable” Reference Answers
Section titled “Capstone Project “Must Be Explainable” Reference Answers”- The model context is not a long-term state: It is a projection/work memory that may expire, be truncated, or be injected; the canonical state is in the Registry/authority/journal and must be reconstructible.
- Observation is not a transition: Seeing a PR page merged is just input; it still requires normalization by the Provider, verification of Capability against acceptance, and Kernel acceptance and writeback.
- Writeback happens before spend: Durable delivery must exist before the budget can be deducted; otherwise, there will be an uncertain state of “money spent but no provable outcome.”
- Committed effects cannot be redone: External actions may be irreversible; redoing them would duplicate side effects/charges. Recovery must first read the receipt/readback and only supplement uncommitted stages.
- Projections cannot have write permissions: Otherwise, the UI/board would become a second source of truth, and sorting, caching, or manual dragging could secretly alter permissions and lifecycle.
- Claims are not permanent leaders: They are responsibilities with a time limit and scope; once expired/invalid, they must yield, otherwise crashes or network partitions could permanently hold up work.
- Recommended actions do not equal permissions:
next_cli_actionsonly helps choose a path; real authorization is in typed authority/transition contracts, and still must go through preflight, receipt binding, validation, and writeback.
10. Final diagram
Section titled “10. Final diagram” ┌──────────────┐ │ Goal State │ └──────┬───────┘ │ ┌───────────────▼────────────────┐ │ Registry + Authority + History │ └───────────────┬────────────────┘ │ projection ▼ Status / Attention │ ▼ Quota decision │ ▼ Turn plan (no effects) │ ▼ Host → Capability → Provider │ ▼ validation → writeback → spend │ ▼ scheduler apply / ack │ Next roundIf you can draw from Goal to the next round on the whiteboard, and write “Fact Source, Authority, Failure Recovery” next to each arrow, then this class can end.
Based on LoopX v2.1.1 (87e5b4f8) source code · 2026-10-31