sage: Window A and B plans with mos-0846 U1, the 382 bus-exit finding, mos-0845 P19 comments (#1558)

U1: usage checks read total and byRun, since `mosaic usage --json` prints
no record list. W7 wants one new byRun entry for the chief run with
input > 0, output > 0 and unknownTurns 0.

Window B's last section: the D4 design can't work as ruled. A refused
PM launch exits 3 and the unit won't restart it (sage-1007).

The comment script and its record put the mos-0845 rulings on P19
379-382 (comments 273-276).
This commit is contained in:
jason.woltje committed 2026-10-19 12:51:52 -05:00
1 parent 6dbc673022
commit 855c9eb019
4 files changed
+116 -34

No files matched your search

@@ -0,0 +1,46 @@
// Sage, 2026-10-19: mos-0845 rulings as task comments on P19 379-382, with Sage's own key (bot user 13). The sync key
// reads each comment back. Comments only: no title, description, done, label or bucket change. Prints no secret.
// Usage: node comment-mos0845-rulings.mjs https://tasks.woltje.com SAGE_TOKEN_FILE SYNC_TOKEN_FILE OUT_JSON
import { readFileSync, writeFileSync, existsSync } from "node:fs";
const [ORIGIN, KEY, SYNC, OUT] = process.argv.slice(2);
if (!/^https:\/\/tasks\.woltje\.com$/.test(ORIGIN)) throw new Error("tasks.woltje.com only");
if (!OUT || existsSync(OUT)) throw new Error("OUT_JSON missing or exists; refusing");
const SIG = "Added by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
const COMMENTS = {
379: [
"mos-0845 D1: go on the one-registry design as a new queue row. Until it lands, the window plans read `threads --business mosaic-stack --json` and expect [] (agents/sage/work/window-plan/repin-5fa9cc8f2.md, 6dbc67302).",
],
380: [
"mos-0845 D2: a tester message to a role with nobody running is refused, not queued. That is this task's fix. The fix belongs in talk's tester path, before the message is stored, with a test that a tester talk to a role with no running instance exits non-zero and writes no message.",
"Message 02f0e5d6 from the 8e7ea89a1 window stays queued for pm as it is. Any store edit to it waits for Jason.",
],
381: [
"Source for the usage-unknown line, corrected. It is in the bus journal at 2026-10-19T17:29:00Z, not 17:23Z: event usage-unknown, run r8fba7e598156, instance chief, turn 21e204db-8f55-4348-8f13-c10f85e764a2, source @none, code baseline-unknown. Sage read it at 17:32Z with journalctl --user -u 'mosaic-bus@mosaic-stack' --since \"2026-10-19T17:20:00Z\". A bare --since 17:23:30 reads as CDT on dragon-lin (22:23:30Z) and finds nothing; --since \"2026-10-19 17:23:30 UTC\" counts 1. Sage's sage-1003 gave the smoke time, 17:23Z, as the line's time.",
"mos-0845 D3: go. In Window A, Jason adds \"usage-source\": [\"transcript\"] with the live 8e7ea89a1 setter right before activate, and the activate restart loads it. Condition: Darkwing's scratch --plan run for A uses a business file that already has usage-source on and proves both 5fa9cc8f2 and a rollback to 8e7ea89a1 load it.",
],
382: [
"mos-0845 D4: go on the gate change. stack-release.sh accepts one named harness-off refusal for launch.by in place of the launched line. Then Jason runs plugins set harness [\"claude-code\"], then a plain unit restart with --pm, then W6. Writing harness from the target copy before activate can't work, because plugins set goes through the live bus (c216f47db cli.mjs:572). The silent default is refused.",
"The tool change gets an independent review and its own scratch rehearsal, since the blob changes from 4b16e848. Window B stays at ca15d73e9. No window past c216f47db goes to Jason until this task has landed.",
],
};
const key = readFileSync(KEY, "utf8").trim(), sync = readFileSync(SYNC, "utf8").trim();
const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
async function api(method, path, body, auth) {
const r = await fetch(ORIGIN + path, { method, headers: { Authorization: `Bearer ${auth}`, "Content-Type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), redirect: "error" });
const t = await r.text(); let json = null; try { json = JSON.parse(t); } catch {}
return { status: r.status, json };
}
writeFileSync(OUT, "", { flag: "wx" });
const out = { at: new Date().toISOString(), comments: [] };
for (const [task, lines] of Object.entries(COMMENTS)) {
const text = [...lines, SIG].map((l) => `<p>${esc(l)}</p>`).join("");
const r = await api("PUT", `/api/v1/tasks/${task}/comments`, { comment: text }, key);
const rec = { task: Number(task), status: r.status, id: r.json?.id, code: r.json?.code, message: r.json?.message };
const back = await api("GET", `/api/v1/tasks/${task}/comments`, undefined, sync);
rec.readBack = back.status;
rec.found = Array.isArray(back.json) && back.json.some((c) => c.id === r.json?.id);
out.comments.push(rec);
if (!rec.found) break;
}
writeFileSync(OUT, JSON.stringify(out, null, 1) + "\n");
console.log(JSON.stringify(out));
@@ -0,0 +1,33 @@
{
"at": "2026-10-19T17:44:59.064Z",
"comments": [
{
"task": 379,
"status": 201,
"id": 273,
"readBack": 200,
"found": true
},
{
"task": 380,
"status": 201,
"id": 274,
"readBack": 200,
"found": true
},
{
"task": 381,
"status": 201,
"id": 275,
"readBack": 200,
"found": true
},
{
"task": 382,
"status": 201,
"id": 276,
"readBack": 200,
"found": true
}
]
}
@@ -91,7 +91,7 @@ takes the `revision` from a read made just before it.
| # | Who | Step |
|---|-----|------|
| W0 | Mos | `cd $REPO && scripts/stack-copy.sh copy 5fa9cc8f2c66b52408b652b59c3070f7210b44d0`. Note the full id it prints. Then P1 for NEW. |
| W1 | Jason, then Mos | PM-idle check. Jason: `mosaic agents --business mosaic-stack`; chief not `working`, pm not running. Mos: `mosaic launches list`. Nobody talks to the chief until W6 passes. Record `date -u +%FT%TZ` as the start stamp. Baseline reads, kept for W6: `$C_OLD names --business mosaic-stack --json` and `$C_OLD threads --business mosaic-stack --json` (both `[]` on 10-19), and the record count from `mosaic usage --business mosaic-stack --json`. |
| W1 | Jason, then Mos | PM-idle check. Jason: `mosaic agents --business mosaic-stack`; chief not `working`, pm not running. Mos: `mosaic launches list`. Nobody talks to the chief until W6 passes. Record `date -u +%FT%TZ` as the start stamp. Baseline reads, kept for W6: `$C_OLD names --business mosaic-stack --json` and `$C_OLD threads --business mosaic-stack --json` (both `[]` on 10-19), and `mosaic usage --business mosaic-stack --json` saved whole, for its `total` and `byRun` (U1, mos-0846). |
| W2 | Jason | Usage source, OLD's setter. `$C_OLD plugins --business mosaic-stack --json`; note `revision`. Write PATCH as `{"revision": <that revision>, "plugins": {"usage-source": ["transcript"]}}`, then `$C_OLD plugins set --file PATCH --business mosaic-stack`. Read again: `usage-source` is `["transcript"]` and no other kind is set. A refusal ends the window with nothing stopped and nothing to undo. |
| W2b | Mos | `node $P/business-check.mjs 8e7ea89a1e86447d26ec335e4b138acfd5130cbc` and the same for NEW, on the patched file. Both LOAD_OK. A REFUSED stops the window; undo W2 as below. |
| W3 | Mos | `scripts/stack-release.sh activate 5fa9cc8f2c66b52408b652b59c3070f7210b44d0 mosaic-stack --plan`. Writes nothing. Its from, to, store schema, target schema, migration and needs lines must match P3's scratch output: from 8e7ea89a1, to 5fa9cc8f2, store schema 3h read from the store the running bus holds, target 3h, no migration step, no `--migrate` need, 78 commits. The bus, Console and CLI lines carry the pointer's flags; beyond those, only copy paths differ. Any other difference stops the window before W5 and goes to Mos. |
@@ -118,7 +118,7 @@ $C_NEW threads --business mosaic-stack --json # rows 128/129: []
mosaic project list --json # exit 0
mosaic limits --business mosaic-stack --json # row 125: exit 0
mosaic business instances mosaic-stack --json # row 165: the file's six instances, nothing added
mosaic usage --business mosaic-stack --json # exit 0, same record count as W1
mosaic usage --business mosaic-stack --json # total and byRun equal W1's, field for field
mosaic launches list # one running chief from this start
mosaic agents --business mosaic-stack # pm not running
```
@@ -134,11 +134,17 @@ wrote a name during the window; stop and report.
```
mosaic talk chief "[mos test] re-pin 5fa9cc8f2: reply with one line, no staffing request" --tester
mosaic usage --business mosaic-stack --json # one new record for that turn, source transcript, status known
mosaic usage --business mosaic-stack --json # one new byRun entry, this start's chief run: input > 0, output > 0, unknownTurns 0
```
The `usage` read is F4's acceptance. A new record with `status` `unknown` goes to
Mos with its code; it doesn't roll the window back by itself.
The `usage` read is F4's acceptance. `mosaic usage --json` prints no record list,
only `total` and the groups `byRun`, `byInstance`, `byModel`, `byProvider` and
`byAccount` (5fa9cc8f2 `packages/cli/src/usage.mjs`), so the check reads the new
`byRun` entry. A turn counts as known only when the transcript added usage
(5fa9cc8f2 `packages/bus/src/usage.mjs:34` returns `no-new-usage` otherwise), so
nonzero input and output with `unknownTurns` 0 prove the transcript source works.
Any other result goes to Mos with the journal's `usage-unknown` code; it doesn't
roll the window back by itself.
There is no pm smoke. pm isn't running, and a tester message to it waits for a
claim nobody makes (F3). The 8e7ea89a1 window's message `02f0e5d6` is still
+26 -29
View File
@@ -49,7 +49,7 @@ after the window, with a `launch.limits.tokens.daily` entry, on Mos's go.
| # | Who | Step |
|---|-----|------|
| W0 | Mos | `cd $REPO && scripts/stack-copy.sh copy ca15d73e9fdcdcf66a10f86cdedeb2d6a08f2b00`. Note the full id. Then P1 for NEW. |
| W1 | Jason, then Mos | PM-idle check as Window A. Record the start stamp. Baseline reads: `$C_OLD names --business mosaic-stack --json`, `$C_OLD threads --business mosaic-stack --json` and the record count from `mosaic usage --business mosaic-stack --json`. Nobody talks to the chief until W6 passes, so no turn writes a usage record (D3). |
| W1 | Jason, then Mos | PM-idle check as Window A. Record the start stamp. Baseline reads: `$C_OLD names --business mosaic-stack --json`, `$C_OLD threads --business mosaic-stack --json` and `mosaic usage --business mosaic-stack --json` saved whole, for its `total` and `byRun` (U1, mos-0846). Nobody talks to the chief until W6 passes, so no turn writes a usage record (D3). |
| W2 | Mos | `scripts/stack-release.sh status mosaic-stack`: pointer on 5fa9cc8f2, schema 3h, last line ok. |
| W3 | Mos | `scripts/stack-release.sh activate ca15d73e9fdcdcf66a10f86cdedeb2d6a08f2b00 mosaic-stack --plan`. It must match P3 on from 5fa9cc8f2, to ca15d73e9, store schema 3h read from the store the running bus holds, target 3i, one migration step 3h to 3i, needs `--migrate`, needs Jason present, 8 commits. Any other difference stops the window before W5. |
| W4 | Mos | Drop-ins, as Window A. |
@@ -66,21 +66,29 @@ $C_NEW plugins --business mosaic-stack --json # unchanged from Wi
$C_NEW names --business mosaic-stack --json # same as W1
$C_NEW threads --business mosaic-stack --json # same as W1 ([] unless Chat was used after A)
mosaic limits --business mosaic-stack --json # exit 0
mosaic usage --business mosaic-stack --json # exit 0, every record from before still listed
mosaic usage --business mosaic-stack --json # total and byRun equal W1's, field for field
mosaic launches list # one running chief from this start
mosaic agents --business mosaic-stack # pm not running
```
The `usage` read shows that the 3i migration kept every usage record. The count
must equal W1's.
The `usage` read shows that the 3i migration kept the usage records. `mosaic usage
--json` prints no record list, only `total` and the groups `byRun`, `byInstance`,
`byModel`, `byProvider` and `byAccount` (ca15d73e9 `packages/cli/src/usage.mjs`,
the same blob as 5fa9cc8f2's), so `total` and `byRun` must equal W1's field for
field.
### W7
```
mosaic talk chief "[mos test] re-pin ca15d73e9: reply with one line, no staffing request" --tester
mosaic usage --business mosaic-stack --json # one new known record, source transcript
mosaic usage --business mosaic-stack --json # one new byRun entry, this start's chief run: input > 0, output > 0, unknownTurns 0
```
A turn counts as known only when the transcript added usage (ca15d73e9
`packages/bus/src/usage.mjs`, the `no-new-usage` return), so nonzero input and
output with `unknownTurns` 0 prove the transcript source still works under 3i. ca15d73e9
also writes an account on new rows, so W7 doesn't compare `byAccount` with W1.
No pm smoke (F3, P19 380). Jason's browser check: Settings shows Token limits
with no daily quota entry. Nobody presses Save.
@@ -111,7 +119,9 @@ stamp leave the live store.
post-attempt copy the run keeps still holds them, and nobody opens or changes
it without Jason.
W1's idle rule and W7's single turn keep the usage count at one record or none.
W1's idle rule and W7's single turn keep the `usage_records` rows after the stamp
to one turn's begin and end rows, or none. This count is read from the store, not
from `mosaic usage`.
`mosaic name` stays out of the window (mos-0641), so `instance_names` should
have none.
@@ -135,29 +145,16 @@ target copy before activate doesn't help either: it goes through the live bus
(c216f47db `cli.mjs:572`), which runs the old code. A silent default for a
missing `harness` kind is refused (D4).
The fix, 382 (D4). `stack-release.sh` accepts one named `harness-off` refusal for
`launch.by` in place of the `launched` line, for a target that has the harness
kind. It's a tool change, so it gets an independent review and its own scratch
rehearsal; the blob changes from 4b16e848.
The steps, once 382 has landed:
1. `activate <target> mosaic-stack --pm`. The target's schema decides
`--migrate`. If Window B is live at 3i, c216f47db doesn't change the schema
(`SCHEMA_VERSION = '3i'` on 894ce3f37), so there's no migration; Jason is
present anyway for step 2. If B isn't live, the target carries 3h to 3i and
needs `--migrate` with Jason (P19 371).
2. Jason: `$C_NEW plugins --business mosaic-stack --json` for the revision, then
PATCH `{"revision": <that revision>, "plugins": {"harness": ["claude-code"]}}`
with `$C_NEW plugins set --file PATCH --business mosaic-stack`. Read again:
`harness` is `["claude-code"]` and the other kinds are unchanged.
3. Mos: a plain restart of `[email protected]`, still `--pm`. The
chief launches. Check exactly one `launched` line for that start.
4. The W6 reads, then the chief tester smoke.
5. One managed coder session with its manifest attached (row 65's landing
session: module, route, counted model, thinking).
Mos puts step 2 to Jason when that window opens.
The fix, 382. mos-0845 D4 ruled that the gate accepts one named `harness-off`
refusal for `launch.by` in place of the `launched` line, then Jason's plugins
set, then a plain restart. That can't work as ruled, and Sage reported it in
sage-1007. A refused PM launch takes the bus down: c216f47db
`packages/cli/src/launcher.mjs:657` throws `PM launch refused: ...` with exit 3,
`packages/cli/src/cli.mjs:507-509` closes the host and rethrows, and the unit's
`RestartPreventExitStatus=2 3 4` (`packages/cli/systemd/mosaic-bus.service.in:33`)
keeps it down. The gate's unit and status checks fail before `pm_launched`, and
there is no live bus for Jason's plugins set. The steps wait for Mos's
ruling on sage-1007. The earlier step list is withdrawn until then.
## What Sage ran for this plan