feat(board): session attention, Discord rows, task attribution and relaunch activity (rows 18, 22, #1511, #1512)
One cumulative control-board, webui and seat state. The four rows edit the
same files (scan.mjs, page.html, README.md, app.js), so they land together,
each on its own receipt:
- Row 18, Discord connector rows on the board (#1509): R3 approved by
Darkwing and Dewey, Gitea comment 26257, manifest 254403b8. Jason
accepted the visual test.
- Row 22, board attention status (#1503): Filbert approved R1, comment
26248, manifest e40b58ec; restart receipt 26249.
- #1511, task attribution (row 6 code phase): R2 approved by Filbert and
Dewey, manifest d4c96395. docs/TOOLS.md carries the approved --by usage
line (tools-usage.patch 86bcba3c).
- #1512, relaunch activity (row 6 pilot): R1 approved by Darkwing and
Dewey, candidate manifest 47769fad. All seven source files match it.
Row 16, internal development bootstrap (#1510): the seven files outside
shared records match Filbert's R1 pins, receipt 26204 (agents/researcher/*,
scripts/test-darkwing-launch.mjs, the bootstrap plan).
packages/webui/src/public/app.js is committed at its #1512 R1 pin ce7d79a4.
The working copy holds Dewey's unreviewed return-flow candidate on top of
that, and it stays uncommitted.
Also: the four row briefs and Darkwing's evidence records under
agents/darkwing/work, including the 2026-09-26 tree manifest and the #1512
re-run against 21e3e908. Serial acceptance command: 397/397, three runs.
The failures that only show when tests run concurrently are in #1509 engine
tests, and they reproduce on clean HEAD.
Suites on the exact staged tree: config 24, task 90, foundation 43,
conductor 17, release 14, auth 15, discord 63; package union 397/397
(serial); test-darkwing-launch 5/5.
Shared records (BUILD-LOG, QUEUE, CURRENT, DEFERRED, SESSIONS, AGENTS.md,
agents/README.md) follow in Sage's records commit.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -12,10 +12,10 @@ rewritable; they are not run records and are not evidence.
|
||||
| State | Plain-words meaning |
|
||||
|---------|----------------------|
|
||||
| working | The agent is in the middle of a turn: thinking or running a tool. A seat whose newest log entry is a tool call or a tool result is working even if its last words looked like a question. |
|
||||
| waiting | The agent finished its turn with a text-only message. It is your move now. |
|
||||
| waiting | The agent explicitly requested your input in its completed reply. |
|
||||
| error | The agent's last turn ended in an error, was aborted, or was cut off. Go look at it. |
|
||||
| offline | There is no live tmux session for this agent right now, or its session exists but no longer runs `pi`. |
|
||||
| idle | The agent is live but has not had a conversation yet. |
|
||||
| idle | The agent is live and available, including after a normal completed reply. |
|
||||
| unknown | The scanner could not ask tmux (missing or not answering). It does not assume the agent is alive. |
|
||||
|
||||
Liveness means a pane in the agent's tmux session is actually running `pi`
|
||||
@@ -23,6 +23,79 @@ Liveness means a pane in the agent's tmux session is actually running `pi`
|
||||
exists but only runs bash or some other program counts as offline, not
|
||||
waiting.
|
||||
|
||||
### Explicit human attention
|
||||
|
||||
A completed assistant reply requests attention only when its first nonblank text
|
||||
line begins at column zero with `Input needed: ` and a nonempty request. Example:
|
||||
|
||||
```text
|
||||
Input needed: Choose staging or production for the approved test.
|
||||
```
|
||||
|
||||
Ordinary replies such as `BOARD_REPLY_OK`, completion reports and questions without
|
||||
this explicit signal are idle. Code/quote examples and thinking blocks do not
|
||||
count. Tool activity/errors retain precedence. A later ordinary completed reply
|
||||
clears the previous request; a user/tool message is working, not waiting.
|
||||
|
||||
Agents reserve the signal for Jason's decision or input, not another agent's
|
||||
review or routine completion. It is display state, never action authorization.
|
||||
Existing unmarked replies cannot establish a human blocker. Seen acknowledges
|
||||
the current event and removes it from the attention list; it does not resolve a
|
||||
genuine request or change waiting to idle. A new request reappears.
|
||||
|
||||
## Relaunch activity notice
|
||||
|
||||
A live native row with a positively live, matching registration gets a
|
||||
`relaunchedAt` timestamp when that registration's valid `startedAt` is strictly
|
||||
newer than valid recorded `lastActivity`. Both board presentations then show
|
||||
`relaunched at X, no messages since` in the current activity/preview positions.
|
||||
The inspector explicitly labels retained last activity, assistant text and errors
|
||||
as historical. CLI `scan --print` also replaces its old preview/age with the notice. New recorded session activity at or after the launch timestamp
|
||||
clears the notice. Equality does not assert a relaunch.
|
||||
|
||||
Missing/invalid timestamps, missing or mismatched registrations, unknown/dead PID
|
||||
or row liveness, and connector rows yield `relaunchedAt: null`. Unknown is not
|
||||
proof of relaunch. The comparison uses the existing session activity timestamp,
|
||||
not a new transcript index or authenticated process-incarnation protocol.
|
||||
|
||||
This field changes presentation only. Historical transcript files and serialized
|
||||
lastActivity/lastAssistantText/lastError remain intact. State, attention, Seen,
|
||||
task selection/attribution and reply eligibility are unchanged. An old unresolved
|
||||
waiting/error state therefore remains visible, with its text labelled historical,
|
||||
rather than being silently cleared by the new notice. No launcher or live
|
||||
registration mutation is required to test this behavior.
|
||||
|
||||
## Discord connector rows
|
||||
|
||||
The CLI discovers private `<dataRoot>/discord/<binding>.json` files on every
|
||||
scan, including server rescans. Only matching safe binding name and seat identity
|
||||
are used. Files must be regular, non-symlink, mode 0600 and at most 1 MiB.
|
||||
Discovery never resolves token paths or projects binding policy, Discord IDs or
|
||||
user/channel lists. Invalid bindings produce fixed, content-free discoveryErrors.
|
||||
Library callers enable this with `discordDataRoot` on scan/startServer.
|
||||
|
||||
Rows use project `fleet` and agent `<seat> (discord: <binding>)`, distinct from
|
||||
native seats. Task is fixed `Discord connector`, with source `connector`, never
|
||||
inferred from the first user message: Discord routing envelopes contain private
|
||||
IDs. Ordinary-agent task derivation and assistant transcript display are unchanged.
|
||||
Session history comes from `sessions/discord-<binding>` without
|
||||
following linked directories/files. Liveness uses the connector's readPid and
|
||||
ownerState checks, not tmux or registration: only a live PID with matching boot
|
||||
ID and start tick is live. Missing, invalid, dead or unverifiable owners are
|
||||
non-live. The `connector` projection contains binding, alive, ownerState and
|
||||
braked only; it does not expose the journal directory or owner record.
|
||||
|
||||
STOP presence is shown separately as braked, even when the owner is offline.
|
||||
An unsafe journal path gives brake unknown, not an unbraked claim. STOP contents
|
||||
are never read. Activity retains the usual idle/waiting/error rules. Both board
|
||||
pages omit Reply for connector rows; the backend refuses connector replies before
|
||||
transport even if a stale/forged native registration supplies tmux details.
|
||||
|
||||
This is read-only observation, not connector control. No brake, unlock, recovery,
|
||||
Discord request, counter collection or engine action is performed. Tests use
|
||||
isolated bindings, sessions and process identities; they do not prove live
|
||||
service transitions or authorize replacing a running board.
|
||||
|
||||
## Commands
|
||||
|
||||
```
|
||||
@@ -156,8 +229,18 @@ name alone. A registered task, project or workspace replaces the derived
|
||||
value and the row's source field (`taskSource`, `activeProjectSource`,
|
||||
`workspaceSource`) reads `registration`; the page shows a small source tag
|
||||
next to the value and a "Registered" line in the detail with the start time,
|
||||
harness, pid and tmux session. An empty task or a null project or workspace
|
||||
in the record leaves the derived value in place. Rows with no registration
|
||||
harness, pid and tmux session. When the task shown is the registered one,
|
||||
the row also carries `taskSetBy` (#1511): the record's `taskSetBy` from
|
||||
`mosaic seat task --by NAME` (else `$MOSAIC_AGENT_NAME`, else `unknown`),
|
||||
or `unknown` for a record written before the field existed. Both pages show
|
||||
it as a "set by NAME" tag after the task's source tag and a "Task set by"
|
||||
detail row. It is what the caller claimed, not a verified identity: the
|
||||
board escapes and displays it and nothing else reads it; in particular the
|
||||
reply gate looks only at the registration. For every other task source
|
||||
(`first-user-message`, `connector`, a stale registration, no task) it is
|
||||
null, so a record never lends its setter to a task it did not set. An empty
|
||||
task or a null project or workspace in the record leaves the derived value
|
||||
in place. Rows with no registration
|
||||
are exactly as before. The board only reads `seats/`; `mosaic launch` and
|
||||
`mosaic seat task` are the only writers. A malformed record is listed in
|
||||
`registrationErrors` on the index (and on stderr for `scan`) and skipped.
|
||||
@@ -194,6 +277,7 @@ values), the scan refuses rather than silently dropping every mark.
|
||||
"cwd": "/mnt/storage/src/mosaic-stack",
|
||||
"task": "Read agents/darkwing/work/RESTART.md",
|
||||
"taskSource": "first-user-message",
|
||||
"taskSetBy": null,
|
||||
"workspace": "/mnt/storage/src/mosaic-stack",
|
||||
"workspaceSource": "tmux-pane",
|
||||
"activeProject": "mosaic-stack",
|
||||
|
||||
Reference in New Issue
Block a user