wg-chat-as

wg chat as first-class entity: decouple chat persistence from service runtime

Metadata

Statusdone
Assignedagent-580
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-26T20:06:03.370023062+00:00
Started2026-04-27T12:57:56.428205502+00:00
Completed2026-04-27T13:16:15.854484236+00:00
Tagseval-scheduled
Tokens9288381 in / 51175 out
Eval score0.58
└ blocking impact0.45
└ completeness0.60
└ coordination overhead0.50
└ correctness0.65
└ downstream usability0.50
└ efficiency0.60
└ intent fidelity0.48
└ style adherence0.70

Description

Description

RESUME FROM PRIOR WIP — this task was already started by agent-105, which made 15h of progress before getting wedged. Start from the existing work, do NOT redo from scratch.

Prior work (already on branch)

  • Branch: wg/agent-105/wg-chat-as
  • Last commit: 74cd06ad6 wip: wg-chat-as 15h checkpoint (agent-105)
  • Files added/modified:
    • NEW: src/commands/chat_cmd.rs (the new wg chat command tree implementation)
    • MOD: src/cli.rs (+109 lines — added Chat enum variant with subcommand tree)
    • MOD: src/main.rs (+47 lines — wired up new chat dispatch)
    • MOD: src/commands/service/ipc.rs (refactor)
    • MOD: src/commands/mod.rs (+1 — module decl)
  • Status: wg chat list works (tested live: shows .coordinator-1 legacy chat correctly). The wg chat subcommand tree is wired in; chat-as-first-class-entity scaffolding is in place.

What got it stuck

wg chat create --name X errors with unexpected argument '--name' found, Usage: wg chat <MESSAGE>. The CLI parser is hitting an args-conflict between the Chat { ... } enum variant's args_conflicts_with_subcommands = true / subcommand_precedence_over_arg = true setup AND the positional MESSAGE arg on that variant. Parser thinks chat is a positional-arg variant instead of a subcommand-tree variant.

In src/cli.rs around lines 1168-1171 — debug the args_conflicts_with_subcommands attribute interaction. Likely fix: separate the wg chat <message> shorthand (positional) from wg chat <subcommand> tree, OR drop the shorthand entirely and require explicit subcommand.

Remaining work to ship

  1. Fix the CLI args parser conflict so wg chat create --name X (and other subcommands like list / show / attach / send / stop / archive / delete) all parse cleanly.
  2. Live smoke the full chat lifecycle:
    • Service stopped → wg chat create --name foo succeeds; chat dir scaffolded
    • wg chat list shows it as 'dormant'
    • Service start → still dormant (NOT auto-spawned)
    • wg chat attach foo opens TUI; send 'hi'; get response from claude CLI
    • Detach (Esc / close TUI) → handler exits cleanly
    • wg chat list shows 'stopped' (or 'dormant')
    • wg chat attach foo again → resumes with prior history
  3. Unit tests for the new code paths
  4. Migration — legacy .coordinator-N graph entries get extracted to .wg/chat/ dirs and removed from graph (per the architectural contract)

Architectural contract (RE-CONFIRMED)

  • Chats are NOT in graph.jsonl — period. .wg/chat/<id>/ IS the chat.
  • No background supervisor — service does NOT watch chat inboxes, does NOT spawn handlers proactively.
  • Reference / index for coherency only — wg chat list is a filesystem walk of .wg/chat/.
  • Attach spawns handler, detach exits handler — like tmux sessions.
  • Async wg chat send <id> <msg> is fire-and-forget — appends to inbox, no autonomous response.
  • TUI is the de facto supervisor for chats it's actively showing — tab open = handler alive; tab closed = handler exits.
  • Eliminate chat-loop / coordinator-loop tags entirely.
  • No graph entries for chats. No cycle iterations. No wg done on chats. No .evaluate- / .flip- / .assign- for chats.

How to start

git checkout wg/agent-105/wg-chat-as     # this is your branch — you already have prior work
cargo build                               # confirm builds
cargo run -- chat list                    # confirm wg chat list works
cargo run -- chat create --name testfoo  # this is the failing case — START HERE
# debug + fix the args parser; iterate until smoke passes

Hard gate before claiming done

  • wg chat create --name X succeeds, returns the new chat id, no errors
  • All 7 wg chat subcommands (create, list, show, attach, send, stop, archive, delete) parse + execute correctly
  • Live smoke (above) completes end-to-end
  • No legacy chat-loop tag remaining anywhere in src/ (grep returns zero hits)
  • cargo build + cargo test pass with no regressions

Depends on

Required by

Messages 2 messages

  1. #1user2026-04-27T02:35:24.797237470+00:00delivered
    Architectural clarification from user (verbatim): 'there should not be chat loop tasks.... what on earth is a chat loop task lol. we just should have chats and handles to them for resuming'.
    
    So the contract is sharper than the original task description suggested. NO ambiguity:
    
    1. **Chats are NOT graph tasks.** A chat does NOT get a `.chat-N` entry in graph.jsonl. The graph is for WORK (units with goals, deps, completion). Conversations don't fit that.
    
    2. **Chats live entirely in `.wg/chat/<id>/`** — that directory IS the chat. Contains inbox.jsonl, outbox.jsonl, handler.log, metadata.json (model, executor, name, created_at, last_active). The dispatcher knows nothing about it.
    
    3. **Service supervisor watches `.wg/chat/` directly.** On boot, enumerates existing chat dirs. On new message in any inbox, spawns a handler. On message complete, handler exits. No cycle iterations. No 'chat-loop' tag. No `wg done` on chats. No `.evaluate-` / `.flip-` / `.assign-` scaffolding.
    
    4. **`wg chat` command tree (per original spec)** is the only API surface — `create / list / show / attach / send / stop / resume / archive / delete`. None of these touch the graph.
    
    5. **Migration**: existing legacy `.chat-N` and `.coordinator-N` graph tasks get removed from graph entirely (their chat dirs migrate to the new model — they were always supposed to be the actual storage). One-time `wg migrate chat-graph-extract` command does this idempotently.
    
    6. **Eliminate the `chat-loop` / `coordinator-loop` tag entirely** — no code path should reference these tags after this lands. The bandaid in `evaluate_all_cycle_iterations` (skip chat-loop tagged) becomes dead code; remove it.
    
    The user's frustration is exactly that chat got modeled as a graph cycle in the first place. Don't preserve that — replace it.
  2. #2user2026-04-27T02:52:29.308453588+00:00delivered
    CORRECTION to my prior message — I was wrong about the service watching chats. User confirmed:
    
    The service does NOT supervise chats. The service deals with TASKS (units of work). Chats are entirely independent — like tmux/screen sessions.
    
    Correct architecture:
    
    1. **Chat = `.wg/chat/<id>/` directory.** Storage is the chat. inbox.jsonl + outbox.jsonl + handler.log + metadata.json. Durable on disk regardless of any process being alive.
    
    2. **No background supervisor.** The service / dispatcher does NOT watch chat inboxes, does NOT spawn chat handlers proactively, does NOT poll. Chats exist on disk independent of any running process.
    
    3. **Reference / index for coherency only.** `wg chat list` enumerates chat dirs (filesystem walk). `wg chat show <id>` reads metadata.json. The TUI shows tabs for chats by listing the dirs. This is METADATA coherency, NOT runtime management.
    
    4. **Attach spawns handler, detach exits handler.** `wg chat attach <id>` (or TUI focusing a chat tab) spawns the handler subprocess. The handler reads inbox, writes outbox, responds to user input. When the user detaches (Esc out of tab, close TUI, Ctrl-C `wg chat attach`), the handler exits. Chat dir stays.
    
    5. **Async send is fire-and-forget**. `wg chat send <id> <msg>` appends to inbox.jsonl and returns. No response is generated until someone attaches. (No autonomous wake-up.)
    
    6. **Mental model**: tmux session. The chat exists whether anyone is 'in' it or not. Many can exist concurrently. Attach / detach freely. The 'session' isn't running anything when nobody is attached — it's just files.
    
    Implications:
    - No `chat-loop` tag (eliminate it everywhere)
    - No graph entries for chats
    - No cycle iterations
    - No `wg done` semantics for chats
    - No `.evaluate-` / `.flip-` / `.assign-` agency scaffolding for chats
    - No daemon involvement at all in the chat lifecycle
    - TUI is the de facto 'supervisor' for chats it's actively showing
    - `wg service stop` does NOT affect chats (they live in the filesystem)
    
    This is much simpler than what I described before. Sorry for the wrong direction. Refer to this as the canonical contract.

Log