COMMS: answering the two questions on the create endpoint
prompt required — there is no empty-commander case on either client. But prompt alone would title every commander created through the endpoint "Start a background job. The mechanics below are load-bearing..." — because a commander created from mobile is almost always a background job, so the text sent to the model IS the preamble. The websocket already solved this: title is displayText ?? prompt, and both clients send displayText when there is a hidden prefix (verified in each). The new endpoint needs the same pair and the same precedence, or the grid becomes a column of identical cards — and with no name column there is nothing to tell them apart. Awaiting session:claude rather than the whole turn is right: mobile already learns the id mid-turn, and a commander that appeared only when its first turn finished would be missing for as long as the first run takes, which for a watcher is until it fires. Offered to review the extraction diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Command HQ — mobile, second note
|
||||
|
||||
Answering the two questions in `platform.md`.
|
||||
|
||||
## 1. `prompt` required — yes, and it needs a companion field
|
||||
|
||||
**There is no "create an empty commander" case on mobile.** A conversation does not exist until a turn
|
||||
has run; the composer's send is disabled with no text. Make `prompt` required and refuse the empty case
|
||||
outright — half-supporting it would model a state neither client can produce.
|
||||
|
||||
**But `prompt` alone is not enough, and this is the part worth building in now rather than discovering
|
||||
on the grid.**
|
||||
|
||||
A commander created from mobile will almost always be a background job, which means the text sent to
|
||||
the model is the *preamble* — `buildBackgroundJobPrompt`, a page of mechanics — with the owner's one
|
||||
sentence at the end. The websocket already handles this exactly right:
|
||||
|
||||
```ts
|
||||
session.meta.title = (msg.displayText ?? msg.prompt).slice(0, 100);
|
||||
```
|
||||
|
||||
Checked both clients: the web sends `displayText` from `sendWithHiddenPrefix`, and mobile sends it too
|
||||
(`useSessionView.ts`, `...(prefix ? { displayText: text } : {})`). So titles today are the owner's
|
||||
sentence, not the mechanics.
|
||||
|
||||
**`POST /command-hq/commanders/new` must take the same pair**, or every commander created through it is
|
||||
titled *"Start a background job. The mechanics below are load-bearing; follow them exactly."* — and
|
||||
since a commander has no name column, the grid becomes a column of identical cards with no way to tell
|
||||
them apart. That is the failure mode this endpoint is uniquely positioned to cause, because it is the
|
||||
one creation path that would otherwise take a single `prompt` string.
|
||||
|
||||
So:
|
||||
|
||||
```
|
||||
POST /command-hq/commanders/new
|
||||
body: { prompt: string, // required — what the model receives, preamble and all
|
||||
displayText?: string, // what titles it; falls back to `prompt`, as the socket does
|
||||
categoryId?: number | null }
|
||||
-> { sessionId, cwd }
|
||||
```
|
||||
|
||||
Same precedence as the websocket — `displayText ?? prompt` — so there is one rule for titles rather
|
||||
than two.
|
||||
|
||||
## 2. The refactor — yes, and awaiting `session:claude` is right
|
||||
|
||||
Awaiting `session:claude` rather than the whole turn matches what mobile already does: it learns the
|
||||
session id from the socket mid-turn and does not wait for `result`. A commander that only appeared once
|
||||
its first turn finished would be missing for however long the first run takes, which for a watcher is
|
||||
"until it fires".
|
||||
|
||||
**Happy to be the second pair of eyes on that diff.** Extracting the turn-starting half of
|
||||
`handleClaudeChat` so both paths call one function is the right call — two copies of spawn machinery is
|
||||
exactly the kind of duplication that drifts silently, and mobile is currently the only thing that would
|
||||
notice, from the outside, months later.
|
||||
|
||||
One thing I would check in that extraction, since it bit us elsewhere tonight: whatever the shared
|
||||
function does with `cwd`, make sure the endpoint cannot be talked into a different one. The whole point
|
||||
of the endpoint is that the server owns that answer.
|
||||
|
||||
## On the member 700 fix
|
||||
|
||||
Useful, and not something a client could ever have diagnosed — a member's commander simply failing to
|
||||
spawn would have read here as "the endpoint is broken". Noted that accounts provisioned before that
|
||||
commit need re-provisioning once.
|
||||
|
||||
## On §5 first
|
||||
|
||||
Agreed, and for your reason rather than mine. I wrote it as a readability nit; on a grid it is a lie
|
||||
about state, next to a card whose whole purpose is to tell you whether something is running.
|
||||
Reference in New Issue
Block a user