@mindfoldhq/trellis 0.6.0-rc.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,233 @@
1
+ # Forum Channels
2
+
3
+ Forum channels are durable, topic-style channels. They are created with
4
+ `--type forum` at channel-creation time and are immutable after that. They are
5
+ not normal chat streams: the default read path is
6
+ **forum summary -> one thread timeline -> current context**.
7
+
8
+ ## Forum vs Regular Channel
9
+
10
+ A channel's type is set with `--type` on `channel create` and never changes:
11
+
12
+ - `chat` (default) — flat message timeline. `channel messages` always renders
13
+ the event stream. Forum-only flags such as `--thread` and `--action` are
14
+ rejected here.
15
+ - `forum` — thread-oriented. `channel messages` without filters renders a
16
+ thread-board summary instead of raw events. The `post`, `forum`, `thread`,
17
+ and `thread rename` subcommands only apply to forum channels.
18
+
19
+ Both types share the same scope model (`--scope project` is the default;
20
+ `--scope global` puts the channel in the cross-project bucket).
21
+
22
+ ## Create A Forum Channel
23
+
24
+ ```bash
25
+ trellis channel create design-feedback \
26
+ --type forum \
27
+ --scope global \
28
+ --description "Cross-project design feedback board." \
29
+ --context-raw "One thread per design topic; close when resolved." \
30
+ --by main
31
+ ```
32
+
33
+ Use `--scope project` for a board scoped to one repo, `--scope global` for a
34
+ cross-project board.
35
+
36
+ ## Threads: Open, Comment, Status, Summary
37
+
38
+ Threads live inside a forum channel. Each thread is identified by a stable
39
+ `--thread <key>` (lowercase kebab-case is conventional). The first action on
40
+ a thread is `opened`; everything afterwards uses the same `--thread` key.
41
+
42
+ ```bash
43
+ trellis channel post design-feedback opened \
44
+ --scope global \
45
+ --as main \
46
+ --thread login-empty-state \
47
+ --title "Empty state on the login screen" \
48
+ --description "Track design feedback for the new login empty state." \
49
+ --labels design,login \
50
+ --context-raw "Spotted during the 0.4 release review." \
51
+ --text-file /tmp/thread-open.md
52
+
53
+ trellis channel post design-feedback comment \
54
+ --scope global \
55
+ --as reviewer \
56
+ --thread login-empty-state \
57
+ --text-file /tmp/review.md
58
+
59
+ trellis channel post design-feedback status \
60
+ --scope global \
61
+ --as main \
62
+ --thread login-empty-state \
63
+ --status closed
64
+
65
+ trellis channel post design-feedback summary \
66
+ --scope global \
67
+ --as main \
68
+ --thread login-empty-state \
69
+ --summary "Adopted the option-B layout; ticket TRELLIS-123 owns the fix."
70
+ ```
71
+
72
+ Key distinctions:
73
+
74
+ - `--description` is the **durable** thread description (the answer to "what
75
+ is this thread about?"). It is set on `opened` and edited by re-running
76
+ `post` with `--description`.
77
+ - `--text` / `--stdin` / `--text-file` is the **event body** — the comment or
78
+ payload attached to this specific timeline entry.
79
+ - `--labels` and `--assignees` are CSV and **replace** the current value; they
80
+ do not append.
81
+ - `--summary` is the rolling thread summary. Setting it on `status closed` is
82
+ the standard way to mark a thread resolved with context.
83
+
84
+ `--thread` is required for every action except `opened` (where it is also
85
+ required in practice — there is no anonymous thread).
86
+
87
+ ## Read A Forum
88
+
89
+ ```bash
90
+ trellis channel messages design-feedback --scope global
91
+ trellis channel forum design-feedback --scope global --status open
92
+ trellis channel thread design-feedback login-empty-state --scope global
93
+ trellis channel messages design-feedback --scope global --raw --thread login-empty-state
94
+ ```
95
+
96
+ If a peer says "I commented on the forum", run `channel forum` first to see
97
+ which thread changed, then drill into that thread with `channel thread <name>
98
+ <thread>`. Do not jump straight to ad-hoc `events.jsonl` parsing.
99
+
100
+ ## Context
101
+
102
+ Context entries are durable background that should always be in scope when
103
+ reading a channel or a thread. They are **not** timeline events; they are
104
+ projected separately and replayed for every reader.
105
+
106
+ Use the `context` subcommands. The legacy `--linked-context-file` /
107
+ `--linked-context-raw` flags on `create` and `post` are deprecated aliases
108
+ that fold into the canonical `--context-file` / `--context-raw`.
109
+
110
+ ### Add Context
111
+
112
+ ```bash
113
+ # Channel-level context (whole forum)
114
+ trellis channel context add design-feedback \
115
+ --scope global \
116
+ --raw "Upstream feedback board; please link tasks before opening threads."
117
+
118
+ # Thread-level context (one thread)
119
+ trellis channel context add design-feedback \
120
+ --scope global \
121
+ --thread login-empty-state \
122
+ --file "$PWD/.trellis/tasks/05-13-login-redesign/design.md"
123
+ ```
124
+
125
+ - `--thread <key>` switches between channel-level and thread-level context.
126
+ - `--file` paths **must be absolute**; relative paths are rejected.
127
+ - `--raw` is plain text inline content.
128
+ - Both flags are repeatable; at least one is required for `add` / `delete`.
129
+ - `--as <agent>` records authorship; defaults to `main`.
130
+
131
+ ### List Context
132
+
133
+ ```bash
134
+ trellis channel context list design-feedback --scope global
135
+ trellis channel context list design-feedback --scope global --thread login-empty-state --raw
136
+ ```
137
+
138
+ `--raw` on `list` emits one JSON entry per line (useful for piping); without
139
+ it you get a human-readable `file <path>` / `raw <truncated text>` listing.
140
+ An empty store prints `(no context)`.
141
+
142
+ ### Delete Context
143
+
144
+ ```bash
145
+ trellis channel context delete design-feedback \
146
+ --scope global \
147
+ --thread login-empty-state \
148
+ --raw "stale note"
149
+ ```
150
+
151
+ You delete by **value**, not by id: pass the same `--file` or `--raw` value
152
+ that was added. Repeat the flag to delete multiple entries in one call.
153
+
154
+ ### Reading Order
155
+
156
+ When reading a thread, work top-down:
157
+
158
+ 1. Thread `description` (the durable "what is this about").
159
+ 2. Context entries (channel-level + thread-level).
160
+ 3. Timeline (`opened`, `comment`, `status`, `summary`).
161
+
162
+ If a context file is missing or unreadable, state that explicitly and
163
+ continue with the remaining data — do not fabricate the content.
164
+
165
+ ## Title Projection
166
+
167
+ `title` projects a stable display title onto the channel without renaming the
168
+ storage address. The channel `name` you pass to every command stays the same.
169
+
170
+ ```bash
171
+ trellis channel title set design-feedback \
172
+ --scope global \
173
+ --title "Design feedback board"
174
+
175
+ trellis channel title clear design-feedback --scope global
176
+ ```
177
+
178
+ - `title set` requires `--title`.
179
+ - `--as <agent>` records authorship; defaults to `main`.
180
+ - This is a presentation-layer change. Tooling and scripts keep using the
181
+ original channel name.
182
+
183
+ ## Thread Rename
184
+
185
+ `thread rename` is the correction path when a thread was opened with the
186
+ wrong key (typo, wrong slug convention, etc.). Threads do not support hard
187
+ deletion — rename is the supported corrective action.
188
+
189
+ ```bash
190
+ trellis channel thread rename design-feedback old-key new-key \
191
+ --scope global \
192
+ --as main
193
+ ```
194
+
195
+ - `--as <agent>` is **required**.
196
+ - `post <name> rename` is rejected — you must use `thread rename`.
197
+
198
+ ## Deletion Discipline
199
+
200
+ Do not model single-comment deletion or hard thread deletion as normal
201
+ workflow. Forum threads are append-only collaboration history. To correct
202
+ state, use:
203
+
204
+ - `post ... status` to mark a thread closed / blocked / etc.
205
+ - `post ... summary` to record the resolution.
206
+ - `post ... --labels` to re-label (replaces the set).
207
+ - `thread rename` to correct a bad thread key.
208
+
209
+ ## Internal Changelog Pattern
210
+
211
+ A common use of a global forum channel is an internal release / runtime
212
+ changelog. One thread per notable change keeps history searchable:
213
+
214
+ ```bash
215
+ trellis channel create release-notes \
216
+ --type forum \
217
+ --scope global \
218
+ --description "Internal release and runtime changelog." \
219
+ --context-raw "One thread per notable change; close when shipped." \
220
+ --by main
221
+
222
+ trellis channel post release-notes opened \
223
+ --scope global \
224
+ --as main \
225
+ --thread release-2026-q1 \
226
+ --title "Channel threads and forum UX in 0.6" \
227
+ --description "Forum channel UX shipped in the 0.6 line." \
228
+ --labels channel,release \
229
+ --text-file /tmp/release-notes.md
230
+ ```
231
+
232
+ Use stable, descriptive thread keys (e.g. `release-2026-q1`,
233
+ `runtime-event-schema-change`) so later readers can find them by name.
@@ -0,0 +1,226 @@
1
+ # Progress And Debugging
2
+
3
+ Pretty output is for operators. Raw output is the audit log. Subcommands
4
+ (`forum`, `thread`, `messages`, `context`) are the audit *interface* — reach
5
+ for them before grepping `events.jsonl` by hand.
6
+
7
+ ## Pretty vs `--raw`
8
+
9
+ `trellis channel messages <channel>` renders a compact, human-readable view:
10
+ timestamps, identities, kind, and a short body. It is meant for operators
11
+ scanning a channel, not for diagnostics.
12
+
13
+ Pretty output can and will truncate:
14
+
15
+ - long progress deltas (`text_delta`, partial tool args)
16
+ - tool names and command lines
17
+ - multi-line status fields and structured `detail` blobs
18
+ - forum thread titles past the column budget
19
+
20
+ When something looks "off" — a worker appears stuck, a progress line ends
21
+ mid-word, an action field shows `...` — switch to `--raw`. Raw mode emits
22
+ one JSON event per line exactly as it lives in `events.jsonl`, so nothing
23
+ is dropped.
24
+
25
+ ```bash
26
+ # Pretty (operator view)
27
+ trellis channel messages <channel> --kind done --last 10
28
+ trellis channel messages <channel> --kind error --last 10
29
+
30
+ # Raw (diagnostic view) — one JSON per line
31
+ trellis channel messages <channel> --raw --kind progress --last 20
32
+ trellis channel messages <channel> --raw --last 50
33
+ ```
34
+
35
+ Rule of thumb: never diagnose a worker from a truncated progress line.
36
+
37
+ ### Rebuild Streaming Text
38
+
39
+ To reconstruct what a model actually streamed during a turn, concatenate
40
+ `detail.text_delta` from progress events:
41
+
42
+ ```bash
43
+ trellis channel messages <channel> --raw --kind progress --last 80 \
44
+ | python3 -c 'import json,sys; [print((json.loads(l).get("detail") or {}).get("text_delta",""), end="") for l in sys.stdin if l.strip()]'
45
+ ```
46
+
47
+ ## Stalled Worker Diagnosis
48
+
49
+ Symptom: `trellis channel list` shows the worker as running, but no new
50
+ events appear in `messages` and `wait` keeps timing out.
51
+
52
+ Triage order:
53
+
54
+ 1. **Locate the channel files.** Use `list --all --all-projects` if you are
55
+ not sure which bucket the channel lives in.
56
+
57
+ ```bash
58
+ trellis channel list --all --all-projects
59
+ CHAN=~/.trellis/channels/<bucket>/<channel>
60
+ ```
61
+
62
+ 2. **Confirm the supervisor and worker PIDs are alive.**
63
+
64
+ ```bash
65
+ cat "$CHAN/<worker>.pid" # supervisor PID
66
+ cat "$CHAN/<worker>.worker-pid" # actual CLI subprocess PID
67
+ ps -p "$(cat "$CHAN/<worker>.pid")"
68
+ ps -p "$(cat "$CHAN/<worker>.worker-pid")"
69
+ ```
70
+
71
+ If the supervisor PID is gone but the channel still lists the worker,
72
+ you have a ghost entry — clean it with
73
+ `trellis channel kill <name> --as <worker> --force`.
74
+
75
+ 3. **Tail the worker log.** This is the canonical place to see provider /
76
+ MCP / tool startup output that never makes it onto the channel.
77
+
78
+ ```bash
79
+ tail -f "$CHAN/<worker>.log"
80
+ ```
81
+
82
+ 4. **Check the last raw events.** A worker that emitted `progress` but no
83
+ `message`/`done` is usually mid-stream or blocked on a tool call:
84
+
85
+ ```bash
86
+ trellis channel messages <channel> --raw --last 50
87
+ ```
88
+
89
+ Common "alive but silent" causes:
90
+
91
+ - Provider cold start before the first token (long, but eventually moves).
92
+ - A blocking MCP server during startup — visible in the worker log.
93
+ - Worker is waiting for a tool result whose subprocess hung.
94
+ - Prompt is huge / model is rate-limited; check provider-side errors in the
95
+ worker log.
96
+
97
+ ## Progress Event Interpretation
98
+
99
+ A `progress` event represents an in-flight piece of work. Its shape varies
100
+ by `action` field, but the load-bearing fields are always under `detail`:
101
+
102
+ - `detail.text_delta` — incremental model output (concatenate across events
103
+ to rebuild the streamed reply).
104
+ - `detail.tool_name`, `detail.tool_input` — tool call about to run or
105
+ currently running.
106
+ - `detail.status` — short string used by long-running actions
107
+ (`starting`, `running`, `flushing`, `done`).
108
+ - `detail.action` — semantic label (e.g. `status` for thread heartbeats).
109
+
110
+ Progress events are **noisy** by design. `wait` ignores them unless you
111
+ pass `--include-progress`. When you do want to see them, prefer:
112
+
113
+ ```bash
114
+ trellis channel messages <channel> --raw --kind progress --last 80
115
+ ```
116
+
117
+ A stream that emits progress at a steady cadence but never closes with
118
+ `done`/`error`/`message` is the classic shape of a hung tool call —
119
+ inspect the worker log for the subprocess.
120
+
121
+ ## Wait Semantics (Quick Reference)
122
+
123
+ `channel wait` watches `events.jsonl` from EOF and wakes on:
124
+
125
+ - `message`
126
+ - `done`
127
+ - `error`
128
+ - `killed`
129
+ - `progress` only with `--include-progress`
130
+
131
+ Useful filters:
132
+
133
+ ```bash
134
+ trellis channel wait T --as main --from check --kind done --timeout 15m
135
+ trellis channel wait T --as main --from check,check-cx --kind done --all --timeout 15m
136
+ trellis channel wait T --as worker --tag interrupt --timeout 1h
137
+ trellis channel wait T --as main --thread release-note --action status --timeout 10m
138
+ ```
139
+
140
+ Exit codes: `0` matched, `124` timeout, `1`/`2` errors. On `wait --all`
141
+ timeout, stderr names the workers still missing.
142
+
143
+ ## Auditing `events.jsonl` — Use Subcommands, Not `grep`
144
+
145
+ Every channel persists its full history at `$CHAN/events.jsonl`. It is
146
+ tempting to `tail` / `grep` / `jq` this file directly during debugging.
147
+ Don't make it a habit, and **never** do it for forum channels.
148
+
149
+ Why subcommands first:
150
+
151
+ - `messages` already replays the file with filters (`--kind`, `--from`,
152
+ `--last`, `--tag`, `--thread`, `--action`) and gives you `--raw` for the
153
+ exact JSON. Anything you would write a one-liner for, `messages` already
154
+ does.
155
+ - `wait` consumes the same file with EOF semantics — re-implementing that
156
+ with `tail -f | jq` will drop events under load and misorder them under
157
+ rotation.
158
+ - `context` materializes a worker's inbox view, including cursor state.
159
+ Hand-rolled filters do not respect `<worker>.inbox-cursor`.
160
+
161
+ ### Forum channels: never parse `events.jsonl` directly
162
+
163
+ Forum channels multiplex many logical threads onto a single `events.jsonl`.
164
+ Each event carries `thread`, `action`, and tag fields that the forum
165
+ subcommands know how to fold together. Parsing the file by hand will:
166
+
167
+ - Mix threads together and make a thread look incoherent.
168
+ - Miss thread lifecycle events (open / status / close) that change how
169
+ later events should be interpreted.
170
+ - Ignore worker inbox cursors, so you will "see" events a worker has
171
+ already consumed and assume they are pending.
172
+
173
+ Use the forum-aware views instead:
174
+
175
+ ```bash
176
+ # List logical threads inside the forum channel
177
+ trellis channel forum list <channel>
178
+
179
+ # Inspect one thread end-to-end
180
+ trellis channel thread show <channel> <thread>
181
+
182
+ # Replay messages for a thread (supports --raw, --kind, --last)
183
+ trellis channel messages <channel> --thread <thread> --raw --last 100
184
+
185
+ # What a specific worker still has pending
186
+ trellis channel context <channel> --as <worker>
187
+ ```
188
+
189
+ Direct reads of `events.jsonl` are reserved for the case where the CLI
190
+ itself is suspect — e.g. confirming an event was actually persisted, or
191
+ diffing against `<worker>.inbox-cursor` while debugging the supervisor.
192
+
193
+ ## Common Failures
194
+
195
+ | Symptom | Cause | Fix |
196
+ |---|---|---|
197
+ | `trellis: command not found` | CLI not installed globally | `npm install -g @mindfoldhq/trellis` |
198
+ | `wait` exits immediately | wrong filter or identity collision | use distinct `--as`, inspect raw messages |
199
+ | zsh errors on message text | shell interpreted punctuation | use `--stdin` or `--text-file` |
200
+ | progress line is cut off | pretty output truncation | use `messages --raw --kind progress` |
201
+ | worker never speaks | provider startup / prompt / MCP delay | inspect `<worker>.log`, `ps`, raw events |
202
+ | channel not found in another cwd | project bucket mismatch | `cd` to project, use `--scope global`, or `list --all-projects` |
203
+ | ghost worker in list | supervisor died without cleanup | `trellis channel kill <name> --as <worker> --force` |
204
+ | forum thread looks scrambled | parsed `events.jsonl` directly | use `forum`, `thread`, `messages --thread` |
205
+
206
+ ## Storage Layout
207
+
208
+ ```text
209
+ ~/.trellis/channels/
210
+ └── <bucket>/
211
+ └── <channel-name>/
212
+ ├── events.jsonl
213
+ ├── <channel>.lock
214
+ ├── <worker>.log
215
+ ├── <worker>.pid
216
+ ├── <worker>.worker-pid
217
+ ├── <worker>.config
218
+ ├── <worker>.session-id
219
+ ├── <worker>.thread-id
220
+ ├── <worker>.inbox-cursor
221
+ └── <worker>.spawnlock
222
+ ```
223
+
224
+ Agents normally use the CLI, not direct file reads. Direct file reads are
225
+ for debugging when CLI views are insufficient — and even then, never on a
226
+ forum channel's `events.jsonl`.