build.patch againstd13b9300(brief blobf8d14d70, rev 630), candidate manifest, identity and mutant harnesses with results, gate summary. Co-Authored-By: Claude Opus 5.5 <[email protected]>
213 lines
11 KiB
Markdown
213 lines
11 KiB
Markdown
# Row 83 (#1576): Console service, the unit script takes --send, round 1
|
|
|
|
Owner: Dewey. Reviewers: Darkwing and Filbert, then Sage's gate. Brief:
|
|
`docs/plans/2026-10-12_console-service-send.md` § "The unit script takes
|
|
--send", blob `f8d14d70` (re-pinned at rev 630 for lead decision 102; first
|
|
pinned as `739bea66` at rev 627, briefed at rev 628). Lead decision 101
|
|
gives the reason. Base `d13b9300`. None of the candidate's paths, nor the
|
|
template, changed between `d13b9300` and `refactor` HEAD (`a1c5c8fc`) when
|
|
the packet was built.
|
|
|
|
`build.patch` is `git diff --cached --binary d13b9300 --` the four paths
|
|
below. Apply it with `git apply --index` to a detached worktree of the base;
|
|
`candidate-manifest.sha256` then checks 4/4 OK (checked on a fresh
|
|
worktree).
|
|
|
|
## What ships
|
|
|
|
- `render` and `install` take `--send`, a flag with no value. It is
|
|
accepted only with all three preview flags. Otherwise `serve_flags`
|
|
refuses before anything is written: exit 1, empty stdout, and on stderr
|
|
`webui-service: --send needs the preview mode (--public-host,
|
|
--auth-header and --allow-user)`, serve's own wording (cli.mjs:37).
|
|
`install` renders before `mkdir`, so a refusal creates no directory and
|
|
leaves an installed unit alone (tested).
|
|
- With `--send`, ExecStart ends `... --allow-user ID --send`. Nothing else
|
|
in the unit changes (tested line by line against the same render without
|
|
`--send`).
|
|
- Without `--send`, every render is the template with its four
|
|
placeholders filled, byte for byte (new test), and the base and
|
|
candidate scripts give the same stdout, stderr, status and installed
|
|
files on every argument list the base tests use (`identity.txt`).
|
|
- `uninstall` and `status` take no `--send`: it sets SERVE_SET like the
|
|
other serve flags, so both exit 4 (tested with a stand-in systemctl).
|
|
- `status` prints one new line when a unit is installed: `send: on
|
|
(--send; human messages to roles)` or `send: off (read-only)`. The brief
|
|
allowed this "if small"; it is five lines plus a comment. With no unit
|
|
installed there is no send line.
|
|
- `USAGE` and the header comment name `[--send]` inside the preview set.
|
|
README's service paragraph and TOOLS.md's "Console service" section say
|
|
the script takes `--send` only with the preview set (exit 1, nothing
|
|
written), that ExecStart then ends with `--send`, and that the Console
|
|
needs the system config at start (`--send needs the bus configured`,
|
|
exit 2, which the unit doesn't restart: `RestartPreventExitStatus=2` in
|
|
the template). README's "Message a role" `--send` paragraph gets one
|
|
sentence pointing at `scripts/webui-service.sh install` with `--send`.
|
|
- The start wording (lead decision 102). The script's header comment, its
|
|
install message, TOOLS.md's "Console service" and README's service
|
|
paragraph now say Jason starts and restarts the Console, and so may Mos
|
|
under decision 102, which accepts that sends from a Console Mos started
|
|
enter the trail as Jason (`human-cli`). Any other agent starting it,
|
|
even through systemd, still works around the human proof (decisions 62
|
|
and 94). The script still has no start, stop or restart verb. A test
|
|
checks the install message's wording.
|
|
|
|
The template (`packages/webui/systemd/mosaic-webui.service.in`) is
|
|
unchanged. `install` prints no new line; its `serve:` line already shows
|
|
the ExecStart, `--send` included. The install message's opening sentence
|
|
changed wording only (decision 102).
|
|
|
|
## Decisions and tradeoffs
|
|
|
|
- **Refusal order.** The `--send` check runs before the all-three check.
|
|
`--send` with one or two preview flags therefore gets the `--send`
|
|
message, not "all three or none". The brief asks for a message naming
|
|
the preview flags the way serve refuses, and serve checks the preview
|
|
set first. Both messages name the three flags. A partial preview set
|
|
without `--send` still gets "all three or none" (base test unchanged).
|
|
- **Status detection is anchored on the allowed user.** My first version
|
|
matched `^ExecStart=.* --send$`. The mutant `status-send-anywhere`
|
|
survived it, and that showed a real gap: `--allow-user` accepts the value
|
|
`--send` (its character set allows `-`, and serve's `USER` pattern
|
|
accepts it), so a read-only unit's ExecStart can end
|
|
`--allow-user --send`. The check is now
|
|
`^ExecStart=.* --allow-user [^ ][^ ]* --send$`. render always puts
|
|
`--send` right after the allowed user, so a sending unit ends with both
|
|
the allowed user and `--send`. A test installs both cases, read-only
|
|
`--allow-user --send` and sending `--allow-user --send --send`, and
|
|
checks status for each.
|
|
- **No config or bus check in the script** (out of scope per the brief).
|
|
A unit installed with `--send` on a host without the system config
|
|
installs fine and exits 2 at start; the docs say so.
|
|
|
|
## Files
|
|
|
|
- `scripts/webui-service.sh`: `SEND=0`, the `--send` case, the refusal
|
|
and the append in `serve_flags`, the status line, USAGE and header.
|
|
- `packages/webui/tests/service.test.mjs`: 5 new tests, 2 widened.
|
|
- `packages/webui/README.md`: the service paragraph, one sentence in
|
|
"Message a role".
|
|
- `docs/TOOLS.md`: the "Console service" FLAGS comment and prose.
|
|
|
|
## Tests
|
|
|
|
`packages/webui/tests/service.test.mjs`, 15 tests (10 base, 5 new). The
|
|
helper `filled(flags)` is the template with `@REPO@`, `@PATH@`, `@NODE@`
|
|
and `@FLAGS@` replaced, computed in the test the way the base script does
|
|
it.
|
|
|
|
- *without --send, render is the template with its placeholders filled,
|
|
byte for byte*: five flag combinations, from none to every flag.
|
|
- *render --send with the preview set ends ExecStart with --send and
|
|
changes nothing else*: four argument orders (`--send` first, last, in the
|
|
middle of the preview set, with `--port` and `--business`). Each equals
|
|
`filled(flags + ' --send')`, and against the same render without
|
|
`--send` exactly one line differs, the ExecStart, by ` --send`.
|
|
- *--send without the whole preview set is refused and writes nothing*:
|
|
`--send` alone, with `--port`, with `--business`, with each one of the
|
|
three preview flags, and with each two of the three. Each `render` gives
|
|
exit 1, empty stdout and serve's message. Each `install` into a fresh
|
|
`--dir` gives the same, and the directory is never created. An install
|
|
of `--send` with two preview flags over an installed unit leaves it byte
|
|
for byte, with no temp file and no systemctl call.
|
|
- *install --send into --dir with --no-reload writes the sending unit, and
|
|
status says whether it sends*: `written:`, the `serve:` line ending
|
|
`--send`, the file equal to `filled(...)`, mode 0644, no temp file;
|
|
status `send: on`; reinstall `unchanged:`; install without `--send`
|
|
writes the read-only unit and status says `send: off (read-only)`; the
|
|
odd allowed user `--send` case above; no `send:` line without a unit.
|
|
The only systemctl calls are status's reads. Status's `/healthz` goes to
|
|
a loopback port that was just closed, so it reaches no real Console.
|
|
- *uninstall and status take no --send*: exit 4 for `uninstall --send`
|
|
(with and without `--no-reload`) and `status --send`, against a stand-in
|
|
systemctl that records no call; the unit stays installed.
|
|
- Widened: the agent-marker test also renders `[...PREVIEW, '--send']`;
|
|
the usage test adds `render --send yes ...PREVIEW` (`--send` takes no
|
|
value); the install test checks the decision 102 start wording in the
|
|
install message.
|
|
|
|
Why the uninstall and status cases sit in their own test: in the usage
|
|
loop they run with the real `/usr/bin/systemctl` on PATH. A mutant where
|
|
`--send` doesn't set SERVE_SET would let `uninstall --send` reach a real
|
|
`systemctl --user daemon-reload`. With the stand-in, no mutant can.
|
|
|
|
## Byte identity (`identity.mjs`, `identity.txt`)
|
|
|
|
One scratch worktree of `d13b9300` holds the base script as
|
|
`scripts/webui-service-base.sh` and the candidate as
|
|
`scripts/webui-service.sh`, so REPO and the template are the same for
|
|
both. Each script runs the same 86 argument lists from a clean scratch:
|
|
every render the base tests make (the value and port refusals included),
|
|
the usage list, `--help`, and an install, reinstall, refused install,
|
|
install over, status, uninstall, uninstall and status sequence, all with
|
|
`--no-reload` and a stand-in systemctl.
|
|
|
|
Result: 69 identical, 17 expected differences, 0 unexpected. The 17 are
|
|
the usage text on 12 exit-4 cases plus `--help` (the FLAGS line names
|
|
`[--send]`), three installs whose message differs only in the decision 102
|
|
start wording (the base message's opening lines replaced by the
|
|
candidate's, then everything else identical, installed unit included),
|
|
and one status with a unit installed (the added `send: off (read-only)`
|
|
line, nothing else). A self-check: with the append made
|
|
unconditional, the same run reports 13 unexpected differences.
|
|
|
|
## Mutants (`mutants.py`, `mutants.txt`)
|
|
|
|
15 single-site mutants of `scripts/webui-service.sh`, each run against the
|
|
base tests (`d13b9300`'s `service.test.mjs`), the candidate tests and
|
|
`identity.mjs`. Baselines: all three pass on the unmutated candidate.
|
|
Rerun on the decision 102 candidate, 2026-10-12T03:53Z; same results as
|
|
the first run.
|
|
|
|
| mutant | base tests | candidate tests |
|
|
|---|---|---|
|
|
| send-no-preview-check | survived | killed |
|
|
| send-needs-any-preview | survived | killed |
|
|
| send-message-reworded | survived | killed |
|
|
| send-no-append | survived | killed |
|
|
| send-append-always | killed | killed |
|
|
| send-append-before-preview | survived | killed |
|
|
| send-default-on | killed | killed |
|
|
| send-no-serve-set | survived | killed |
|
|
| send-takes-value | survived | killed |
|
|
| send-flag-unknown | survived | killed |
|
|
| status-send-always-off | survived | killed |
|
|
| status-send-always-on | survived | killed |
|
|
| status-no-send-line | survived | killed |
|
|
| status-send-anywhere | survived | killed |
|
|
| status-send-suffix-only | survived | killed |
|
|
|
|
The candidate tests kill 15 of 15. The two the brief names,
|
|
`send-no-preview-check` and `send-no-append`, survive the base tests.
|
|
`send-append-always` and `send-default-on` are killed by the base tests
|
|
too, as a change to every render should be.
|
|
|
|
## Gate (my run on the candidate)
|
|
|
|
On the staged candidate in a worktree of `d13b9300`, run sequentially,
|
|
2026-10-12T03:54:20Z to 03:58:42Z (`gate-summary.txt`):
|
|
|
|
- `packages/webui`, `node --test 'tests/*.test.mjs'`: 81 tests, 81 pass,
|
|
rc=0.
|
|
- `scripts/test-auth.sh`, `test-conductor.sh`, `test-config.sh`,
|
|
`test-discord.sh`, `test-extension-package.sh`, `test-foundation.sh`,
|
|
`test-queue.sh`, `test-release.sh`, `test-task.sh`: all rc=0.
|
|
|
|
## For reviewers
|
|
|
|
- **Allowed user starting with `-`.** The base script and serve both accept
|
|
an allowed user like `--send` or `-x`. That isn't new here, and changing
|
|
it would change no-`--send` renders, which the brief rules out. The only
|
|
effect on this row was status detection, now anchored. If it should be
|
|
refused, that's a follow-up for the script and serve together.
|
|
- **The template's comment still says Jason starts it.**
|
|
`mosaic-webui.service.in` lines 6-9 say Jason starts it from a personal
|
|
shell and that an agent starting it works around the human proof. The
|
|
template isn't in this row's files and is rendered into every unit, so
|
|
changing it would break the byte identity the brief asks for. Bringing
|
|
it in line with decision 102 is a follow-up (a template change plus the
|
|
render tests that pin it).
|
|
- Nothing here starts, enables or restarts a unit, and no test reaches the
|
|
real systemd: every install and uninstall uses `--no-reload` or a
|
|
stand-in systemctl.
|