Skip to content

Stage 7: CLI, Dashboard, and Extensions

Course: LoopX Source Code Class · Stage Test Prerequisite: Stage 6, Understanding Facts and Projections Corresponding Overview: core-mechanisms.md the interface and extension parts Goal of this stage: To see how the same control plane serves humans, scripts, Hosts, and external channels without duplicating the business core.

LoopX has CLI, Dashboard, Lark/IM, Goal Mode, and different Agent Hosts. They look like multiple products, but in fact, they should all follow the same boundary:

  • Facts are provided by registry/state/journal;
  • Read models are generated by status/presentation;
  • Actions are handled by typed command/authority;
  • Host adapters only deal with connecting to the specific model runtime;
  • Channels only handle ingress/egress, without rewriting target facts.

If each interface keeps its own copy of the ‘current task’, the system will immediately lose a single source of truth.

Interfaces are consumers, not the control plane itself; Host adapters are translation layers, not rule layers.

CLI outputs can help humans and Agents decide, but changes in output format cannot change the semantics of should-run, validation, or settlement.

  1. cli.py Assemble command families: status, turn, quota, todo, goal, presentation, dash, extended capabilities, etc., and unify JSON/markdown outputs.
  2. status_server.py Provide read-only/control API projections; Dashboard fetches data from collect_status() and the presentation layer.
  3. presentation/ Responsible for markdown/HTML/API views; renderers/status_markdown.py, turn_envelope_markdown.py, etc. only render existing facts.
  4. pi_goal_mode/, zcode_goal_mode/, dsh_goal_mode/, opencode_goal_mode/ Translate LoopX contracts into invocation methods for different Hosts.
  5. turn_driver/host_process.ts, host_bridge_transport.py, host_interaction.ts Handle processes, stdio, interaction, and timeout boundaries.
  6. extensions/lark/ and other channels handle events, identity, receipts, and user notifications, but still return to the same state and Turn entry.
Entry Input Output Should Not Own
CLI argv, workspace/runtime config Human- or machine-readable projection Independent state database
status server Query/control request status, attention, action projection Directly fabricate completion
Dashboard Read model Visualization Another set of Todo facts
Goal Mode adapter Host request Host result/event Its own validation rules
extension/channel External events normalized ingress Bypass gate/quota
Host process Contract and context typed candidate Directly write canonical state

Different Hosts have different models, tool protocols, and session mechanisms, so adapters are needed to translate requests and results. But Turn identity, envelope, validation, writeback, and spend are still owned by the LoopX core. Adapters cannot skip stages just because a certain Host is more convenient.

Markdown is suitable for humans to locate information, while scripts and Agents need stable fields. next_cli_actions, quota reason, envelope, receipt can all be consumed in a structured way; recommended actions are only steering, execution still goes through authority.

CLI / Dashboard / IM event
→ normalized command or ingress
→ registry + status projection
→ should-run / typed action authority
→ Turn plan
→ Goal Mode Host adapter
→ host process / bridge
→ typed result Return to kernel settlement
→ status refresh

Pay attention to the last paragraph: the results must return to the kernel, rather than the adapter updating the Dashboard data source itself.

From the Dashboard, observe should_run, then follow collect_status() → should-run payload to find the source field. Acceptance criteria: be able to indicate that the field comes from quota/route, not calculated by the presentation itself.

Read the host adapters in pi_goal_mode and dsh_goal_mode. Acceptance criteria: though the host protocols differ, both receive the same turn identity/envelope and return results to the same validation and settlement.

Experiment C: Injecting an event from a channel

Section titled “Experiment C: Injecting an event from a channel”

Use an extended test to construct an external event. Acceptance criteria: the event must first become an auditable ingress, then pass through gate/authority; it cannot directly be marked as Todo complete or skip quota.

  1. The source of should_run should be canonical decisions and states like quota/route; the presentation only displays and does not calculate facts itself.
  2. The host protocols of pi_goal_mode and dsh_goal_mode can differ, but they must share the turn identity/envelope and return to the same validate/writeback/spend semantics.
  3. An external event must first become an auditable ingress, then go through gate/authority; it cannot directly write Todo completion, skip quota, or forge next actions.
Failure Common Root Cause Recovery
Dashboard inconsistent with CLI Projection cache/version differences Recalculate using canonical state
Host adapter drops fields Translation layer loses contract Fix adapter, restore contract tests
Channel duplicate delivery Lack of idempotent ingress Deduplicate using event id/receipt
Recommended actions not executable Projection expired or authority changed Re-run should-run/authority
Host process timeout Tool/model long blocking Retain journal, resume according to recovery policy
UI directly marks complete Bypass writeback Remove write entry, return to typed command
  1. What do CLI, Dashboard, and Goal Mode each consume and own?
  2. Why can’t the Goal Mode adapter determine completion itself?
  3. Why can’t recommended actions serve as a permissions whitelist?
  4. How should duplicate messages from external channels be handled?
  5. Why can’t the adapter rerun privately after a host process crash?
  6. How to verify an interface is not secretly maintaining a second set of states?
  1. CLI consumes commands and fact projections, producing human/machine-readable results; Dashboard consumes status/presentation read models; Goal Mode consumes turn contracts and translates Host protocols. None of them can own canonical Goal/Todo/quota facts or settlement rights.
  2. Completion requires evidence verification, lifecycle writeback, spend, and closeout. The adapter only sees Host candidate results and cannot prove these stages have been committed; self-determination would bypass the kernel and create false completions.
  3. Recommended actions are only steering and may expire due to version, filtering, or permission restrictions. Valid actions must still pass typed authority, preflight, receipt binding, and settlement; prohibited actions should return explicit errors.
  4. Deduplicate using stable event id/ingress receipt and distinguish “accepted” and “processed”. Duplicate deliveries can only replay existing states, without re-executing side effects.
  5. The adapter does not know whether Host effects have occurred or which stage the journal has been committed to. Private reruns may duplicate tool side effects; it must return to the kernel, read the journal/receipt, and recover according to prefix.
  6. After modifying interface display, refresh the canonical state to see if it returns to facts; then trace all write operations to ensure they go through typed command, authority, journal, and receipt. If the interface has its own persistence bucket, that is a second set of states.
  • loopx/cli.py
  • loopx/status.py
  • loopx/status_server.py
  • loopx/presentation/
  • loopx/presentation/renderers/status_markdown.py
  • loopx/pi_goal_mode/
  • loopx/zcode_goal_mode/
  • loopx/dsh_goal_mode/turn_host_adapter.py
  • loopx/control_plane/turn_driver/host_process.ts
  • loopx/extensions/lark/

Enter Stage 8: What engineering measures ensure these boundaries? How do tests, journal, atomic writes, and recovery audits prevent system distortion during crashes and concurrency?