plans: D1 brief carries decision 96's four conditions and records the claude pin and Console flags in the pointer (Mos mos-0716, Darkwing survey)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -77,7 +77,12 @@ start has no gate that puts the old copy back.
|
||||
|
||||
1. A pointer and a log, the same shape as `release.sh`:
|
||||
- `<dataRoot>/state/stack-active.json` holds `{ copy, business, pm,
|
||||
schema, activation, at }`. It is written to a temp file and renamed.
|
||||
claude, console, schema, activation, at }`. It is written to a temp
|
||||
file and renamed. `claude` is the bus unit's `--claude` pin, and
|
||||
`console` is the Console unit's flag list (`--port`, `--business`,
|
||||
`--board`, `--send` and the public-host, auth-header and allow-user
|
||||
set). `webui-service.sh` saves its flags nowhere else, so the
|
||||
pointer is their record (Darkwing's survey, 2026-10-18).
|
||||
- `<dataRoot>/state/stack-activation-log.jsonl` is append-only. Each
|
||||
line has `at`, `op`, `from`, `to`, `backup`, `result` and, on a
|
||||
refusal or a failed gate, `code`. `op` is one of `adopt`,
|
||||
@@ -89,7 +94,10 @@ start has no gate that puts the old copy back.
|
||||
passes and the bus unit's copy is the Console's and the wrapper's.
|
||||
The live stack is already on one copy (52f35e7a0), so no mixed-setup
|
||||
path is needed. A pointer that already exists refuses
|
||||
`already-adopted`.
|
||||
`already-adopted`. `adopt` reads `claude` and `console` from the
|
||||
effective units with `systemctl --user show -p ExecStart -p
|
||||
Environment`, the way `bus-service.sh status` reads `--pm`
|
||||
(:200-209).
|
||||
3. `activate ID BUSINESS [--pm]` moves the stack from the pointer's copy
|
||||
to copy `ID`. It refuses, with a code, a log line and no change, when
|
||||
any of these holds:
|
||||
@@ -101,7 +109,11 @@ start has no gate that puts the old copy back.
|
||||
- a bus drop-in overrides `ExecStart` or `WorkingDirectory`,
|
||||
`drop-in-override`. It is named, and the operator removes it as in
|
||||
TOOLS.md step 3;
|
||||
- the target is already the pointer's copy, `already-active`.
|
||||
- the target is already the pointer's copy, `already-active`;
|
||||
- the effective units' `--pm`, `--claude` or Console flags differ from
|
||||
the pointer's, `unit-flags-drift`. The difference is printed. A hand
|
||||
edit between runs is never carried forward or reverted without
|
||||
anyone seeing it; the operator settles it first.
|
||||
4. The order inside `activate` is as follows. Each step is logged, and a
|
||||
failure at any step goes to item 6.
|
||||
1. Capture the rollback set under
|
||||
@@ -116,7 +128,8 @@ start has no gate that puts the old copy back.
|
||||
owner picks the read, for example a read-only SQLite open of the
|
||||
version the store records, and the packet names it. If the version
|
||||
is the new copy's `SCHEMA_VERSION`, there's no backup. If it's
|
||||
older, back up the stopped store to
|
||||
older and the run has no `--migrate`, refuse `migration-needs-flag`
|
||||
through item 6. With `--migrate`, back up the stopped store to
|
||||
`<dataRoot>/backups/stack/<activation>/` (`backup.sh`: 0700, sums,
|
||||
a source and copy comparison, the stopped check again after the
|
||||
copy), then run the new copy's `migrate-schema.mjs`. If it's newer
|
||||
@@ -124,9 +137,10 @@ start has no gate that puts the old copy back.
|
||||
`store-newer`. The stack is stopped by then, so the refusal goes
|
||||
through item 6 and starts the old stack again.
|
||||
4. Install the bus unit with `bus-service.sh install --copy ID`,
|
||||
keeping `--pm` and the `--claude` pin the pointer recorded. Then
|
||||
install the Console with `webui-service.sh install --copy ID`,
|
||||
keeping its saved flags. Then switch the wrapper with
|
||||
with exactly the `--pm` and `--claude` pin the pointer recorded.
|
||||
Then install the Console with `webui-service.sh install --copy ID`
|
||||
with exactly the pointer's `console` flags. Then switch the wrapper
|
||||
with
|
||||
`stack-copy.sh wrapper ID`.
|
||||
5. Start the bus, then the Console.
|
||||
5. The health gate runs after the start and passes only when all of
|
||||
@@ -160,33 +174,56 @@ start has no gate that puts the old copy back.
|
||||
`schema-differs` unless `--restore ACTIVATION` names the backup taken
|
||||
when the store was migrated. With `--restore`, it prints the
|
||||
post-attempt path it keeps and how many bus events were written after
|
||||
the backup's stamp, then restores.
|
||||
8. `status BUSINESS` prints the pointer, the last five log lines, the
|
||||
the backup's stamp, then restores. If that count is above zero, it
|
||||
refuses `post-backup-events` unless `--events N` repeats the printed
|
||||
count.
|
||||
8. `activate ID BUSINESS --plan` and `rollback BUSINESS --plan` print
|
||||
the target, whether a migration or a restore is expected (from the
|
||||
pointer's `schema` and the target copy's `SCHEMA_VERSION`, with no
|
||||
store read) and the flags that would be installed. They change
|
||||
nothing and write no log line, so the window knows beforehand
|
||||
whether Jason must be present.
|
||||
9. `status BUSINESS` prints the pointer, the last five log lines, the
|
||||
live units' copies, the result of `stack-copy.sh check`, `bus status`
|
||||
and the drift from `refactor`. It only reads.
|
||||
9. Who runs it. `adopt`, `activate` and `rollback` stop and start the
|
||||
live units, so they are run by Jason or Mos only, and each run is a
|
||||
live step that needs Mos's go, as TOOLS.md says today. Decisions 94
|
||||
and 102 still decide who starts the Console. `webui-service.sh`
|
||||
keeps having no start or stop verb (:50). The release script is the
|
||||
one path that stops and starts, and its header comment says who may
|
||||
run it. `status` is open to every seat.
|
||||
10. Who runs it. Decision 96 covers the script stopping and starting
|
||||
the live units under four conditions (Mos, mos-0716), and the
|
||||
header comment states all four:
|
||||
- every run of `adopt`, `activate` or `rollback` happens on Mos's
|
||||
go, and Jason or Mos runs it;
|
||||
- a run that migrates the store, an `activate --migrate`, happens
|
||||
with Jason present;
|
||||
- a `rollback --restore` with events written after the backup waits
|
||||
for Jason, which is why it needs `--events N`;
|
||||
- the script never prunes backups, rollback sets, post-attempt
|
||||
directories or copies.
|
||||
|
||||
Tests run with a stand-in `systemctl` on `PATH`, temporary
|
||||
Decisions 94 and 102 still decide who starts the Console.
|
||||
`webui-service.sh` keeps having no start or stop verb (:50). The
|
||||
release script is the one path that stops and starts. `status` and
|
||||
`--plan` are open to every seat.
|
||||
|
||||
Tests run with a stand-in `systemctl` and `systemd-analyze` on `PATH`
|
||||
(`install_guard` also calls `systemd-analyze --user unit-paths`), temporary
|
||||
`XDG_CONFIG_HOME` and `XDG_DATA_HOME`, a temporary data root, and fake
|
||||
copies whose `scripts/mosaic` and Console are small stubs, as
|
||||
`packages/cli/tests/stack-copy.test.mjs` and
|
||||
`packages/webui/tests/service.test.mjs` do. The cases:
|
||||
|
||||
- `adopt` writes the pointer and one log line only when the check passes.
|
||||
- `adopt` writes the pointer and one log line only when the check passes,
|
||||
with `claude` and `console` read from the stand-in's `show` output.
|
||||
A second `adopt` refuses.
|
||||
- `activate` installs exactly the pointer's `--pm`, `--claude` and
|
||||
Console flags, and a stand-in unit whose flags differ refuses
|
||||
`unit-flags-drift` with no change.
|
||||
- Each refusal in item 3 leaves the units, the wrapper, the pointer and
|
||||
the store unchanged, and it writes one log line with its code.
|
||||
- An `activate` with no schema change: the stand-in sees the stops, the
|
||||
installs and the starts in that order. The pointer names the new
|
||||
copy, and no backup directory exists.
|
||||
- An `activate` with a schema change makes the backup before the
|
||||
migration. A fixture migration that fails restores the backup and
|
||||
- An `activate` with a schema change and no `--migrate` refuses
|
||||
`migration-needs-flag` and starts the old stack. With `--migrate` it
|
||||
makes the backup before the migration. A fixture migration that fails restores the backup and
|
||||
starts the old stack. The post-attempt directory exists, and the
|
||||
restored files match the backup's sums.
|
||||
- Each check in item 5, failing on its own, rolls back. The pointer is
|
||||
@@ -195,10 +232,14 @@ copies whose `scripts/mosaic` and Console are small stubs, as
|
||||
- A failing rollback gate stops with `rollback-failed` and starts
|
||||
nothing more.
|
||||
- `rollback` finds the previous copy from the log, refuses
|
||||
`schema-differs` without `--restore`, and restores with it.
|
||||
`schema-differs` without `--restore`, and restores with it. With
|
||||
post-backup events, `--restore` without a matching `--events N`
|
||||
refuses `post-backup-events`.
|
||||
- `--plan` reports the expected migration or restore and the flags, and
|
||||
leaves the units, pointer, log and store unchanged.
|
||||
- The store is never opened for writing outside `migrate-schema.mjs` and
|
||||
the restore, and nothing under `backups/` or `bus.post-attempt-*` is
|
||||
removed.
|
||||
the restore, and nothing under `backups/`, `state/stack-rollback/`,
|
||||
`bus.post-attempt-*` or the copies directory is removed.
|
||||
|
||||
Mutants: one per behavior above, with the killing test in the packet.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user