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:
2026-09-26 14:54:18 -05:00
co-authored by Claude Opus 5.5
parent 21e3e908b6
commit af4203ca92
67 changed files with 2417 additions and 78 deletions
+172 -1
View File
@@ -29,7 +29,10 @@ import {
updateTask,
findRegistrations,
samePath,
resolveSetBy,
TASK_LIMIT,
SET_BY_NAME,
SET_BY_UNKNOWN,
} from "../src/seat.mjs";
const pkgRoot = resolve(import.meta.dirname, "..");
@@ -91,6 +94,9 @@ function buildConfig(root, dataRoot = join(root, "data")) {
function cliEnv(overrides = {}) {
const env = { ...process.env, TMUX: "", TMUX_PANE: "" };
delete env.MOSAIC_LAUNCH_REGISTERED;
// The developer's shell may carry a seat name (agents/rocko/launch.sh
// exports one); attribution tests set it explicitly or not at all.
delete env.MOSAIC_AGENT_NAME;
return { ...env, ...overrides };
}
@@ -290,7 +296,7 @@ test("writeRegistration/readRegistration: round trip, permissions, absence, and
// 7. updateTask
// ---------------------------------------------------------------------------
test("updateTask: changes task and updatedAt only, and refuses appropriately", () => {
test("updateTask: changes task, taskSetBy and updatedAt only, and refuses appropriately", () => {
const root = makeRoot();
const seatDir = buildRepoSeat(root, "myseat");
const resolved = resolveSeat("myseat", { repo: root });
@@ -300,11 +306,14 @@ test("updateTask: changes task and updatedAt only, and refuses appropriately", (
const updated = updateTask(seats, "myseat", "revised");
assert.equal(updated.task, "revised");
assert.equal(updated.taskSetBy, SET_BY_UNKNOWN, "no setBy option records the literal unknown");
assert.notEqual(updated.updatedAt, null);
for (const key of Object.keys(record)) {
if (key === "task" || key === "updatedAt") continue;
assert.deepEqual(updated[key], record[key], `field ${key} changed unexpectedly`);
}
assert.equal(updated.startedAt, record.startedAt, "startedAt is the launch time and survives a task update");
assert.deepEqual(Object.keys(updated).sort(), [...Object.keys(record), "taskSetBy"].sort(), "exactly one field is added");
// Refuses when there is no registration to attach to.
assert.throws(() => updateTask(seats, "ghost", "x"), (err) => {
@@ -560,3 +569,165 @@ test("samePath: equal paths, symlinked dirs, distinct dirs, and non-strings", ()
assert.equal(samePath(1, "x"), false);
assert.equal(samePath(null, target), false);
});
// ---------------------------------------------------------------------------
// 14. Task attribution (#1511): taskSetBy on the record, resolveSetBy, and the
// --by / MOSAIC_AGENT_NAME precedence at the CLI. Attribution is a claim by
// the caller: bounded, escaped by the presentations, never authority.
// ---------------------------------------------------------------------------
test("resolveSetBy: explicit --by wins over the environment; absent or empty environment gives unknown; invalid explicit or environment values refuse with exit 4", () => {
assert.equal(resolveSetBy({ by: "darkwing", env: { MOSAIC_AGENT_NAME: "rocko" } }), "darkwing");
assert.equal(resolveSetBy({ by: null, env: { MOSAIC_AGENT_NAME: "rocko" } }), "rocko");
assert.equal(resolveSetBy({ env: {} }), SET_BY_UNKNOWN);
assert.equal(resolveSetBy({ env: { MOSAIC_AGENT_NAME: "" } }), SET_BY_UNKNOWN);
assert.equal(resolveSetBy({ by: "jason@host:1", env: {} }), "jason@host:1");
assert.equal(resolveSetBy({ by: "a".repeat(64), env: {} }), "a".repeat(64), "64 characters is the bound");
const refused = (fn, pattern) => assert.throws(fn, (err) => {
assert.ok(err instanceof SeatError);
assert.equal(err.exitCode, 4);
assert.match(err.message, pattern);
return true;
});
for (const bad of ["", " ", "a".repeat(65), "<b>x</b>", "two words", "-leading", ".leading", "tab\tname", "new\nline", "ünïcode", "a/b", "a;b", "$(x)"]) {
refused(() => resolveSetBy({ by: bad, env: { MOSAIC_AGENT_NAME: "valid" } }), /--by/);
assert.equal(SET_BY_NAME.test(bad), false);
// The offending value is never echoed back.
if (bad.trim().length > 1) assert.throws(() => resolveSetBy({ by: bad, env: {} }), (err) => !err.message.includes(bad));
}
refused(() => resolveSetBy({ by: 42, env: {} }), /--by/);
// A set but malformed environment value is refused, not read as unknown:
// silently reporting "unknown" would hide a misconfigured seat, and --by
// is the explicit way past it.
refused(() => resolveSetBy({ env: { MOSAIC_AGENT_NAME: "<script>" } }), /MOSAIC_AGENT_NAME/);
refused(() => resolveSetBy({ env: { MOSAIC_AGENT_NAME: "a".repeat(65) } }), /MOSAIC_AGENT_NAME/);
assert.throws(() => resolveSetBy({ env: { MOSAIC_AGENT_NAME: "<script>" } }), (err) => !err.message.includes("<script>"));
assert.equal(resolveSetBy({ by: "explicit", env: { MOSAIC_AGENT_NAME: "<script>" } }), "explicit", "an explicit value does not consult the environment at all");
});
test("validateRegistration/readRegistration: taskSetBy is optional; a record without it (written before #1511) still loads unchanged; an invalid one is refused; the version does not change", () => {
const root = makeRoot();
const seatDir = buildRepoSeat(root, "old");
const resolved = resolveSeat("old", { repo: root });
const seats = seatsDir(join(root, "data"));
const record = makeRegistration({ resolved, task: "launched task", pid: 1 });
assert.equal("taskSetBy" in record, false, "launch does not attribute; only seat task does");
assert.equal(record.version, 1);
// An old on-disk record, byte for byte, without the field.
const path = registrationPath(seats, "old", "repo");
mkdirSync(dirname(path), { recursive: true });
const oldBytes = JSON.stringify(record, null, 2) + "\n";
writeFileSync(path, oldBytes);
const loaded = readRegistration(seats, "old", "repo");
assert.deepEqual(loaded, record);
assert.equal(loaded.taskSetBy, undefined);
assert.equal(readFileSync(path, "utf8"), oldBytes, "reading never rewrites (no implicit migration)");
assert.equal(findRegistrations(seats, "old").length, 1);
// Valid values.
for (const ok of ["unknown", "darkwing", "jason@host:1", "a".repeat(64)]) validateRegistration({ ...record, taskSetBy: ok });
// Invalid values, never echoed.
for (const bad of [null, 7, "", "<b>", "two words", "a".repeat(65), {}]) {
assert.throws(() => validateRegistration({ ...record, taskSetBy: bad }), (err) => {
assert.ok(err instanceof SeatError);
assert.match(err.message, /taskSetBy/);
if (typeof bad === "string" && bad.length > 1) assert.equal(err.message.includes(bad), false);
return true;
});
}
writeFileSync(path, JSON.stringify({ ...record, taskSetBy: "<b>" }));
assert.throws(() => readRegistration(seats, "old", "repo"), /taskSetBy/);
});
test("updateTask: records setBy, preserves startedAt and every unrelated field, upgrades an old record in place only when the task is set, and replaces a previous attribution", () => {
const root = makeRoot();
buildRepoSeat(root, "myseat");
const resolved = resolveSeat("myseat", { repo: root });
const seats = seatsDir(join(root, "data"));
const started = new Date("2026-09-10T10:00:00Z");
const record = makeRegistration({ resolved, task: "original", harness: "pi", tmux: { socket: "mosaic-fleet", session: "myseat" }, pid: 1, workspace: "/w", project: "proj", now: () => started });
writeRegistration(seats, record);
const first = updateTask(seats, "myseat", "by darkwing", { setBy: "darkwing", now: () => new Date("2026-09-14T10:00:00Z") });
assert.equal(first.taskSetBy, "darkwing");
assert.equal(first.startedAt, started.toISOString());
assert.equal(first.updatedAt, "2026-09-14T10:00:00.000Z");
for (const key of ["seat", "project", "workspace", "tmux", "harness", "pid", "sessionsDir", "seatDir", "launchScript", "layout", "version"]) {
assert.deepEqual(first[key], record[key], `field ${key} changed unexpectedly`);
}
assert.deepEqual(readRegistration(seats, "myseat", "repo"), first);
const second = updateTask(seats, "myseat", "by jason", { setBy: "jason", now: () => new Date("2026-09-14T11:00:00Z") });
assert.equal(second.taskSetBy, "jason", "a later set replaces the attribution; it is not appended");
assert.equal(second.startedAt, started.toISOString());
const third = updateTask(seats, "myseat", "anonymous");
assert.equal(third.taskSetBy, SET_BY_UNKNOWN, "no setBy means unknown, never the previous name");
// Invalid setBy refuses with exit 4 before anything is written.
const before = readFileSync(registrationPath(seats, "myseat", "repo"), "utf8");
assert.throws(() => updateTask(seats, "myseat", "x", { setBy: "<b>" }), (err) => err instanceof SeatError && err.exitCode === 4);
assert.throws(() => updateTask(seats, "myseat", "x", { setBy: "" }), (err) => err instanceof SeatError && err.exitCode === 4);
assert.equal(readFileSync(registrationPath(seats, "myseat", "repo"), "utf8"), before);
});
test("CLI seat task: --by beats MOSAIC_AGENT_NAME, the environment beats nothing, empty environment is unknown, invalid --by or environment refuses with exit 4 and leaves the record byte for byte", () => {
const root = makeRoot();
buildRepoSeat(root, "myseat");
const { configPath, dataRoot } = buildConfig(root);
const path = registrationPath(seatsDir(dataRoot), "myseat", "repo");
const launchResult = runCli(["launch", "myseat", "--task", "before", "--config", configPath], { cwd: root, env: cliEnv({ MOSAIC_CONFIG: configPath, MOSAIC_AGENT_NAME: "launcher" }) });
assert.equal(launchResult.status, 0, launchResult.stderr);
const launched = JSON.parse(readFileSync(path, "utf8"));
assert.equal("taskSetBy" in launched, false, "launch --task does not attribute, even with the variable set");
const run = (args, env) => runCli(["seat", "task", "myseat", ...args, "--config", configPath], { cwd: root, env: cliEnv({ MOSAIC_CONFIG: configPath, ...env }) });
const read = () => JSON.parse(readFileSync(path, "utf8"));
let r = run(["one", "--by", "darkwing"], { MOSAIC_AGENT_NAME: "rocko" });
assert.equal(r.status, 0, r.stderr);
assert.match(r.stdout, /set by darkwing/);
assert.equal(read().taskSetBy, "darkwing");
assert.equal(read().task, "one");
assert.equal(read().startedAt, launched.startedAt);
r = run(["two"], { MOSAIC_AGENT_NAME: "rocko" });
assert.equal(r.status, 0, r.stderr);
assert.match(r.stdout, /set by rocko/);
assert.equal(read().taskSetBy, "rocko");
r = run(["three"], {});
assert.equal(r.status, 0, r.stderr);
assert.match(r.stdout, /set by unknown/);
assert.equal(read().taskSetBy, "unknown");
r = run(["four"], { MOSAIC_AGENT_NAME: "" });
assert.equal(r.status, 0, r.stderr);
assert.equal(read().taskSetBy, "unknown");
for (const key of Object.keys(launched)) {
if (key === "task" || key === "updatedAt") continue;
assert.deepEqual(read()[key], launched[key], `field ${key} changed unexpectedly`);
}
const frozen = readFileSync(path, "utf8");
r = run(["five", "--by", "<script>alert(1)</script>"], { MOSAIC_AGENT_NAME: "rocko" });
assert.equal(r.status, 4);
assert.match(r.stderr, /refused: --by/);
assert.equal(r.stderr.includes("<script>"), false, "the refusal does not echo the value");
assert.equal(readFileSync(path, "utf8"), frozen, "an invalid --by writes nothing");
r = run(["five", "--by", ""], {});
assert.equal(r.status, 4);
assert.equal(readFileSync(path, "utf8"), frozen);
r = runCli(["seat", "task", "myseat", "five", "--config", configPath, "--by"], { cwd: root, env: cliEnv({ MOSAIC_CONFIG: configPath }) });
assert.equal(r.status, 4);
assert.match(r.stderr, /missing value for --by/);
assert.equal(readFileSync(path, "utf8"), frozen);
r = run(["five"], { MOSAIC_AGENT_NAME: "not a name" });
assert.equal(r.status, 4);
assert.match(r.stderr, /MOSAIC_AGENT_NAME/);
assert.equal(r.stderr.includes("not a name"), false);
assert.equal(readFileSync(path, "utf8"), frozen, "an invalid environment value writes nothing");
r = run(["six", "--by", "explicit"], { MOSAIC_AGENT_NAME: "not a name" });
assert.equal(r.status, 0, "an explicit --by is the way past a bad environment value");
assert.equal(read().taskSetBy, "explicit");
assert.equal(read().task, "six");
});