plans: refreshed row 128 brief, the bus project and thread verbs and talk --thread (#1622)

The 2026-10-14 brief predates rows 121, 142 and 143. This one names the
verbs on the existing broker ops, keeps plain talk asking for a thread
with no default, and targets acceptance 314 steps 1 and 3. Owner moves
to researcher.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-18 09:03:57 -05:00
co-authored by Claude Opus 5.5
parent 4af594fea0
commit 0f3eb25ea0
+137
View File
@@ -0,0 +1,137 @@
# Row 128 brief, refreshed 2026-10-18
This replaces the short brief in `docs/plans/2026-10-14_prd-1.2-build.md`
("mosaic talks to the assistant in a named thread"). Rows 121, 142 and 143
have landed since that brief was written, so the bus side is done and the
CLI side can be named exactly. Line numbers are at ac55e84fe.
## mosaic talks to the assistant in a named thread
### Problem
The bus has every project and thread op since row 121 (#1615):
`project.create` and `project.list` (`packages/bus/src/broker.mjs:2050`,
`:2068`), `thread.create`, `thread.list`, `thread.open`, `thread.send` and
`thread.messages` (`:2074`, `:2098`, `:2112`, `:2119`, `:2146`). No code in
`packages/cli` or `packages/webui` calls any of them. The assistant is the
business's threaded instance, and the broker refuses a human's plain
`message.send` to it with `thread-required-use-thread-send`
(`broker.mjs:288`). So today Jason can't create a project or a thread, and
`mosaic talk assistant ...` can only fail. Acceptance run 314
(`docs/acceptance/314.md`) needs both: step 1 creates a bus project, an
assistant thread in it and opens it, and step 3 talks in that thread and
expects only the assistant's reply. Requirements: REQ-CLI-1, REQ-CLI-2,
REQ-THREAD-2, REQ-USER-2 (`docs/prd/mosaic-stack.md:475`, `:668`, `:673`).
Gitea #1622.
### Owner and reviewer
- Owner: researcher.
- Reviewer: filbert (CLI only, no broker or sandbox change).
### Files owned
- `packages/cli/src/cli.mjs` (dispatch, `USAGE`, `talk` and `follow`)
- `packages/cli/src/project.mjs` (the `create` and `list` subcommands)
- `packages/cli/src/thread.mjs` (new: thread verbs and the thread resolver)
- `packages/cli/tests/thread-cli.test.mjs` (new)
- `packages/cli/tests/project.test.mjs`
- `packages/cli/tests/follow.test.mjs`, only if the follow loop's existing
tests need a thread case
- `packages/cli/README.md`, `docs/TOOLS.md`
- `docs/acceptance/314.md`, steps 1 and 3 only: replace "row 128's
commands" with the real command lines
- the packet `agents/researcher/work/queue-128/`
No change to `packages/bus`. If a verb below can't be built on the
existing ops, stop and tell Sage; that is a brief change, not a fix in
scope.
### What ships
Verbs. Every one goes through `callFor` (`cli.mjs:172`), so the human
transport, `--business` and the refusal inside an agent work as they do
for `talk` today. Each list verb takes `--json`.
1. `mosaic project create <name> [--repo <repo>]` calls `project.create`.
`mosaic project list` calls `project.list` and prints name, repo and a
short id. They join `init` and `check` under the `project` verb.
`init` and `check` keep their exact arguments and refusals; `create`
and `list` work on the bus record, `init` and `check` on the repository
on disk, and `docs/TOOLS.md` says that in one sentence.
2. `mosaic threads [--project <project>]` calls `thread.list` and prints
project name, thread name, instance and a short id.
3. `mosaic thread create <project> <name>` calls `thread.create` and
prints the id and the instance. `mosaic thread open <thread>` calls
`thread.open`. `mosaic thread read <thread>` pages `thread.messages`
and prints the history oldest first; it marks nothing read.
4. `mosaic talk --thread <thread> <text> [--wait <s> | --follow]` sends
with `thread.send`, class REQUEST, and takes one positional. Without
`--follow` it prints only the message whose `in_reply_to` is the sent
id, as row 142 does for roles (`cli.mjs:348`), and leaves the rest
unread. With `--follow` it prints every message in that thread after
the sent one and marks read those addressed to the human; messages of
other threads and outside threads stay unread for `mosaic inbox`.
`mosaic follow --thread <thread>` is the same loop without the send.
5. Plain `mosaic talk <role> <text>` to a threaded instance asks for a
thread; there is no default thread. On `thread-required-use-thread-send`
the CLI exits 2 with a message that names `--thread` and
`mosaic threads`. The bus never picks between instances, and a CLI
default would pick between Jason's threads for him. The packet records
this choice.
Thread and project references. A project is its name or its id. A thread
is its id, an id prefix of at least 8 characters, or `<project>/<name>`.
The resolver reads `project.list` and `thread.list` and refuses an unknown
or ambiguous reference before any send, the way `findDecision` does
(`cli.mjs:111`).
Refusals. `thread-not-owned`, `thread-not-found`, `project-not-found`,
`project-exists`, `thread-exists`, `unknown-repo`,
`thread-instance-missing` and `thread-instance-ambiguous` each print one
plain line and exit non-zero. The CLI adds no check the broker already
makes.
Tests, in `packages/cli/tests/thread-cli.test.mjs` against a real broker
the way `thread-launch.test.mjs` builds one:
- project create and list, including `project-exists` and `unknown-repo`;
`init` and `check` arity refusals unchanged;
- thread create, list (with and without `--project`), open and read;
- the resolver: id, prefix, `<project>/<name>`, too-short prefix, unknown
and ambiguous;
- `talk --thread` prints only the reply to the sent id and leaves an
unrelated message unread; `--wait` timeout; `--follow` prints only that
thread's messages and leaves another thread's message unread;
- plain `talk` to the assistant gets the `--thread` message, exit 2;
- REQ-USER-2: a thread owned by another human. `talk --thread`, `thread
open` and `thread read` on it are refused with `thread-not-owned`, and
no message, open or delivery row is written.
Mutants: one per behavior above, recorded in the packet with the killing
test, as row 142's packet does.
Suites: `node --test packages/cli/tests/*.test.mjs`, then the full gate.
Acceptance 314: after this row, step 1's bus half is
`mosaic project create stack --repo stack`,
`mosaic thread create stack assistant`, `mosaic thread open stack/assistant`
and `mosaic threads --project stack`; step 3 is
`mosaic talk --thread stack/assistant "<text>"`. The builder writes the
real lines into `docs/acceptance/314.md`.
### Out of scope
- Renaming a project or a thread: no broker op exists. P19 follow-up.
- The Console chat area: row 129 (#1623).
- Closing, deleting or archiving threads.
- Any broker, schema or launcher change.
- A live smoke. Steps 1 and 3 run in Jason's acceptance run, after the
re-pin and with Mos's go.
### Gate
Filbert approves on #1622, naming the candidate manifest digest. Sage
reruns the full gate at the landing target, and it must be green
(`scripts/test-*.sh` plus the package suites, 25 of 25 as on 6e7fdf7ff).
The REQ-USER-2 test above passes and its mutant is killed.