summaryrefslogtreecommitdiffhomepage
path: root/tasks.md
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-12 18:37:09 +0900
committerAdam Malczewski <[email protected]>2026-06-12 18:37:09 +0900
commitdbf77ba78ff840e0ed5f6294030523fe3ab121fa (patch)
treee768aef3edd0c126212058c3d1433355594c49be /tasks.md
parent6689eb51b467d8e370f31495840d88661f978168 (diff)
downloaddispatch-dbf77ba78ff840e0ed5f6294030523fe3ab121fa.tar.gz
dispatch-dbf77ba78ff840e0ed5f6294030523fe3ab121fa.zip
feat(history): CR-5 windowed reads — ?limit= / ?beforeSeq= on GET /conversations/:id
Selection sinceSeq < seq < beforeSeq; newest-limit window, ascending; positive- integer validation (400, store never sees an invalid window); 1-based gap-free seq codified as the contractual has-older mechanism (no earliestSeq field). transport-contract 0.9.0->0.10.0, wire 0.6.0->0.6.1 (doc-only). conversation-store +8 tests, transport-http +20; 935 vitest + 112 bun green. Live-verified: 6/6 probe checks OK. FE courier: frontend-history-windowing-handoff.md
Diffstat (limited to 'tasks.md')
-rw-r--r--tasks.md80
1 files changed, 74 insertions, 6 deletions
diff --git a/tasks.md b/tasks.md
index f77577a..205d9c9 100644
--- a/tasks.md
+++ b/tasks.md
@@ -26,8 +26,11 @@ extension through the host):
## How to run
```bash
-KEY1=$(grep DISPATCH_API_KEY_OPENCODE1 .env | cut -d= -f2)
-PORT=4567 DISPATCH_API_KEY="$KEY1" bun packages/host-bin/src/main.ts # boots app + collector
+# .env auto-loads DISPATCH_API_KEY (do NOT re-export) and pins BACKEND_PORT (beats PORT).
+# Private probe instance: override the port + ISOLATE data paths (ORCHESTRATOR §8):
+BACKEND_PORT=4567 SURFACE_WS_PORT=4569 DISPATCH_DB=/tmp/opencode/probe/dispatch.db \
+ DISPATCH_TRACE_DB=/tmp/opencode/probe/traces.db DISPATCH_JOURNAL=/tmp/opencode/probe/app.ndjson \
+ bun packages/host-bin/src/main.ts # boots app + collector
curl -s -X POST localhost:4567/chat -H 'content-type: application/json' \
-d '{"conversationId":"c1","message":"Say hello in 3 words."}' # field = conversationId
```
@@ -323,8 +326,35 @@ FE courier in: `../dispatch-web/backend-handoff-cache-warming.md` (+ CR-1/CR-2 f
2 automatic warms @5s each pushing future `nextWarmAt`, mid-turn close → `abortedTurn:true` +
`done.reason:"aborted"` + warming disabled, catalog scopes + table field present, echo present.
+## History windowing — FE CR-5 (DONE)
+FE courier in: `../dispatch-web/backend-handoff-chat-limit.md` (+ living `backend-handoff.md` §2
+CR-5). Courier out: `frontend-history-windowing-handoff.md`. User-gated call: ask #3 shipped as
+the INVARIANT option (no new field) — seq is contractually **1-based, monotonic, gap-free**; FE
+derives `hasOlder` from `chunks[0].seq > 1`.
+- **Wave 0 (orchestrator, contracts):** `limit`/`beforeSeq` query-param semantics + validation +
+ `latestSeq` windowed-read caveat documented on `ConversationHistoryResponse`
+ (`@dispatch/transport-contract` `0.9.0→0.10.0`); 1-based seq guarantee codified on
+ `StoredChunk` (`@dispatch/wire` `0.6.0→0.6.1`, doc-only).
+- **Wave 1 — `conversation-store`:** additive `loadSince(id, sinceSeq?, window?: { beforeSeq?,
+ limit? })` — selection `sinceSeq < seq < beforeSeq`, newest-`limit` window, result stays
+ ascending; garbage-in treated as absent (transport validates upstream). +8 tests.
+- **Wave 2 — `transport-http`:** parses + validates the params (positive integers; malformed/
+ zero/negative → 400 `{ error }`, store never called with an invalid window); two-arg call
+ shape preserved when no params (regression-guarded). +20 tests.
+- 935 vitest + 112 bun tests, typecheck + biome clean. **LIVE-VERIFIED** (isolated boot, real
+ flash turns): firstSeq=1; `limit=2`→`[5,6]` ascending w/ correct `latestSeq`; `limit=9999`→
+ full log; `beforeSeq=3`→`[1,2]`; `beforeSeq=3&limit=1`→`[2]`; `limit=0`/`beforeSeq=0`/
+ `limit=abc`→400×3. `RESULT: OK` ×6.
+- **Scar tissue (process):** (1) probing with a PRIVATE boot was overkill — the windowing checks
+ are read-only GETs and the dev stack was running; prefer probing `bin/up`/`up2` or asking the
+ user (ORCHESTRATOR §8 updated). (2) The §8 boot recipe was stale (`DISPATCH_API_KEY_OPENCODE1`
+ doesn't exist; an empty re-export OVERRIDES `.env` → "No providers registered"; `.env`'s
+ `BACKEND_PORT` beats `PORT`; un-isolated data paths spawn a duplicate collector on the dev
+ DB) — recipe fixed in §8 + above. (3) Violated the bracket trick once (`pkill -f 'cr5-data'`
+ self-matched → killed parent shell, timeout-with-no-output); the existing §8 rule stands.
+
## Open items
-- **Context window LIMIT (next, sibling of context size):** expose the selected model's max
+- **Context window LIMIT (deferred, sibling of context size):** expose the selected model's max
context-window token limit so the FE can render `contextSize / limit` (e.g. `1286 / 200000`).
Source = the provider/model catalog (`ModelInfo`); likely a field on the models response
and/or stamped alongside `contextSize`. "context size" = current usage (DONE); "context
@@ -341,9 +371,47 @@ FE courier in: `../dispatch-web/backend-handoff-cache-warming.md` (+ CR-1/CR-2 f
chain).
## Roadmap
-1. **CLI** — done.
-2. **Web frontend** (in progress, SEPARATE repo `../dispatch-web`; Svelte +
+1. **Web frontend** (in progress, SEPARATE repo `../dispatch-web`; Svelte +
DaisyUI, same methodology). Slice 2 = browser chat MVP consuming the
wire/transport-contract + metrics. Cross-repo contract changes are couriered
via the user (ORCHESTRATOR §7); `lsp references` does not span repos.
-3. **dedup / storage growth** — after the frontend (see Open items).
+2. **CLI → open-tab handoff (cross-client messaging):** an AI given a short
+ conversation identifier (4+ chars) in chat can use the CLI to send a message
+ INTO that conversation, and an FE tab watching it sees the message + reply
+ live. To the receiving AI the message appears as a REGULAR user message
+ (no special framing). The broadcast plumbing already exists and is
+ live-verified (detached turns + `chat.subscribe` + CR-3 `user-message`
+ event); the gaps are (a) a conversation LIST/discovery endpoint (none
+ exists), (b) short-id / prefix resolution of `conversationId` in the CLI,
+ (c) end-to-end verification of the handoff workflow. CLI semantics:
+ - **read last message** (new): BLOCKING — waits until the in-flight turn
+ settles, then returns ONLY the AI's last message of that turn (not the
+ whole conversation).
+ - **send, no `--queue` flag (default):** BLOCKING — sends, waits for the
+ turn to settle, returns the AI's last message (same shape as the read).
+ - **send with `--queue`:** enqueues the message into the conversation's
+ message queue (roadmap item 3) and exits immediately.
+3. **Message queue + steering injection (backend core; prerequisite for the
+ `--queue` flag in item 2):** a per-conversation queue a client (FE or CLI)
+ can push a message onto while a turn is GENERATING. Delivery semantics:
+ - On the turn's next TOOL CALL, queued messages are injected as "steering"
+ messages returned alongside the tool result (the model sees them
+ mid-turn and can adjust course).
+ - If the turn ends before any tool call fires, the queued messages are
+ COMBINED and sent as a fresh user message starting a NEW turn.
+ - FE queueing UX (queue while generating) couriered to `../dispatch-web`.
+ Touches the kernel turn loop (injection at the tool-result boundary) — a
+ contract-first design pass needed before summoning.
+4. **CLI flag to open/activate an FE tab:** optional CLI flag (new or existing
+ conversation) that makes an already-open frontend open the conversation as a
+ tab and mark it active. Does NOT exist today — no backend→FE "open/focus
+ conversation" push (only the inverse, `POST /conversations/:id/close`).
+ Needs a new broadcast WS op + endpoint/flag here, and FE handling couriered
+ to `../dispatch-web`.
+5. **`todo` tool** — a per-conversation task-list tool the model maintains
+ (like opencode's todowrite/todoread), as a standard tool extension; likely a
+ surface so the FE can render the live list.
+6. **`web_search` tool** — a web search tool (like old dispatch's;
+ reference-only source at `../dispatch-source`), as a standard tool extension.
+
+(Done and dropped from the list: CLI; dedup / storage growth.)