- Created a main workspace index to track AI Agent work records across developers. - Added a personal index for developer 'yuxuanhui' with current status and session history. - Initialized the first journal file for 'yuxuanhui' to document AI development sessions. - Introduced AGENTS.md for Trellis instructions, detailing project structure and usage guidelines.
8.3 KiB
Progress And Debugging
Pretty output is for operators. Raw output is the audit log. Subcommands
(forum, thread, messages, context) are the audit interface — reach
for them before grepping events.jsonl by hand.
Pretty vs --raw
trellis channel messages <channel> renders a compact, human-readable view:
timestamps, identities, kind, and a short body. It is meant for operators
scanning a channel, not for diagnostics.
Pretty output can and will truncate:
- long progress deltas (
text_delta, partial tool args) - tool names and command lines
- multi-line status fields and structured
detailblobs - forum thread titles past the column budget
When something looks "off" — a worker appears stuck, a progress line ends
mid-word, an action field shows ... — switch to --raw. Raw mode emits
one JSON event per line exactly as it lives in events.jsonl, so nothing
is dropped.
# Pretty (operator view)
trellis channel messages <channel> --kind done --last 10
trellis channel messages <channel> --kind error --last 10
# Raw (diagnostic view) — one JSON per line
trellis channel messages <channel> --raw --kind progress --last 20
trellis channel messages <channel> --raw --last 50
Rule of thumb: never diagnose a worker from a truncated progress line.
Rebuild Streaming Text
To reconstruct what a model actually streamed during a turn, concatenate
detail.text_delta from progress events:
trellis channel messages <channel> --raw --kind progress --last 80 \
| python3 -c 'import json,sys; [print((json.loads(l).get("detail") or {}).get("text_delta",""), end="") for l in sys.stdin if l.strip()]'
Stalled Worker Diagnosis
Symptom: trellis channel list shows the worker as running, but no new
events appear in messages and wait keeps timing out.
Triage order:
-
Locate the channel files. Use
list --all --all-projectsif you are not sure which bucket the channel lives in.trellis channel list --all --all-projects CHAN=~/.trellis/channels/<bucket>/<channel> -
Confirm the supervisor and worker PIDs are alive.
cat "$CHAN/<worker>.pid" # supervisor PID cat "$CHAN/<worker>.worker-pid" # actual CLI subprocess PID ps -p "$(cat "$CHAN/<worker>.pid")" ps -p "$(cat "$CHAN/<worker>.worker-pid")"If the supervisor PID is gone but the channel still lists the worker, you have a ghost entry — clean it with
trellis channel kill <name> --as <worker> --force. -
Tail the worker log. This is the canonical place to see provider / MCP / tool startup output that never makes it onto the channel.
tail -f "$CHAN/<worker>.log" -
Check the last raw events. A worker that emitted
progressbut nomessage/doneis usually mid-stream or blocked on a tool call:trellis channel messages <channel> --raw --last 50
Common "alive but silent" causes:
- Provider cold start before the first token (long, but eventually moves).
- A blocking MCP server during startup — visible in the worker log.
- Worker is waiting for a tool result whose subprocess hung.
- Prompt is huge / model is rate-limited; check provider-side errors in the worker log.
Progress Event Interpretation
A progress event represents an in-flight piece of work. Its shape varies
by action field, but the load-bearing fields are always under detail:
detail.text_delta— incremental model output (concatenate across events to rebuild the streamed reply).detail.tool_name,detail.tool_input— tool call about to run or currently running.detail.status— short string used by long-running actions (starting,running,flushing,done).detail.action— semantic label (e.g.statusfor thread heartbeats).
Progress events are noisy by design. wait ignores them unless you
pass --include-progress. When you do want to see them, prefer:
trellis channel messages <channel> --raw --kind progress --last 80
A stream that emits progress at a steady cadence but never closes with
done/error/message is the classic shape of a hung tool call —
inspect the worker log for the subprocess.
Wait Semantics (Quick Reference)
channel wait watches events.jsonl from EOF and wakes on:
messagedoneerrorkilledprogressonly with--include-progress
Useful filters:
trellis channel wait T --as main --from check --kind done --timeout 15m
trellis channel wait T --as main --from check,check-cx --kind done --all --timeout 15m
trellis channel wait T --as worker --tag interrupt --timeout 1h
trellis channel wait T --as main --thread release-note --action status --timeout 10m
Exit codes: 0 matched, 124 timeout, 1/2 errors. On wait --all
timeout, stderr names the workers still missing.
Auditing events.jsonl — Use Subcommands, Not grep
Every channel persists its full history at $CHAN/events.jsonl. It is
tempting to tail / grep / jq this file directly during debugging.
Don't make it a habit, and never do it for forum channels.
Why subcommands first:
messagesalready replays the file with filters (--kind,--from,--last,--tag,--thread,--action) and gives you--rawfor the exact JSON. Anything you would write a one-liner for,messagesalready does.waitconsumes the same file with EOF semantics — re-implementing that withtail -f | jqwill drop events under load and misorder them under rotation.contextmaterializes a worker's inbox view, including cursor state. Hand-rolled filters do not respect<worker>.inbox-cursor.
Forum channels: never parse events.jsonl directly
Forum channels multiplex many logical threads onto a single events.jsonl.
Each event carries thread, action, and tag fields that the forum
subcommands know how to fold together. Parsing the file by hand will:
- Mix threads together and make a thread look incoherent.
- Miss thread lifecycle events (open / status / close) that change how later events should be interpreted.
- Ignore worker inbox cursors, so you will "see" events a worker has already consumed and assume they are pending.
Use the forum-aware views instead:
# List logical threads inside the forum channel
trellis channel forum list <channel>
# Inspect one thread end-to-end
trellis channel thread show <channel> <thread>
# Replay messages for a thread (supports --raw, --kind, --last)
trellis channel messages <channel> --thread <thread> --raw --last 100
# What a specific worker still has pending
trellis channel context <channel> --as <worker>
Direct reads of events.jsonl are reserved for the case where the CLI
itself is suspect — e.g. confirming an event was actually persisted, or
diffing against <worker>.inbox-cursor while debugging the supervisor.
Common Failures
| Symptom | Cause | Fix |
|---|---|---|
trellis: command not found |
CLI not installed globally | npm install -g @mindfoldhq/trellis |
wait exits immediately |
wrong filter or identity collision | use distinct --as, inspect raw messages |
| zsh errors on message text | shell interpreted punctuation | use --stdin or --text-file |
| progress line is cut off | pretty output truncation | use messages --raw --kind progress |
| worker never speaks | provider startup / prompt / MCP delay | inspect <worker>.log, ps, raw events |
| channel not found in another cwd | project bucket mismatch | cd to project, use --scope global, or list --all-projects |
| ghost worker in list | supervisor died without cleanup | trellis channel kill <name> --as <worker> --force |
| forum thread looks scrambled | parsed events.jsonl directly |
use forum, thread, messages --thread |
Storage Layout
~/.trellis/channels/
└── <bucket>/
└── <channel-name>/
├── events.jsonl
├── <channel>.lock
├── <worker>.log
├── <worker>.pid
├── <worker>.worker-pid
├── <worker>.config
├── <worker>.session-id
├── <worker>.thread-id
├── <worker>.inbox-cursor
└── <worker>.spawnlock
Agents normally use the CLI, not direct file reads. Direct file reads are
for debugging when CLI views are insufficient — and even then, never on a
forum channel's events.jsonl.