Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e8218a2ed | ||
|
|
8ddba89b74 | ||
|
|
3227614cd7 | ||
|
|
3bce852d5d | ||
|
|
541dee2b75 |
No files matched your search
@@ -5387,5 +5387,3 @@ Gander: after Duckworth-0100 design approval with C1-C5, prepared the two host-s
|
||||
Row 299 (573, #1806, Gander, Filbert): before, the P10 band test timed a fault run minus a separate baseline run, and a loaded whole-suite run went red. Mos approved direct timing from host /proc/uptime stamps with ambient load only (mos-1409). After: rebased onto 80793d824 as ffa93b054 (range-diff 3/3 =, manifest 277ace0b unchanged). Gate 07:26Z-07:50Z: case1 whole 3x 53/0/0, cli whole 917/0/0 (59 files, load 1.54-7.17), P10 inner 2.27 s, outer 4.01 s, M1-M6 killed. M4's planned guard return then exact outer-reason failure counts as its kill (sage-3271, mos-1426). Filbert APPROVE c31084 rev 3485, N1 M1 margin 0.02 s. 299 LANDED ffb2fedfb 08:03Z, done rev 3487, #1806 closed c31087; queue commit 8a35ffadb (revs 3474-3487). Row 303: Duckworth APPROVE c31079 rev 3480 with C1, the whole-file gate. Rows 219 (bfa421b6c) and 295 r2 (b16cef1d0) rebases: Dewey static clean. Corrections: Launchpad and Gander have no token, and the CLI refuses another seat's token file, so I posted both requests as sage (c31082, c31083). My sage-3265 wording led Duckworth to poll queue show into Gander's slot (07:20Z-07:26Z); I ruled it ambient load (sage-3274).
|
||||
2026-10-23T10:48:40Z | Sage, rows 302, 295 and 219 landings, the Docker pool diagnostic, rows for Vikunja 590 and 591 | Before: refactor 1ac655005. 302 (#1809, Gizmoduck, Dewey) LANDED 3ed9fd754 08:49Z: 7 commits onto 1ac655005, range-diff all =, tree = gated merge 783602e06; queue commit 07802dc57 (revs 3488-3494). Row 219's gate went 11/3 in test-release.sh: release activate's health check failed because Docker could not create sage-diag1437_default, since all predefined address pools were used up. Under mos-1437 I reproduced it on clean 07802dc57 (11/3, the same stderr). I then removed 18 unused gate _default networks, and the rerun went 14/0 with the run-task marker ok. Mos accepted the removal and ruled that a probe that can create something waits for the go and a removal waits for the report (mos-1438). 295 (#1801, Morgana, Dewey) round 2 gate on d68b4300d (manifest e94c9aeb) was green. It LANDED 2efd127ce 10:10Z: 9 commits onto 07802dc57, HEAD~1 tree = gated a86592ffc. Done rev 3502, #1801 c31105, P19 414 c911. 219 (#1720, Rocko, Dewey): the restart on the post-295 merge 054da642f (manifest 4a2271dd, my mos-1439 call) passed node 2523/0/2 and shells 449/0, with 24 mutants killed. It LANDED 5fdfd7275 10:40Z (8 row commits plus packet-only evidence, tree e86a84a85 = gated). Done rev 3509, #1720 c31110, P19 416 c913. Queue commit 90633c864 (revs 3495-3510). Brief docs/plans/2026-10-23_gate-env-rows.md names rows for 590 (claude-session slug) and 591 (compose network cleanup), and DEFERRED.md gets 219 N1 (U6). Row 272 (Huey) conflicts with 5fdfd7275 in code, so it moves back to in-progress for a rebase. Its new fallback is bounded to a session.list access-refused on an omitted-session route (sage-3357). Corrections: my network create probe ran before Mos's go, and the removal ran before the report. My first slot-order line put the diag start at 09:44Z; it was about 09:41Z. My 219 push piped its output through grep, but the after-fetch confirmed origin. Queue commit 90633c864 also carries Huey's rev 3510 (272 back to in-progress), and its message names only 3495-3509.
|
||||
|
||||
|
||||
2026-10-23T11:03:46Z | Gyro Vikunja571 mos-1444 PRD d8 follow-on | Branch gyro/editor-571-d8 from origin/refactor c16e943b9. Both designs now keep library.convert outside ACTIONS/ROUTED and broker processing, retain REQ-WAIT-1/hard-wait test unchanged, constrain unmarked story eligibility to mapped book/playground scope, and add whole-host pre-import restore recovery from remote import manifests plus the Gitea archive commit. Lookups refuse until one current version is proven; VM1012 restore needs Jason present under Q185. W7 no longer owns hard-waits.test.mjs. Canonical queue next gyro returned nothing; direct Mos assignment governs. Static diff, exact replacement and append-only checks pass. No code, tests, build, browser, private-file or live action. Fenton re-check requested after authorized branch push.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Row 305 (#1812, Vikunja 591): shell suites remove the compose network they create
|
||||
|
||||
Owner Gizmoduck. Reviewer Filbert. Gate owner Sage. Brief:
|
||||
docs/plans/2026-10-23_gate-env-rows.md, "Brief: shell suites remove the compose network they create
|
||||
(Vikunja 591)", at c16e943b9. Base c16e943b9. Mos approved the change in mos-1442 point 2. Mos approved
|
||||
the two new checks in mos-1445 under mos-1272, adding the presence half.
|
||||
|
||||
## The leak, as the code has it at c16e943b9
|
||||
|
||||
- `packages/processing-control/src/containers.mjs:16-19`. `containerArgs` builds
|
||||
`docker compose run --rm ...`. `--rm` removes the container. The project's `<project>_default`
|
||||
network stays.
|
||||
- `compose.yaml` has no top-level `name:`, so compose names the project after the checkout
|
||||
directory. Every gate worktree left one network. By 10-23 they had used up Docker's address pools.
|
||||
|
||||
## Does COMPOSE_PROJECT_NAME reach compose? Yes, on every path the two suites take
|
||||
|
||||
- Task path. `scripts/run-task.sh:29` execs `node scripts/mosaic-task.mjs`. Nothing scrubs the env
|
||||
before that: `scripts/common.sh` has no `env -i`, no `unset` and no COMPOSE. `mosaic-task.mjs:326`
|
||||
sets `spawnEnv = { ...process.env }`, `:405` passes `env: spawnEnv` to `runContainer`, and
|
||||
`containers.mjs:25` passes those options to `spawnSync('docker', ...)`.
|
||||
- test-release. `release.sh activate` calls `health_check`, and `health_check` calls `run-task.sh`
|
||||
at `:54`, which is the task path above. `env MOSAIC_MOCK_RESPONSE=...` adds to the env and keeps
|
||||
the rest. The suite calls only `status`, `activate` and `rollback`, so `release.sh:122`
|
||||
`compose build` is off its path.
|
||||
- test-task seat cases (`:240`, `:315-351`). `agent.sh:209` execs
|
||||
`packages/processing-control/src/container-cli.mjs`, and `container-cli.mjs:16` calls
|
||||
`runContainer` with `env: process.env`.
|
||||
- `build.sh:13`, `release.sh:122` and `verify.sh:40` also run compose. Neither suite calls them.
|
||||
|
||||
## Change (scripts/test-release.sh, scripts/test-task.sh only)
|
||||
|
||||
- After `SANDBOX="$(mktemp -d)"`, export
|
||||
`COMPOSE_PROJECT_NAME=mosaic-test-<release|task>-<id>`. `<id>` is the sandbox name after its last
|
||||
dot, lowercased, alphanumeric only.
|
||||
- `remove_compose_network` runs `docker network rm "${COMPOSE_PROJECT_NAME}_default"`:
|
||||
- If there's no docker binary, it returns 0.
|
||||
- If the error says `not found` or `No such network`, it returns 0.
|
||||
- On any other failure it prints one stderr line naming the network, then returns 0. That
|
||||
includes a daemon that is down. Sage kept that line in sage-3367 (a).
|
||||
- Each existing EXIT trap keeps everything it did and gains `; remove_compose_network` at the end.
|
||||
The trap's own exit status doesn't change the script's.
|
||||
- One new check per suite, just before the summary. That is after the last Docker step whether or
|
||||
not the live cases ran. Both halves sit inside a `docker info` branch:
|
||||
- the network is present under the run's project name before the explicit
|
||||
`remove_compose_network` (this proves the export reached compose);
|
||||
- after the remove, it is absent.
|
||||
|
||||
A failing `docker network ls` fails the check. Without the daemon, the check prints a skip line.
|
||||
- No `docker compose down`, and no other network is touched. No product file changes.
|
||||
|
||||
Commits: 541dee2b7 (draft), 3bce852d5 (presence half, mos-1445).
|
||||
|
||||
## Gate (Sage's slot, in a gap)
|
||||
|
||||
- Before the first run, run `docker network rm` on a name that was never created and record the
|
||||
daemon's exact wording (sage-3367 b). If the wording matches neither pattern, stop and report to
|
||||
Sage.
|
||||
- Each suite runs whole from a gate worktree, under `timeout -k 10 900`. That is far more than
|
||||
3x the row 302 gate's walls: test-release 3 s, test-task 16 s (mos-1275).
|
||||
- TMPDIR comes from `mktemp -d /mnt/storage/scratch/tmp/gXXX`.
|
||||
- Before and after each run, record `docker network ls` filtered to `mosaic-test-`. The run's
|
||||
network must be absent after.
|
||||
- Grep `^skip` and name every skip.
|
||||
- A run killed by the timeout's SIGKILL skips the EXIT trap and leaks its one network. The name is
|
||||
per-run under `mosaic-test-`, so the gate's after-listing finds it and removes it by its exact name
|
||||
(Filbert N1; no code change).
|
||||
- If `docker info` works but there is no network to find, that's a first-run red. It goes to Sage
|
||||
for Mos, unfixed (mos-1445).
|
||||
|
||||
## Mutants (mos-1445)
|
||||
|
||||
- (a) Drop the export. The new check must go red, because compose uses the directory's project and
|
||||
nothing exists under the run's name.
|
||||
- (b) Make the function's `docker network rm` a no-op. The new check must go red, because the
|
||||
network is still present after the remove.
|
||||
- (c) Drop `remove_compose_network` from the trap. This one is a known survivor: the explicit call
|
||||
covers the normal path, and the trap covers early exits.
|
||||
|
||||
Each mutant runs on an isolated copy of the file. Restores are checked by sha256. After each mutant, the network it
|
||||
leaves is removed by its exact name (mos-1438). Mutant (a) leaves the worktree directory's
|
||||
`<dir>_default`, and mutant (b) leaves the run's `${COMPOSE_PROJECT_NAME}_default`.
|
||||
@@ -0,0 +1,88 @@
|
||||
start 2026-10-23T11:14:01Z HEAD 8ddba89b7 refactor b99ca86b9 docker 29.7.2
|
||||
== wording
|
||||
rc=1 stderr: Error response from daemon: network mosaic-test-absent-46829331_default not found
|
||||
exit status 1
|
||||
== green
|
||||
TMPDIR /mnt/storage/scratch/tmp/gIj4
|
||||
nets[before test-task]:
|
||||
test-task rc=0 wall 16 s :: selftest: 92 passed, 0 failed
|
||||
OK compose network made under the run's project and removed after the run
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
nets[after test-task]:
|
||||
TMPDIR /mnt/storage/scratch/tmp/gDYF
|
||||
nets[before test-release]:
|
||||
test-release rc=0 wall 4 s :: selftest: 15 passed, 0 failed
|
||||
OK compose network made under the run's project and removed after the run
|
||||
nets[after test-release]:
|
||||
== mutants
|
||||
Ma scripts/test-task.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/g6SN
|
||||
nets[before Ma-task]:
|
||||
Ma-task rc=1 wall 16 s :: selftest: 91 passed, 1 failed
|
||||
FAIL compose network made under the run's project and removed after the run
|
||||
red: FAIL compose network made under the run's project and removed after the run
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
nets[after Ma-task]: gizmo-305_default
|
||||
restore ok scripts/test-task.sh
|
||||
Ma-task KILLED
|
||||
cleaned gizmo-305_default
|
||||
nets[after cleanup Ma-task]:
|
||||
Ma scripts/test-release.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/g48Q
|
||||
nets[before Ma-release]:
|
||||
Ma-release rc=1 wall 3 s :: selftest: 14 passed, 1 failed
|
||||
FAIL compose network made under the run's project and removed after the run
|
||||
red: FAIL compose network made under the run's project and removed after the run
|
||||
nets[after Ma-release]: gizmo-305_default
|
||||
restore ok scripts/test-release.sh
|
||||
Ma-release KILLED
|
||||
cleaned gizmo-305_default
|
||||
nets[after cleanup Ma-release]:
|
||||
Mb scripts/test-task.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/gcm1
|
||||
nets[before Mb-task]:
|
||||
Mb-task rc=1 wall 15 s :: selftest: 91 passed, 1 failed
|
||||
FAIL compose network made under the run's project and removed after the run
|
||||
red: FAIL compose network made under the run's project and removed after the run
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
nets[after Mb-task]: mosaic-test-task-pf33rz8tic_default
|
||||
restore ok scripts/test-task.sh
|
||||
Mb-task KILLED
|
||||
cleaned mosaic-test-task-pf33rz8tic_default
|
||||
nets[after cleanup Mb-task]:
|
||||
Mb scripts/test-release.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/gSxg
|
||||
nets[before Mb-release]:
|
||||
Mb-release rc=1 wall 3 s :: selftest: 14 passed, 1 failed
|
||||
FAIL compose network made under the run's project and removed after the run
|
||||
red: FAIL compose network made under the run's project and removed after the run
|
||||
nets[after Mb-release]: mosaic-test-release-db4p70csnf_default
|
||||
restore ok scripts/test-release.sh
|
||||
Mb-release KILLED
|
||||
cleaned mosaic-test-release-db4p70csnf_default
|
||||
nets[after cleanup Mb-release]:
|
||||
Mc scripts/test-task.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/g6WJ
|
||||
nets[before Mc-task]:
|
||||
Mc-task rc=0 wall 16 s :: selftest: 92 passed, 0 failed
|
||||
OK compose network made under the run's project and removed after the run
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
skip: skip live provider cases (row 244: no provider call in the gate)
|
||||
nets[after Mc-task]:
|
||||
restore ok scripts/test-task.sh
|
||||
Mc-task survived (known)
|
||||
nets[after cleanup Mc-task]:
|
||||
Mc scripts/test-release.sh | 2 +-
|
||||
TMPDIR /mnt/storage/scratch/tmp/g2jz
|
||||
nets[before Mc-release]:
|
||||
Mc-release rc=0 wall 3 s :: selftest: 15 passed, 0 failed
|
||||
OK compose network made under the run's project and removed after the run
|
||||
nets[after Mc-release]:
|
||||
restore ok scripts/test-release.sh
|
||||
Mc-release survived (known)
|
||||
nets[after cleanup Mc-release]:
|
||||
tree clean after mutants
|
||||
end 2026-10-23T11:15:17Z
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# Row 305 gate (sage-3374): wording, both suites whole, mutants a/b/c with exact-name cleanup.
|
||||
set -uo pipefail
|
||||
WT=/mnt/storage/scratch/gizmo-305
|
||||
OUT=/mnt/storage/scratch/gizmo-305-out/gate
|
||||
mkdir -p "$OUT"
|
||||
cd "$WT" || exit 9
|
||||
[ "$(git rev-parse HEAD)" = 8ddba89b7442f09fc71cf24d7f250e40a7f60fdf ] || { echo "HEAD drift"; exit 9; }
|
||||
[ -z "$(git status --porcelain)" ] || { echo "dirty tree"; exit 9; }
|
||||
[ -L node_modules ] || ln -s /mnt/storage/src/mosaic-stack/node_modules node_modules
|
||||
[ -L node_modules ] || { echo "no node_modules link"; exit 8; }
|
||||
DIRNET=gizmo-305_default
|
||||
nets() { echo " nets[$1]: $(docker network ls --format '{{.Name}}' | grep -E '^(mosaic-test-|gizmo-305_)' | tr '\n' ' ')"; }
|
||||
newtmp() { export TMPDIR="$(mktemp -d /mnt/storage/scratch/tmp/gXXX)"; echo " TMPDIR $TMPDIR"; }
|
||||
run() { # name script
|
||||
local name=$1 s=$2; newtmp; nets "before $name"
|
||||
local t0=$SECONDS
|
||||
timeout -k 10 900 "$s" > "$OUT/$name.log" 2>&1; local rc=$?
|
||||
echo "$name rc=$rc wall $((SECONDS-t0)) s :: $(grep -E '^selftest:' "$OUT/$name.log")"
|
||||
[ $rc -eq 124 ] || [ $rc -eq 137 ] && echo "SHELL-PHASE TIMEOUT (mos-1275): to Mos unplaced"
|
||||
grep -E 'compose network' "$OUT/$name.log" | sed 's/^/ /'
|
||||
grep -E '^FAIL|could not remove' "$OUT/$name.log" | sed 's/^/ red: /'
|
||||
grep -E '^skip' "$OUT/$name.log" | sed 's/^/ skip: /'
|
||||
nets "after $name"
|
||||
LASTRC=$rc
|
||||
}
|
||||
echo "start $(date -u +%FT%TZ) HEAD $(git rev-parse --short HEAD) refactor $(git rev-parse --short origin/refactor) docker $(docker version --format '{{.Server.Version}}')"
|
||||
echo "== wording"
|
||||
ABS="mosaic-test-absent-$RANDOM$RANDOM"_default
|
||||
docker network rm "$ABS" >/dev/null 2>"$OUT/absent.txt"; echo " rc=$? stderr: $(cat "$OUT/absent.txt")"
|
||||
grep -qE 'not found|No such network' "$OUT/absent.txt" || { echo "STOP: wording matches neither pattern"; exit 3; }
|
||||
echo "== green"
|
||||
for s in task release; do run "test-$s" "scripts/test-$s.sh"; [ $LASTRC -eq 0 ] || { echo "STOP: red on green run"; exit 4; }; done
|
||||
nets "after green" | grep -qE 'mosaic-test-|gizmo-305_' && { echo "STOP: network left after green"; exit 5; }
|
||||
echo "== mutants"
|
||||
mut() { # tag python-edit expected(red|green)
|
||||
local tag=$1 edit=$2 want=$3
|
||||
for s in task release; do
|
||||
local f="scripts/test-$s.sh" sum; sum=$(sha256sum "$f" | cut -d' ' -f1)
|
||||
cp -p "$f" "$OUT/$s.orig"
|
||||
python3 -B -c "$edit" "$f" || { echo "mutant $tag edit failed"; exit 6; }
|
||||
git diff --stat -- "$f" | head -1 | sed "s/^/ M$tag /"
|
||||
run "M$tag-$s" "$f"
|
||||
cp -p "$OUT/$s.orig" "$f"
|
||||
[ "$(sha256sum "$f" | cut -d' ' -f1)" = "$sum" ] && echo " restore ok $f" || { echo "RESTORE MISMATCH $f"; exit 7; }
|
||||
if [ "$want" = red ]; then grep -q '^FAIL.*compose network' "$OUT/M$tag-$s.log" && echo " M$tag-$s KILLED" || echo " M$tag-$s SURVIVED (unexpected)"
|
||||
else grep -q '^OK.*compose network' "$OUT/M$tag-$s.log" && echo " M$tag-$s survived (known)" || echo " M$tag-$s unexpected red"; fi
|
||||
# exact-name cleanup (mos-1438)
|
||||
for n in $(docker network ls --format '{{.Name}}' | grep -E '^(mosaic-test-(task|release)-[a-z0-9]+_default|gizmo-305_default)$'); do
|
||||
docker network rm "$n" >/dev/null && echo " cleaned $n"
|
||||
done
|
||||
nets "after cleanup M$tag-$s"
|
||||
done
|
||||
}
|
||||
E='import sys;p=sys.argv[1];s=open(p).read();o=%s;n=%s;assert s.count(o)==1;open(p,"w").write(s.replace(o,n))'
|
||||
mut a "$(printf "$E" "'export COMPOSE_PROJECT_NAME='" "'COMPOSE_PROJECT_NAME='")" red
|
||||
mut b "$(printf "$E" "'err=\"\$(docker network rm \"\$net\" 2>&1 >/dev/null)\" && return 0'" "'err=\"\" && return 0'")" red
|
||||
mut c "$(printf "$E" "'; remove_compose_network'\"'\"' EXIT'" "''\"'\"' EXIT'")" green
|
||||
[ -z "$(git status --porcelain | grep -v '^?? node_modules$')" ] && echo "tree clean after mutants" || { echo "TREE DIRTY"; git status --porcelain; }
|
||||
echo "end $(date -u +%FT%TZ)"
|
||||
@@ -1,66 +0,0 @@
|
||||
# Row 300 build notes (Launchpad): R6-N1, an HTTP-level test of the user-session option swap (#1807)
|
||||
|
||||
Brief: docs/plans/2026-10-23_r6-followup-rows.md § Brief: R6-N1. Reviewer Duckworth, gate owner Sage.
|
||||
Base c13c337e1 (refactor, after row 294 landed at d3059c2c3). Branch launchpad/row300.
|
||||
|
||||
## Change
|
||||
|
||||
Tests only. One new file, packages/webui/tests/user-option-swap.test.mjs. No product change and no
|
||||
existing assertion or fixture touched.
|
||||
|
||||
- **Gate stubbed open.** The file registers an in-thread load hook (`registerHooks`, as
|
||||
thread-claims.test and library-cli.test do through `--import`) keyed on the one URL
|
||||
`serve.mjs?gate=open`. On that URL alone it prepends `return true;` to `userRoute`'s body, then
|
||||
imports `startServer` from it. Every other import of serve.mjs, and every relative import inside
|
||||
the copy, is the real module. If the gate's signature line is not in serve.mjs exactly once, the
|
||||
hook throws. A renamed gate then fails loudly, instead of quietly testing the closed gate. The
|
||||
test also asserts that the copy's `userRoute` answers true for `POST /api/bus/message`.
|
||||
- **Setup.** This is granted-user.test.mjs's setup, cut to what the test needs: the fake OP, the
|
||||
in-process broker for `demo`, createSso with the access hook, and `userOptionsFor` over alice's
|
||||
transport. Every owner option is a stub that records its own name. The owner transport records
|
||||
`['transport', verb, args]`. One list, `owner`, holds both kinds of owner call.
|
||||
- **Positive control.** The owner signs in and posts `/api/bus/message`. Exactly
|
||||
`['option', 'send']` must be recorded, so the route reaches `send` and the count works.
|
||||
- **The check.** Alice signs in and walks G4's owner routes, copied, plus two chat reads. No answer
|
||||
may say `owner-only`, so the gate really is open. After each route, every owner record must be
|
||||
`['transport', 'plugins', {}]`, the read mos-1394 allowed. The message route must reach the user
|
||||
transport (`message.send`), and every transport opened is alice's.
|
||||
|
||||
Why a new file: granted-user.test.mjs's setup imports startServer statically. Passing the gate-open
|
||||
copy into it would change that fixture, and a fixture change goes to Mos. The route list and setup
|
||||
are copied, with a comment naming their source.
|
||||
|
||||
## Mutant
|
||||
|
||||
M12: serve.mjs:689 drops `send` from the user-session destructure, so a user session keeps the
|
||||
owner's `send`. Killed when "R6-N1" reports not ok. Expected failure: on `POST /api/bus/message`,
|
||||
the owner record holds `['option', 'send']`. run1/mutants.py applies it (anchor exactly once), runs
|
||||
the new file alone, restores with git checkout and checks the tree is clean.
|
||||
|
||||
## Gate
|
||||
|
||||
Duckworth approves the manifest. On Sage's CLEAR: run1/gate.sh does npm ci (root and webui), the new
|
||||
file whole, the webui suite whole, then M12. Logs go to /mnt/storage/scratch/launchpad-r300/run1,
|
||||
outside the tree. Not run yet.
|
||||
|
||||
MANIFEST.sha256 lists the one new path.
|
||||
|
||||
## Run 1 (sage-3408 CLEAR, 12:05Z)
|
||||
|
||||
npm ci root and webui were green. The new file was red on its first run (mos-1272, placed by me):
|
||||
`TypeError: Cannot read properties of undefined (reading 'set-cookie')` in signIn. When I cut down
|
||||
granted-user.test.mjs's `call`, I dropped `headers: res.headers` from what it resolves, so the
|
||||
sign-in found no cookies. The fix puts `headers` back, the same as granted-user.test.mjs:40. No
|
||||
assertion changed. The new file then passed alone (1/0). The fix is a new commit, and the manifest
|
||||
is re-hashed. The gate resumes at new-file on the new head.
|
||||
|
||||
Run 1 resumed (TAG -r2) on db5122920, manifest db8be52ce895603e687985acfae29e53e3e8782ae945c3cded6cca36141bfa3b:
|
||||
|
||||
- new file whole: 1 pass, 0 fail.
|
||||
- webui suite whole: 375 pass, 0 fail, 0 skipped, 0 cancelled, 58.2 s (limit 600).
|
||||
- M12 killed. "R6-N1" reports not ok at :151: `POST /api/bus/message: ["option","send"]`, where
|
||||
`["transport","plugins",{}]` is expected. The restore left the tree clean.
|
||||
|
||||
Duckworth N1 (duckworth-0263, non-blocking): the setup passes no `upstream`, so the swap's
|
||||
`upstream = null` has no recorder here. The test proves the swap for the options it stubs. It
|
||||
proves nothing about `upstream`.
|
||||
@@ -1 +0,0 @@
|
||||
03b5d60f68ea2bddd779e1df19519855a5f01cc28ec9ddb26ee7c45fcfe75cf4 packages/webui/tests/user-option-swap.test.mjs
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Row 300 gate run 1 (brief R6-N1): npm ci (root and packages/webui), the new test file whole, the
|
||||
# webui suite whole, then mutant M12. Stops at the first red. FROM=<step> resumes at a step.
|
||||
set -u -o pipefail
|
||||
WT=/mnt/storage/scratch/launchpad-r300/wt
|
||||
OUT=$WT/agents/launchpad/work/queue-300/run1
|
||||
LOG=/mnt/storage/scratch/launchpad-r300/run1
|
||||
FROM=${FROM:-npm-root}; TAG=${TAG:-}
|
||||
mkdir -p $LOG
|
||||
export TMPDIR=$(mktemp -d /mnt/storage/scratch/tmp/gXXXXXX)
|
||||
echo "start $(date -u +%H:%M:%SZ) FROM=$FROM TAG=$TAG TMPDIR $TMPDIR head $(git -C $WT rev-parse HEAD)" >> $LOG/summary.txt
|
||||
[ -z "$(git -C $WT status --porcelain)" ] || { echo "STOP worktree not clean" | tee -a $LOG/summary.txt; exit 9; }
|
||||
on=0
|
||||
step() { # name limit dir cmd...
|
||||
local name=$1 limit=$2 dir=$3; shift 3
|
||||
[ $on = 1 ] || [ $name = $FROM ] || return 0; on=1
|
||||
local t0=$(date +%s%N)
|
||||
( cd $dir && timeout -k 10 $limit "$@" ) > $LOG/$name$TAG.log 2>&1
|
||||
local rc=$?
|
||||
local ms=$(( ($(date +%s%N) - t0) / 1000000 )); local dt=$((ms/1000)).$(printf %03d $((ms%1000)))
|
||||
echo "$name$TAG rc=$rc seconds=$dt limit=$limit $(date -u +%H:%M:%SZ)" | tee -a $LOG/summary.txt
|
||||
[ $rc -eq 0 ] || { echo "STOP at $name$TAG" | tee -a $LOG/summary.txt; exit $rc; }
|
||||
}
|
||||
step npm-root 900 $WT npm ci --ignore-scripts
|
||||
step npm-webui 900 $WT/packages/webui npm ci --ignore-scripts
|
||||
step new-file 300 $WT/packages/webui node --test tests/user-option-swap.test.mjs
|
||||
step webui 600 $WT/packages/webui node --test tests/
|
||||
[ -z "$(git -C $WT status --porcelain)" ] || { echo "STOP worktree dirty after the suite" | tee -a $LOG/summary.txt; git -C $WT status --porcelain >> $LOG/summary.txt; exit 9; }
|
||||
echo "SUITES GREEN $(date -u +%H:%M:%SZ)" | tee -a $LOG/summary.txt
|
||||
python3 -B $OUT/mutants.py
|
||||
rc=$?; echo "MUTANTS rc=$rc $(date -u +%H:%M:%SZ)" | tee -a $LOG/summary.txt; exit $rc
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Row 300 mutant M12 (BUILD.md "Mutant"): serve.mjs keeps the owner's send for a user session. The
|
||||
# edit must match exactly once; the new file runs alone under timeout -k 10 300 with the TAP
|
||||
# reporter; git checkout restores and the tree must be clean. Killed = "R6-N1" reports "not ok".
|
||||
import json, os, re, subprocess, sys, time
|
||||
|
||||
WT = '/mnt/storage/scratch/launchpad-r300/wt'
|
||||
LOG = '/mnt/storage/scratch/launchpad-r300/run1'
|
||||
SWAP = "({ bus, send, settingsWrite, projectFiles, projectFile, projectSave, chat, nameWrite, assistantStop, instancesWrite, routesWrite, agentWrite, processing } = userOptions(session));"
|
||||
MUTANTS = [
|
||||
('M12', 'packages/webui/src/serve.mjs', SWAP,
|
||||
"({ bus, settingsWrite, projectFiles, projectFile, projectSave, chat, nameWrite, assistantStop, instancesWrite, routesWrite, agentWrite, processing } = userOptions(session));",
|
||||
('packages/webui', 'tests/user-option-swap.test.mjs'), 'R6-N1'),
|
||||
]
|
||||
|
||||
def git(*a):
|
||||
return subprocess.run(['git', '-C', WT, *a], capture_output=True, text=True, check=True).stdout
|
||||
|
||||
def main():
|
||||
if git('status', '--porcelain'): raise SystemExit('worktree not clean at start')
|
||||
summary, bad = [], 0
|
||||
for mid, path, old, new, (pkg, test), killer in MUTANTS:
|
||||
p = os.path.join(WT, path)
|
||||
try:
|
||||
s = open(p).read()
|
||||
if s.count(old) != 1: raise SystemExit(f'{mid}: anchor count {s.count(old)} in {path}')
|
||||
open(p, 'w').write(s.replace(old, new))
|
||||
diff = git('diff')
|
||||
t0 = time.time()
|
||||
r = subprocess.run(['timeout', '-k', '10', '300', 'node', '--test', '--test-reporter=tap', test],
|
||||
cwd=os.path.join(WT, pkg), capture_output=True, text=True)
|
||||
dt = round(time.time() - t0, 1)
|
||||
finally:
|
||||
git('checkout', '--', path)
|
||||
if git('status', '--porcelain'): raise SystemExit('worktree not clean after restore')
|
||||
open(f'{LOG}/{mid}.diff', 'w').write(diff)
|
||||
open(f'{LOG}/{mid}.tap', 'w').write(r.stdout + '\n# stderr\n' + r.stderr)
|
||||
res = {m.group(2): m.group(1) == 'ok' for m in re.finditer(r'^(ok|not ok) \d+ - (.*)$', r.stdout, re.M)}
|
||||
hit = [n for n in res if n.startswith(killer)]
|
||||
killed = r.returncode not in (0, 124, 137) and bool(hit) and all(not res[n] for n in hit)
|
||||
bad += not killed
|
||||
print(f'{mid} rc={r.returncode} seconds={dt} killed={killed} red={[n for n, ok in res.items() if not ok]}', flush=True)
|
||||
summary.append({'mutant': mid, 'rc': r.returncode, 'seconds': dt, 'killed': killed, 'killer': killer})
|
||||
json.dump(summary, open(f'{LOG}/mutants.json', 'w'), indent=1)
|
||||
sys.exit(1 if bad else 0)
|
||||
|
||||
main()
|
||||
@@ -1,638 +0,0 @@
|
||||
# PRD 1.17 draft: Case 2 story files are DOCX (Q235 to Q237, P1 to P6)
|
||||
|
||||
Sage, 2026-10-23, for mos-1366 item 1 and Vikunja 570. Draft 8. It is d7 plus Mos's d8 fix list mos-1443 (see "d8 changes"). d7 is d6 plus Mos's ruling mos-1379 on Fenton's 571 B2 (see "d7 changes"). d6 is d5 with Webby's round 3 (webby-0207) fixed: B1 to B3 and N10 to N13, with N14 left for Mos (see "d6 changes"). d5 folds in:
|
||||
- Mos's d4 check ruling mos-1372 (D1 to D14; D15 was dropped).
|
||||
- mos-1374, which replaces J-c.
|
||||
- The impact map mos-1368 (jason-master-restart d183246, `projects/mosaic-mvp/case2-docx-impact-map.md`: A1 to A16, critic items C1 to C6, items 2 to 7).
|
||||
- Mos's F4 measurement.
|
||||
|
||||
Review order (mos-1367 B5): Webby, then Mos, then Jason. Base: PRD 1.16, `docs/prd/mosaic-stack.md` blob a6db9b4a at 482e865ac.
|
||||
1.16 lands first (row 291), and this text is a new version on top of it. Nothing here is built or queued. The impact map's queue changes (A24, A57 to A59) go through `scripts/mosaic queue` after 1.17 is approved (C9).
|
||||
|
||||
Sources, verbatim in Mos's DECISIONS:
|
||||
- Q235, Jason's Q36 answer.
|
||||
- Q236: chapters are DOCX, Markdown for agent files and docs.
|
||||
- Q237: "It is correct for now (subject to future change)".
|
||||
- The P1 to P6 reading as restated to Jason in Q38.
|
||||
|
||||
## Settled points (mos-1367)
|
||||
|
||||
These stand as ruled. d5 changes only what mos-1372 changed.
|
||||
|
||||
- **O1. Where a converted chapter lives.** The DOCX lives in the writing store of
|
||||
O2 design D12, and the archived Markdown stays in the user's repository under a
|
||||
human-marked archive folder. Ruled yes in B1, on the condition that the text
|
||||
says plainly that a converted chapter leaves the Gitea-mirrored repository and
|
||||
lives in the stack's writing store. mos-1372 D7 and mos-1375 add a remote for
|
||||
the store, off the stack's host.
|
||||
- **O2. The unit of conversion.** One story file per import, refusing a file
|
||||
that is already converted. Ruled yes in B2: each file gets its own fidelity
|
||||
report, human confirmation, manifest and commit.
|
||||
- **O3. Whether conversion is a vocabulary action.** A human-only verb outside
|
||||
the agent vocabulary, with no role grant and no agent request path. Ruled yes
|
||||
in B3.
|
||||
- **O4. Reading archived Markdown.** A new `archived` scope. Lookups leave it out
|
||||
unless the caller asks, every answer marks it archived, and a canon citation
|
||||
can't name it. Ruled yes in B4.
|
||||
|
||||
## d3 choices after mos-1372
|
||||
|
||||
- **C1 is replaced by D1, keep-source-scope.** A DOCX keeps its source's scope:
|
||||
universe, book, and canon or playground. A playground DOCX follows the
|
||||
playground rules and is never returned as canon. The import accepts canon and
|
||||
playground story files. Type-folder files and supporting files stay Markdown
|
||||
(P4). This also settles the impact map's Q18, item 4. It leaves one narrowing
|
||||
for Jason, J-i. A playground DOCX can't become canon in 1.17.
|
||||
- **C2 stands.** The move keeps the file's path under the archive folder:
|
||||
`book1/ch3.md` goes to `<archive>/book1/ch3.md`. An archived file's universe
|
||||
and book are those of its old path.
|
||||
- **C3 is replaced by D3 and D14.** The archive commit is written by a new
|
||||
human-only bus step (Vikunja 571) on the C2-02 write plumbing and pushed through
|
||||
C2-03b. The order is the store commit and the remote's confirmation that it
|
||||
holds that commit, then the archive commit and its push, then publication to the
|
||||
lookups.
|
||||
- **N4 stands.** REQ-LIB-8 says "a real user's books". The PRD names no user
|
||||
anywhere in Case 2.
|
||||
|
||||
## Text changes
|
||||
|
||||
### Status and sources
|
||||
|
||||
In the Status bullet's first line, "- Status: approved, version 1.16." becomes
|
||||
"- Status: approved, version 1.17." Status gains, after the two 1.16 sentences at
|
||||
the end of the bullet: "Version 1.17 records Jason's rulings Q235 to Q237 of
|
||||
2026-10-23: Case 2 story files are DOCX, Markdown stays for agent files and
|
||||
documentation, and a human-started import converts a Markdown story file one way.
|
||||
It also adds REQ-LIB-9, the Console's DOCX editor, from Jason's rulings Q195, Q226
|
||||
and Q234. It changes what Case 2 requirements allow, so Mos puts the text to Jason
|
||||
as written, and it lands only after his yes (mos-1366, Vikunja 570)."
|
||||
|
||||
New source line, above the 1.16 one: "Version 1.17 source: Jason's Q235, answering
|
||||
Q36: 'How about we see a markdown file, we convert the markdown file to docx, then
|
||||
archive or mark the markdown file as converted. The new standard for files in the
|
||||
creating writing use case is to use docx to handle versioning and WYSIWYG. We
|
||||
eliminate the potential for confusion based on the files. Agents must understand
|
||||
which files are what format and where they live. The system must allow for import
|
||||
and conversion. We will not run the systems in parallel. There will be an
|
||||
irreversible conversion of the files.' His Q236 says: 'For creative writing
|
||||
chapters, we need to utilize docx as the standard. Markdown is acceptable for
|
||||
agent files, instructions, PRDs, documentation, etc. The creative writing files
|
||||
should be docx for familiarity for the user.' His Q237 says 'Q38: It is correct
|
||||
for now (subject to future change)', which confirms Mos's reading P1 to P6.
|
||||
REQ-LIB-9 rests on his Q195 request for 'a full WYSIWYG editor within Mosaic
|
||||
Stack', his Q226 answer 'F41: We want to move editing into the WYSIWYG in the
|
||||
WebUI. All changes are instantly committed and available to the agents.' and his
|
||||
Q234 answer 'Q37: yes' to the exact security header for the editor's frame. The
|
||||
storage follows the O2 design D10 to D12 as rewritten under Vikunja 571, at
|
||||
b99ca86b9 on `refactor`."
|
||||
|
||||
### Creative library, section lead
|
||||
|
||||
Replace "The library is the user's own writing repository." with "The library is
|
||||
the user's own writing repository plus the stack's writing store, which holds the
|
||||
DOCX story files (REQ-LIB-8, version 1.17)."
|
||||
|
||||
### REQ-LIB-1
|
||||
|
||||
Add, before "(Design 1.1": "The mapping also names one archive folder, set by the
|
||||
human, where converted Markdown story files go. A book's DOCX story files are in
|
||||
the stack's writing store, under the same universe and book (REQ-LIB-8)." Version
|
||||
tag, inside the closing parenthesis: "Version 1.15: supporting folders.)" becomes
|
||||
"Version 1.15: supporting folders. Version 1.17: the archive folder and the
|
||||
writing store.)"
|
||||
|
||||
### REQ-LIB-2
|
||||
|
||||
Replace "A file's scope comes from its path alone, prefixes first: a Markdown file
|
||||
under a supporting prefix is supporting, one under a playground prefix at any level
|
||||
is playground, any other Markdown file in a book folder is canon, and everything
|
||||
else is unmapped and never returned. A folder in both lists is supporting." with:
|
||||
|
||||
"A Markdown file's scope comes from its path and from past imports, prefixes
|
||||
first: a Markdown file under the archive folder is archived, one under a
|
||||
supporting prefix is supporting, a Markdown file at a converted file's old path is
|
||||
unmapped under REQ-LIB-8 but flagged in the format map, one under a playground
|
||||
prefix at any level is playground, any other Markdown file in a book folder is
|
||||
canon, and everything else is unmapped and never returned. A folder in both lists
|
||||
is supporting. The archive folder follows the same placement rules and may not
|
||||
overlap another prefix or a book folder. An archived file keeps the path it had
|
||||
under the archive folder, and its universe and book are those of that old path. A
|
||||
DOCX document in the writing store keeps its source's scope: the universe, the
|
||||
book if there is one, and canon or playground. Its source is the Markdown file it
|
||||
was converted from or, for one the human starts in the editor, the universe and
|
||||
book or the playground the human picks (REQ-LIB-8). A playground DOCX follows the
|
||||
playground rules and is never returned as canon. It stays playground after its
|
||||
draft universe is made real. In version 1.17 no promotion or mapping change makes
|
||||
a playground DOCX canon. A later version of this PRD says how one becomes canon."
|
||||
|
||||
Replace "Lookups return canon unless the caller asks for playground or
|
||||
supporting." with "Lookups return canon unless the caller asks for playground,
|
||||
supporting or archived. Every answer marks an archived file as archived and names
|
||||
the DOCX that replaced it."
|
||||
|
||||
Replace "so an agent can't cite a playground or supporting file as canon" with "so
|
||||
an agent can't cite a playground, supporting or archived file as canon".
|
||||
|
||||
In REQ-LIB-2 only, replace "The Console shows each cite's scope." with "The Console shows each cite's
|
||||
scope and format, and whether a cited Markdown file was converted."
|
||||
|
||||
Version tag, inside the closing parenthesis: "Version 1.15: supporting.)" becomes
|
||||
"Version 1.15: supporting. Version 1.17: archived scope and DOCX scope.)"
|
||||
|
||||
### REQ-LIB-4
|
||||
|
||||
Replace "The user commits and pushes with their own tools, today Obsidian with
|
||||
obsidian-git." with "The user commits and pushes Markdown with their own tools,
|
||||
today Obsidian with obsidian-git. A converted story file's current text is no
|
||||
longer in that repository, which keeps only its archived Markdown (REQ-LIB-8)."
|
||||
|
||||
Add, after "Bus writes and pushes come in later rows (C2-02, C2-03b).": "A DOCX
|
||||
story file is saved in the Console's editor, and each accepted save is one commit
|
||||
by the human in the stack's writing store (REQ-LIB-9). Each writing-store commit
|
||||
is also pushed to a remote off the stack's host, never by force-push. The remote
|
||||
is a setting only a human changes, and it starts unset. A repository on the
|
||||
stack's host never counts as that remote. A missing remote or a failed push never
|
||||
undoes a save, and the user sees each push that is pending or failed. Only the
|
||||
stack's host pushes to that remote, and no agent can reach it with any credential.
|
||||
Agents read the local commit."
|
||||
|
||||
Replace "Agents read only the mirror's served commit and never hold a copy of
|
||||
their own, so they see the user's push within about a minute." with "Agents read
|
||||
the user's repository only at the mirror's served commit, except a story file
|
||||
during its import under REQ-LIB-8. They read a DOCX story file only at a committed
|
||||
version in the writing store, under REQ-LIB-5. They never hold a copy of their
|
||||
own, so they see the user's Markdown push within about a minute and a DOCX save at
|
||||
their next lookup after the editor reports it as committed."
|
||||
|
||||
Version tag: "and the sync items.)" becomes "and the sync items. Version 1.17,
|
||||
with Q222 for the remote setting.)"
|
||||
|
||||
### REQ-LIB-5
|
||||
|
||||
Add, after "Each answer names the commit it read.": "Each answer also names the
|
||||
file's format and where it lives: its path, or its document id in the writing
|
||||
store. A DOCX story file is read from its latest committed save, never from
|
||||
unsaved text. A lookup that starts after the editor reports a save as committed
|
||||
returns that save or a later one, even while its push to the remote is pending or
|
||||
has failed, and the answer names the version. Get, search and manuscript read a
|
||||
DOCX story file as its extracted text with DOCX locators, never as lines. That
|
||||
text is the file with its tracked changes accepted. An agent reads a story file's
|
||||
comments, or its text with tracked deletions shown, only after a human turns on
|
||||
the matching setting. Both settings are off by default, and only a human changes
|
||||
them. The reader in this version can't read some things a DOCX story file can
|
||||
hold, such as a web link, a text box, a field or hidden text. The editor warns the
|
||||
human when an edit adds one, and the human can still save it. Until a later save
|
||||
takes it out, lookups give agents none of the text of the part that holds it,
|
||||
whether that is the chapter's body, a note or a comment. The manuscript lookup
|
||||
follows the book's chapter order across both formats (O2 design D10), and the next
|
||||
chapter it names is never an archived file. Links out and in resolve across both
|
||||
formats. The universe lookup returns the format map (REQ-LIB-8)."
|
||||
|
||||
Replace "The user sees them in Obsidian's graph and backlinks." with "The user sees
|
||||
a Markdown file's links in Obsidian's graph and backlinks. A DOCX story file's
|
||||
wikilinks stay clickable in the Console's editor (O2 design D11), and no graph
|
||||
shows them yet."
|
||||
|
||||
Version tag: 'and "Connections are always visible".)' becomes 'and "Connections
|
||||
are always visible". Version 1.17, with Q222 for the two settings.)'
|
||||
|
||||
### REQ-LIB-6
|
||||
|
||||
Replace "A reply may cite lines of the repository at a commit or pages the agent
|
||||
fetched, and the broker checks every citation before it stores the message." with
|
||||
"A reply may cite lines of a Markdown file at a commit, a place in a committed
|
||||
DOCX story file, or pages the agent fetched, and the broker checks every citation
|
||||
before it stores the message. A DOCX citation never calls a paragraph a line. It
|
||||
names the document id, the committed version and a DOCX locator. A citation that
|
||||
names an archived file as current is refused. The `requireCitation` setting below
|
||||
applies to Markdown and DOCX citations alike, and so does the rule for a citation
|
||||
marked as canon."
|
||||
|
||||
Add, after "the broker refuses such a write before any git call.": "The writing
|
||||
store and the archive folder are read-only to a creative agent as well, and the
|
||||
broker's path check treats the archive folder as story. No agent creates, edits,
|
||||
deletes, converts, archives or restores a story file in any format, and no agent
|
||||
writes a DOCX. No creative agent starts or undoes a conversion, and none asks for
|
||||
one through a tool or a decision it raises, as REQ-LIB-8 says. An agent may still
|
||||
suggest a conversion to the human in chat. Each creative role's contract states
|
||||
which files are DOCX and which are Markdown, and cites a DOCX story file by its
|
||||
locator, never by line."
|
||||
|
||||
Version tag, inside the closing parenthesis: "Version 1.15.)" becomes "Version
|
||||
1.15. Version 1.17.)"
|
||||
|
||||
### New REQ-LIB-8
|
||||
|
||||
This bullet goes after REQ-LIB-7 and before the "### Installer" heading.
|
||||
|
||||
"- **REQ-LIB-8.** Story files become DOCX. DOCX is the standard for chapters and
|
||||
the other story text in a Case 2 writing project, canon and playground alike. A
|
||||
story file becomes DOCX through a human's import (below), or when the human
|
||||
starts it in the editor. From then on DOCX is its only working format, edited in
|
||||
the Console's editor (REQ-LIB-9). A Markdown story file stays Markdown until its
|
||||
import. Files in a type folder (REQ-LIB-1), such as character and place notes,
|
||||
stay Markdown. So do supporting files, agent files, instructions, PRDs and
|
||||
documentation, including the character sheets, summaries and cross-links agents
|
||||
keep under REQ-LIB-6.
|
||||
- A converted story file's current text leaves the user's Gitea-mirrored
|
||||
repository. Its DOCX lives in the stack's writing store, on the stack's host,
|
||||
and not in the repository the user pushes or opens in Obsidian. Only its
|
||||
archived Markdown stays there.
|
||||
- An import converts one Markdown story file, canon or playground, outside every
|
||||
type folder (REQ-LIB-1), to a DOCX document in the writing store. It refuses
|
||||
an unmapped, supporting, archived or type-folder file, and a file that is
|
||||
already converted. Each import has its own fidelity report, the human's
|
||||
confirmation of that report, a manifest naming the source file and its commit,
|
||||
and one commit in the store. The DOCX keeps every wiki link of the source as
|
||||
written, and a lost link to another library file fails the fidelity report. A
|
||||
web link becomes plain text that keeps its label and address, and the fidelity
|
||||
report lists it for the human to confirm. A web link that can't be kept safely
|
||||
as plain text refuses the import.
|
||||
- The human can also start a new story file in the editor, in a universe and
|
||||
book or a playground the human picks. It is a DOCX document in the writing
|
||||
store from its first commit, with no Markdown copy, and it opens under the
|
||||
same gate as the import.
|
||||
- The same import marks the Markdown file converted, naming the document, and
|
||||
moves it to the archive folder under its old path (REQ-LIB-1, REQ-LIB-2).
|
||||
The mark and the move are one commit authored by the human in the user's
|
||||
repository. A new human-only bus step (Vikunja 571) on the C2-02 write
|
||||
plumbing writes it, and C2-03b pushes it. The move keeps the bytes and the
|
||||
git history, so it isn't `data.delete`.
|
||||
- The store commit comes first, and the writing store's remote must confirm it
|
||||
holds that commit. Then come the archive commit and its push, then publication
|
||||
to the lookups. Until publication the Markdown at its old path keeps its canon
|
||||
or playground scope. Agents read that file at the commit the import started
|
||||
from, even after the mirror's served commit reaches the archive commit or a
|
||||
later one. No lookup returns the file's archived copy before publication, even
|
||||
one that asks for archived files. A refusal or failure before the archive push
|
||||
leaves the Markdown unmoved and no DOCX that a lookup returns. A failure after
|
||||
the archive push leaves a pending import that the human sees and can resume,
|
||||
never a claim that nothing moved. An archive push whose result is unknown
|
||||
counts as a failure after the archive push until the stack reads the result
|
||||
back from the user's remote.
|
||||
- Each stage of an import writes a logged event. The import's record on the
|
||||
stack's host names the source file's path, commit and blob and the new
|
||||
document id, and each event points to that record.
|
||||
- After a conversion, a Markdown file at the converted file's old path is neither
|
||||
canon nor playground. Lookups leave it out, the format map flags it, and the human is told.
|
||||
- A new Markdown story file in a book folder that holds converted files stays
|
||||
canon until its import, unless it sits at a converted file's old path or under
|
||||
a playground prefix. The Console flags it and offers the import. Nothing
|
||||
converts it on its own.
|
||||
- A hybrid's exclusion that covers a converted file's old path also covers its
|
||||
DOCX document (REQ-LIB-3). An exclusion of a whole book folder also covers
|
||||
every DOCX document in that book, including one started in the editor. An
|
||||
exclusion can also name a DOCX document by its id.
|
||||
- Only a human starts an import or a new story file, from the CLI or a Console
|
||||
session signed in as that human. Both are human verbs outside the agent action
|
||||
vocabulary. Neither is added to `ACTIONS` in the business vocabulary or to the
|
||||
broker's always-gated list, including the import's action, `library.convert`.
|
||||
No role holds them, no agent can request them, and the hard-wait list in
|
||||
REQ-WAIT-1 doesn't change. In an organization with several humans, who may
|
||||
start them is a setting only a human changes, and the default is the owner
|
||||
only.
|
||||
- Conversion is one way, with no parallel run. Neither the Console nor any agent
|
||||
edits a converted story file as Markdown, and no DOCX edit syncs back to
|
||||
Markdown. The Console's Markdown save refuses every file under the archive
|
||||
folder. The user's own tools can still change the archived Markdown, and no
|
||||
such change reaches the DOCX. The old Markdown stays in git history, and
|
||||
nothing rewrites history. A promotion into a book folder (C2-19) runs the
|
||||
import for a Markdown story file or is refused. A promotion of a playground
|
||||
DOCX is refused in version 1.17.
|
||||
- Agents get a format map: for each mapped folder and story file, its format,
|
||||
scope and where it lives, archived files, flagged files and pending imports
|
||||
included.
|
||||
- The import and new story files ship closed. They open only after four things.
|
||||
The editor ships. The human has set the writing store's remote, and the stack
|
||||
has checked that it can push there. Agents can read committed DOCX story files
|
||||
through the lookups and cite them (REQ-LIB-5, REQ-LIB-6). Any earlier agent
|
||||
system that writes the user's files has stopped, which for Case 2 is the
|
||||
Hermes retirement (#423 step 5). So the import itself never cuts agents off
|
||||
from a chapter, the chapter's current text never lives only on the stack's
|
||||
host, and no second system writes the story. The first import of a real user's
|
||||
books waits for Jason's go.
|
||||
(Q235, Q236, Q237: P1 to P6. Q222 for the setting. O2 design D10 to D12.
|
||||
Version 1.17.)"
|
||||
|
||||
### New REQ-LIB-9
|
||||
|
||||
This bullet goes after REQ-LIB-8.
|
||||
|
||||
"- **REQ-LIB-9.** The Console's DOCX editor. The human edits a DOCX story file in
|
||||
the Console's editor, in a split pane with the agent chat alongside it. The
|
||||
human can pin an agent chat to a document. The human can select a word,
|
||||
right-click it, and choose a synonym from a thesaurus. Only a human saves. Saves
|
||||
happen on their own while the human types (Q226), at intervals only a human
|
||||
changes, and each accepted save is one commit with the human as author, pushed
|
||||
as REQ-LIB-4 says. A save made against an older version than the current one is
|
||||
refused. Agents never write a DOCX. Versioning is the editor's tracked changes
|
||||
plus one git commit per save. The editor's code is vendored and pinned, with a
|
||||
hash per file and the licenses that its independent security review accepted. At
|
||||
runtime the editor loads only files that the stack itself serves, and it
|
||||
requests nothing from any other host. The editor's frame sends exactly the
|
||||
content security policy Jason approved in Q234, and the WebUI shell's own header
|
||||
is unchanged. REQ-PROJ-3's project docs editor is unchanged. (Q195, Q226, Q234,
|
||||
Q236. O2 design D3, D4, D6, D8, D10, D13, D14, D16 and D22. Version 1.17.)"
|
||||
|
||||
### Version 1.17 notes
|
||||
|
||||
Added after the 1.16 notes:
|
||||
|
||||
"- Version 1.17:
|
||||
- Jason confirmed the reading 'for now (subject to future change)' (Q237). The
|
||||
rulings stand until he revises them.
|
||||
- The 10-27 Case 2 release ships on Markdown as built (P6). The 1.11 line 'The
|
||||
Case 2 MVP for 10-27 is the Markdown library (#416). The WYSIWYG editor (Q195,
|
||||
Q196) is an add-on that doesn't gate it.' still holds. Conversion opens after
|
||||
10-27, and only once REQ-LIB-8's four conditions are met. The editor ships,
|
||||
the writing store's remote is set and the stack has checked that it can push
|
||||
there, agents can read and cite committed DOCX story files through the
|
||||
lookups, and Hermes is retired, which is #423 step 5.
|
||||
- The 1.12 note says five bus write and Console editor rows, C2-02, C2-03b,
|
||||
C2-11a, C2-11b and C2-19, don't gate 10-27. Jason's Q226 F42 later moved
|
||||
C2-02, C2-03b and C2-11b into the 10-27 slice. The Case 2 design brings C2-11a
|
||||
in with them, because C2-11b needs it. C2-19 stays outside the slice. Mos's
|
||||
reading of F42 is that C2-02 and C2-03b now gate 10-27, because design 9.2
|
||||
puts them in 'the smallest slice that lets her start'. C2-11a and C2-11b are
|
||||
slice rows that still don't gate 10-27, because the editor is the Q195 add-on.
|
||||
The DOCX change in 1.17 leaves this slice as it is, and C2-11b's Markdown
|
||||
editor never edits a converted story file.
|
||||
- Q236 narrows Q176's editor choice to DOCX for story files (REQ-LIB-9). The
|
||||
1.12 note that the Case 2 design keeps Obsidian now holds only for Markdown
|
||||
files, including story files not yet imported. A DOCX story file is edited
|
||||
only in the Console's editor under REQ-LIB-9.
|
||||
- This replaces two parts of the O2 design at 25c09f19f. The superseded-notice
|
||||
proposal from Fenton's F1 in D12 is withdrawn, and the
|
||||
keep-Markdown-at-its-path model of D11 is replaced. Gyro's rewrite of the O2
|
||||
design for Vikunja 571, landed on `refactor` at b99ca86b9, carries the
|
||||
details, and where it differs from this text, this text holds:
|
||||
- the import and archive steps, the mark, and the new bus step;
|
||||
- links from supporting files to a moved chapter;
|
||||
- the DOCX reader;
|
||||
- the user's unpushed or later changes to an archived file or at its old path,
|
||||
and pushing and closing the file in Obsidian before each import;
|
||||
- the writing store's remote in W4 section 7.3, which replaces the no-remote
|
||||
and no-backup rule that W4 section 7.4 held before the rewrite, at
|
||||
062646487;
|
||||
- import events counted by a bus restore, and recovery when a bus restore or a
|
||||
restore of the whole host predates an import;
|
||||
- manifest order for the manuscript lookup and its next chapter;
|
||||
- `library.convert` kept out of `ACTIONS`, out of the hard-wait note and out
|
||||
of the pinned `GATED_ONLY` list in packages/business/src/vocabulary.mjs.
|
||||
- Agents read a converted story file through the Case 2 lookups under the same
|
||||
project and universe access as Markdown canon, in any thread or room. W4's
|
||||
earlier O2-only conversations, per-document grants and per-send sharing don't
|
||||
gate these lookups. The 571 rewrite replaced them in W4 sections 7.1 and 7.2.
|
||||
The creative tool list in REQ-LIB-6 doesn't change.
|
||||
- The six creative role contracts row 213 landed say 'Every item cites the
|
||||
lines of the user's material it is about'. A build row under 571 changes that
|
||||
line for DOCX story files (REQ-LIB-6).
|
||||
- A new Markdown file in a book folder is still canon in 1.17. The 1.17
|
||||
exception is a file at a converted file's old path, which REQ-LIB-2 makes
|
||||
unmapped.
|
||||
- Story files convert whether canon or playground. Type-folder and supporting
|
||||
files stay Markdown.
|
||||
- Measured 2026-10-23 at about 01:21Z: the Case 2 user's library repository
|
||||
tracks 213 files, 203 of them Markdown, and none is a .docx or .doc. It has no
|
||||
untracked files. The user's .doc files (Q196) are outside it. So the landed
|
||||
code has no DOCX there to report as unreadable at 10-27.
|
||||
- Text replaced in 1.17, kept here as in earlier notes:
|
||||
- Creative library lead, the 1.16 sentence: "The library is the user's own
|
||||
writing repository."
|
||||
- REQ-LIB-2, the 1.16 sentences: "A file's scope comes from its path alone,
|
||||
prefixes first: a Markdown file under a supporting prefix is supporting,
|
||||
one under a playground prefix at any level is playground, any other
|
||||
Markdown file in a book folder is canon, and everything else is unmapped
|
||||
and never returned. A folder in both lists is supporting." "Lookups return
|
||||
canon unless the caller asks for playground or supporting." "so an agent
|
||||
can't cite a playground or supporting file as canon" "The Console shows
|
||||
each cite's scope."
|
||||
- REQ-LIB-4, the 1.16 sentences: "The user commits and pushes with their own
|
||||
tools, today Obsidian with obsidian-git." "Agents read only the mirror's
|
||||
served commit and never hold a copy of their own, so they see the user's
|
||||
push within about a minute."
|
||||
- REQ-LIB-5, the 1.16 sentence: "The user sees them in Obsidian's graph and
|
||||
backlinks." A converted chapter's connections show in Obsidian only as they
|
||||
stood at conversion, until a Console view of their links exists. Q226
|
||||
records that view as a later option.
|
||||
- REQ-LIB-6, the 1.16 sentence: "A reply may cite lines of the repository at
|
||||
a commit or pages the agent fetched, and the broker checks every citation
|
||||
before it stores the message."
|
||||
- REQ-LIB-1 only gains sentences.
|
||||
- REQ-LIB-3's text and REQ-LIB-7 are unchanged. REQ-LIB-8 adds one form of
|
||||
exclusion REQ-LIB-3 doesn't have: naming a DOCX document by its id. A path
|
||||
exclusion also covers DOCX documents, through a converted file's old path or a
|
||||
whole book folder. An archived file and a DOCX document keep a universe, and a
|
||||
book where their source has one, so every lookup still names one universe.
|
||||
REQ-PROJ-3, the Console editor for a project's spec and docs, is unchanged.
|
||||
C2-11b opens the library's Markdown files in that same editor.
|
||||
- In `packages/tasks/requirements.json` the titles of REQ-LIB-1, REQ-LIB-2 and
|
||||
REQ-LIB-4 change, and those of REQ-LIB-5 and REQ-LIB-6 stay. REQ-LIB-1 becomes
|
||||
'A human-set library maps the user's repository onto universes, books, types,
|
||||
playgrounds, supporting and archive folders'. REQ-LIB-2 becomes 'Scope comes
|
||||
from the path or a DOCX's source, lookups default to canon, and only canon
|
||||
files are ever cited as canon'. REQ-LIB-4 becomes 'Git holds every change. The
|
||||
bus fast-forwards a read-only mirror every 60 seconds, the one place agents
|
||||
read Markdown'. REQ-LIB-8 and REQ-LIB-9 add two ids, so the count goes from 85
|
||||
to 87. REQ-LIB-8 is titled 'Case 2 story files become DOCX by a human-only
|
||||
one-way import or in the editor; Markdown stays for notes and docs', and
|
||||
REQ-LIB-9 'The Console's DOCX editor: only a human saves, each save is one
|
||||
commit, and the editor code is vendored and pinned'.
|
||||
- Open points O1 to O4 of draft 1 were ruled by Mos in mos-1367 B1 to B4.
|
||||
- Sage files the build rows under Vikunja 570 and 571 after the rewrite is
|
||||
approved. This amendment adds the requirements only."
|
||||
|
||||
### Risks
|
||||
|
||||
The new lines go at the end of "## Risks and open questions", after the bullet
|
||||
that begins "Trusted mode lets an agent" and before the "## Milestones" heading.
|
||||
- "A DOCX file is a zip archive, so git can't show a line diff of a chapter.
|
||||
Review of a story change goes through the editor and the committed reader,
|
||||
not `git diff`. (Version 1.17.)"
|
||||
- "A converted chapter's DOCX is not in Obsidian's graph. Obsidian shows the
|
||||
chapter only through its archived Markdown, and no DOCX edit reaches that file's
|
||||
links. The DOCX's current links show only in the Console's editor until a
|
||||
Console view of them exists. (Version 1.17.)"
|
||||
- "Conversion can't be undone in place. Front matter, wiki link forms and
|
||||
unsupported blocks may not survive it, and the mirror can't refuse the user's
|
||||
push to an archived file. The controls are the fidelity report, the human's
|
||||
confirmation, an untouched original on refusal, and the kept archive.
|
||||
(Version 1.17.)"
|
||||
- "A restore of the stack's bus alone from a backup taken before an import drops
|
||||
the import's logged events, while the archive commit and the DOCX stay. A
|
||||
restore of the stack's whole host from such a backup also takes the writing
|
||||
store and the host's import records back to before the import. The archive
|
||||
commit stays in the user's Gitea repository and the DOCX stays on the writing
|
||||
store's remote, but the host keeps no record of the import. A bus restore counts
|
||||
import events, and the import's recovery covers both cases (Vikunja 571).
|
||||
(Version 1.17.)"
|
||||
|
||||
## d8 changes (Mos's d8 fix list, check wf_63bba879-180)
|
||||
|
||||
- R1: REQ-LIB-4's tail covers DOCX saves, which agents see at their next lookup after the editor reports them as committed. The notes quote the whole 1.16 sentence. Source: nit/jason/F10.
|
||||
- R2: REQ-LIB-4's new title says the mirror is "the one place agents read Markdown". Source: decisions.n14.
|
||||
- R3: J-b asks whether 1.17 requires the Console Connections view, with Mos's recommendation of yes. Sources: mos1372/F9, jason/F2, anchors/F5.
|
||||
- R4: C2-02 and C2-03b gate 10-27, C2-11a and C2-11b are slice rows that don't, and "F42 wins" is gone. New J-k. Sources: anchors/F6, jason/F5.
|
||||
- R5: where the landed 571 design differs, this text holds. Sources: anchors/F8, adversarial/F8 item 1, jason/F8, critic/C6, G16's design follow-on.
|
||||
- R6: `library.convert` stays out of `ACTIONS`, and REQ-WAIT-1's hard-wait list doesn't change. Sources: gyro571/F1, adversarial/F8 item 3, critic/C6.
|
||||
- R7: a repository on the stack's host never counts as the writing store's remote, and Item 2 says so. Sources: mos1372/F2, adversarial/F1, gyro571/F2.
|
||||
- R8: "no agent credential reaches it" becomes "no agent can reach it with any credential". Source: Fenton's B1 under mos-1379.
|
||||
- R9: no playground DOCX becomes canon in 1.17, and a promotion of one is refused. New J-i. Sources: mos1372/F8, adversarial/F2.
|
||||
- R10: REQ-LIB-9 restates Q195's pin and right-click thesaurus, and its cite gains D4 and D22. Source: critic/C4.
|
||||
- R11: REQ-LIB-9's license bar is the licenses its independent security review accepted. New J-l. Source: critic/C3.
|
||||
- R12: no text for D16's narrow-window tabs. Mos records that reading in STATE. Sources: jason/F1, second verifier vote.
|
||||
- R13: no lookup returns a file's archived copy before publication. Source: adversarial/F5 part 3.
|
||||
- R14: a restore of the whole host from a backup taken before an import is a fourth recovery case. Source: adversarial/F6.
|
||||
- M1: REQ-LIB-4's writing-store sentences follow the later bus rows sentence and add the off-host remote rules and DOCX read timing. The note quotes both 1.16 sentences. Sources: mos1372/F2, adversarial/F1, gyro571/F2, anchors/F4, nit/jason/F10, adversarial/F5 part 1, Fenton B1.
|
||||
- M2: REQ-LIB-8's order bullet adds the remote's confirmation, the old-path read rule and "archive push". Sources: mos1372/F2 and the other remote findings, mos1372/F7, adversarial/F5 parts 2 to 4.
|
||||
- M3: REQ-LIB-8's gate bullet has four conditions, adding the remote. Sources: the remote findings, critic/C1 and C2 edit 2.
|
||||
- M4: the 1.17 note on when conversion opens restates the four conditions and drops W4b. Sources: jason/F5, the remote findings.
|
||||
- M5: Item 2 rewritten with the remote rules. Sources: the remote findings.
|
||||
- M6: the 1.12 gating note rewritten. Sources: anchors/F6, jason/F5.
|
||||
- M7: REQ-LIB-9 gains the split pane, the pin, the thesaurus, the license bar and the runtime load rule, and cites more of the design. Sources: jason/F1, critic/C4, critic/C3, nit/anchors/F12, nit/gyro571/F9.
|
||||
- M8: REQ-LIB-2, the one-way bullet and the C1 note keep a playground DOCX out of canon in 1.17. Sources: mos1372/F8, adversarial/F2.
|
||||
- M9: REQ-LIB-5 says what the reader can't read, and the import turns web links into plain text. New J-j. Sources: critic/C1, critic/C2.
|
||||
- M10: an exclusion of a whole book folder covers that book's DOCX documents. Source: adversarial/F3, with B5.
|
||||
- M11: the human-verbs sentence and the 571 list item name `library.convert` and REQ-WAIT-1. Sources: gyro571/F1, adversarial/F8 item 3, critic/C6.
|
||||
- M12: J-b rewritten. Sources: mos1372/F9, jason/F2, anchors/F5, gyro571/F3, critic/C6.
|
||||
- M13: J-d puts the agent read model to Jason as his call. Source: mos1372/F1.
|
||||
- M14: Status moves to version 1.17 and names REQ-LIB-9. Sources: anchors/F2, mos1372/F4, critic/C7.
|
||||
- M15: the 1.17 source line quotes Q235 in full (mos-1446) and the REQ-LIB-9 sources, at b99ca86b9. Sources: critic/C5, anchors/F9, jason/F8 pin part, nit/gyro571/F8, critic/C6 pin part.
|
||||
- M16: the 571 list lead names the two replaced design parts and the landed design. Sources: anchors/F9, anchors/F8, adversarial/F8 item 1, jason/F8, critic/C6.
|
||||
- Landing swap: Gyro's docs round for R5, R6 and R14 landed as b99ca86b9 (Fenton fenton-0015), so M15 and M16 cite b99ca86b9 in place of 767bb62c7, as the d8 fix list's header says. J-b keeps 767bb62c7 for its line numbers.
|
||||
- M17: W4 section numbers in the remote item and the lookups note. Sources: gyro571/F5, nit/adversarial/F11.
|
||||
- M18: the D7 landing line. Sources: gyro571/F5, the remote findings.
|
||||
- M19: a logged event for each import stage, in REQ-LIB-8 and A2. Source: gyro571/F7.
|
||||
- M20: the Risks line on restores adds the whole-host case. Sources: adversarial/F6, gyro571/F7.
|
||||
- M21: the 571 restore item adds the whole-host case. Source: adversarial/F6.
|
||||
- M22: the graph Risks line and the REQ-LIB-5 note name a Console view. Sources: anchors/F5, jason/F2.
|
||||
- M23: the d6 B3 line drops "F42 wins". Source: anchors/F6.
|
||||
- M24: new Markdown in a converted book, with the old-path and playground exceptions. Source: mos1372/F6.
|
||||
- M25: J-c's last sentence is Mos's reading. Source: mos1372/F10.
|
||||
- M26: J-h rewritten with the D13 defaults. Source: jason/F3.
|
||||
- M27: Item 4 rewritten. Sources: jason/F4, gyro571/F4, decisions.unmarked_folders.
|
||||
- M28: the "Not taken" note on unmarked folders. Sources: jason/F4, gyro571/F4, decisions.unmarked_folders.
|
||||
- M29: the import refuses an unmapped file. Sources: gyro571/F4, decisions.unmarked_folders.
|
||||
- M30: placement notes for REQ-LIB-8, REQ-LIB-9 and the Risks lines. Sources: anchors/F3, nit/anchors/F14.
|
||||
- M31: REQ-LIB-4's title and the D11 landing line. Source: decisions.n14.
|
||||
- M32: the Q236 note limits the 1.12 Obsidian note to Markdown files. Source: critic/C8.
|
||||
- M33: the exclusion note adds path exclusions of DOCX documents. Source: anchors/F7.
|
||||
- M34: A9 moves from "Mine" to the impact-map list. Source: decisions.exclusion_by_id.
|
||||
- M35: the D5 landing line. Sources: anchors/F10, mos1372/F5, nit/adversarial/F12.
|
||||
- M36: the D9 and D14 landing lines. Source: mos1372/F1.
|
||||
- M37: the O1 and C3 notes add the off-host remote and its confirmation. Sources: the remote findings.
|
||||
- M38: the REQ-PROJ-3 note. Source: nit/anchors/F11.
|
||||
- M39: REQ-LIB-5's freshness sentence keys on the editor reporting a save as committed. Source: nit/adversarial/F9.
|
||||
- M40: REQ-LIB-6 bars agent requests for a conversion and allows a suggestion in chat. Source: nit/jason/F9.
|
||||
- M41: REQ-LIB-2's opening and old-path rule, and the "Mine" note. Source: nit/adversarial/F10.
|
||||
- M42: REQ-LIB-8's lead sentence on Markdown story files. Source: nit/mos1372/F12.
|
||||
- M43: REQ-LIB-6's citation sentence. Source: nit/anchors/F13.
|
||||
- M44: REQ-LIB-5's version tag uses plain quotes. Source: nit/anchors/F15.
|
||||
- M45: reference codes B5, D12, D10 and B4 name their source. Source: nit/mos1372/F11.
|
||||
- Files the row would own: four files, with the id count going to 87. Sources: anchors/F1, adversarial/F4, decisions.n14 F4.
|
||||
|
||||
## d7 changes (mos-1379, Fenton's 571 B2)
|
||||
|
||||
- REQ-LIB-5 gains Mos's three sentences after the extracted-text sentence. The text agents read has tracked changes accepted. Comments, and text with tracked deletions shown, each wait for a setting only a human turns on, off by default. Its version tag cites Q222 for the two settings, which is the only text here beyond Mos's.
|
||||
- J-d gains Mos's sentence on comments and tracked deletions.
|
||||
- Fenton's B1 is design only. d6's "no agent credential reaches it" holds, and the shared helper stays #431.
|
||||
|
||||
## d6 changes (Webby round 3, webby-0207)
|
||||
|
||||
- B1: titles for REQ-LIB-8 and REQ-LIB-9 in the requirements.json note and the file list. REQ-LIB-9 takes Webby's title. REQ-LIB-8 keeps mine, because Webby's ("...one-way import that archives the Markdown under its old path") leaves out D2's story files started in the editor.
|
||||
- B2: REQ-LIB-2 makes a Markdown file at a converted file's old path unmapped, ahead of the playground and canon rules, so a playground conversion is covered too. REQ-LIB-8's old-path bullet says "neither canon nor playground".
|
||||
- B3: the slice note names Q226 F42's three rows (C2-02, C2-03b, C2-11b). C2-11a joined the slice with C2-11b, because C2-11b needs it. Both are slice rows that don't gate 10-27, as design 9.2, case2-rows.md:1655 and the impact map's A57 say. The 'F42 wins' sentence is gone from the note in d8, so no queue change follows from it.
|
||||
- N10: the cite-scope replacement is scoped to REQ-LIB-2. The 1.14 note's copy stays.
|
||||
- N11: the notes say REQ-LIB-8 adds the by-id exclusion form REQ-LIB-3 doesn't have.
|
||||
- N12: J-h marks the autosave intervals for Jason.
|
||||
- N13: J-b names REQ-LIB-5's "Connections are always visible" tag and Q226's "another way to handle the visual brain map".
|
||||
- N14, not taken: REQ-LIB-4's title stays internal F3's text, as mos-1372 D11 ruled. Webby's alternative, "...and agents read Markdown from it alone" (120 chars), is Mos's call.
|
||||
|
||||
## Where each mos-1372 item landed
|
||||
|
||||
- D1: REQ-LIB-2's DOCX sentences, the REQ-LIB-8 lead and import bullet, C1 above, and the notes. "Playground files stay Markdown in 1.17" is gone.
|
||||
- D2: REQ-LIB-2's "for one the human starts in the editor" and the REQ-LIB-8 new-story-file bullet. The universe-and-book note is now true.
|
||||
- D3: the REQ-LIB-8 order bullet. This also settles N8.
|
||||
- D4: REQ-LIB-8's one-way bullet, which carries the archive refusal and consequence F2's text, and the 571 list item.
|
||||
- D5: it landed in REQ-LIB-2's "a Markdown file at a converted file's old path is unmapped" in Webby's B2 form, and in the REQ-LIB-8 old-path bullet.
|
||||
- D6: REQ-LIB-5's freshness sentences.
|
||||
- D7 and mos-1375: REQ-LIB-4's remote sentences, the remote step in REQ-LIB-8's order bullet, the fourth opening condition and the 1.17 note on when conversion opens, plus the 571 list item on W4 section 7.3, which replaces the no-remote rule of the old W4 section 7.4. The impact map's item 2 adds "only the stack's host pushes, and no agent credential reaches it".
|
||||
- D8: the REQ-LIB-5 replacement, the import bullet's wiki-link sentence, the Risks line, the note quoting the old sentence, and "REQ-LIB-1 only gains sentences".
|
||||
- D9: the 1.17 note that agents read a converted story file through the Case 2 lookups, from the d4 check's consistency B2, and J-d, which puts the read model to Jason as his call.
|
||||
- D10: the d4 check's B5 sentence, in REQ-LIB-8.
|
||||
- D11: internal F3's clause in the REQ-LIB-4 section, and in the notes the title as Mos amended it for N14.
|
||||
- D12: the whole 1.16 sentence replaced, and quoted in full in the notes.
|
||||
- D13: consequence F1's text, in REQ-LIB-4 and REQ-LIB-8's first bullet.
|
||||
- D14: the row text from the d4 check's consistency B1, in the mark-and-move bullet and C3 above.
|
||||
|
||||
## What d5 adds beyond mos-1372 (for Webby and Mos to check)
|
||||
|
||||
From the impact map, folded as mos-1368 item 1 asked:
|
||||
- A1: the Console shows a cite's format and converted state (REQ-LIB-2).
|
||||
- A2: the logged events and the several-humans setting, default owner only, under Q222.
|
||||
- A3: the import is outside the vocabulary, the hard-wait list is unchanged, and the archive move isn't `data.delete`. The C6 code site is in the 571 list.
|
||||
- A4: the section lead and REQ-LIB-1's writing-store sentence.
|
||||
- A6: format and location in every answer, extracted text with DOCX locators, links across formats.
|
||||
- A7: read-only extends to the store and the archive, no agent action on a story file in any format, no agent DOCX write, and role contracts state the formats. C1's role contract line is a 571 build item.
|
||||
- A8: the DOCX cite shape, and a cite naming an archived file as current is refused.
|
||||
- A9: a hybrid sees a source's DOCX canon through REQ-LIB-2's source scope, and REQ-LIB-8 lets an exclusion name a DOCX document by its id. The id form lets the human exclude a single DOCX started in the editor, which has no old path. An archived file isn't canon, so no hybrid sees it.
|
||||
- A10: REQ-LIB-9, so the count is 87, not 86.
|
||||
- A11: the Hermes gate, from item 3.
|
||||
- A12: the C2-19 promotion sentence.
|
||||
- A13: the broker's path check treats the archive folder as story.
|
||||
- A14 and C5: two Risks lines.
|
||||
- A15: the flagged-new-file bullet. It sits beside the note from the d4 check's B4, "a new Markdown file in a book folder is still canon". The file stays canon and is offered for import.
|
||||
- A16: three titles change and two stay.
|
||||
- C2: manifest order for the manuscript lookup.
|
||||
- F3: the C2-02 gating note.
|
||||
- F4: Mos's measurement.
|
||||
|
||||
Mine, beyond either source:
|
||||
- REQ-LIB-2 opens "A Markdown file's scope comes from its path and from past imports". DOCX scope comes from the source, so "a file's" would be false.
|
||||
- REQ-LIB-9's autosave sentence. It is Mos's reading of F41's "instantly committed", with human-set intervals. The exact intervals stay in the design.
|
||||
|
||||
Not taken:
|
||||
- Impact map item 4's "files in unmarked folders are eligible one at a time", for folders outside every book folder and playground only. Their files are unmapped under REQ-LIB-2, so a DOCX made from one would have no universe or book to keep. The human maps such a folder into a book folder or a playground first, under REQ-LIB-1. A file in an unmarked folder inside a book folder or a playground is canon or playground, and the import takes it one file at a time.
|
||||
- A6's named chapter-links view. D8 takes B8's "no graph shows them yet", and J-b puts the view to Jason.
|
||||
|
||||
## Marked for Jason (additions in the text he sees)
|
||||
|
||||
- J-a. Whether "We will not run the systems in parallel" applies per chapter or as one switch per book. His call. As written, it applies per chapter.
|
||||
- J-b. A converted chapter's DOCX is not in Obsidian's graph. Obsidian shows the chapter only through its archived Markdown, and no DOCX edit reaches that file's links. REQ-LIB-5 still cites two TARGET lines, "Visualization of data via Obsidian or equivalent is required" and "Connections are always visible". Mos's reading is that 1.17 as written meets neither line for converted chapters. Their current links show to the user only as clickable text inside the editor, and no graph or list shows them. Q226 leaves room for "another way to handle the visual brain map". The O2 design that landed for Vikunja 571 at 767bb62c7 holds a Console Connections view and its tests as later work that waits for this answer. His call whether 1.17 requires that view. As written, it does not. Mos recommends that it does, because impact map A6 says "Recommended: name the view" and TARGET says "Connections are always visible".
|
||||
- J-c (mos-1374): "The store pushes to a remote (D7), and the Case 2 VM is in the nightly PBS backup. For a fixed restore point before her first real import, a manual backup of VM 1012 with PBS protect runs first. That step is reversible and needs no reboot." Mos's reading is that this sits inside the P5 go step, so it needs no new question.
|
||||
- J-d. How agents read a converted chapter, D9. His call. As written, an agent reads it through the ordinary Case 2 lookups in any thread or room, under the same project and universe access as Markdown canon. This is Mos's reading of F41 and REQ-LIB-7. The other choice is the model in the earlier O2 design, W4 sections 7.1 and 7.2. Under it, an agent reads a converted chapter only in a new writing conversation that holds one human and one agent, only after the business owner grants that agent access to that document, and by default only what the human attaches to each message. Comments and tracked deletions stay hidden from agents until a human turns on a setting for each. Markdown has neither, so the default keeps agents at the access Markdown gives them. Those two sentences are Mos's ruling mos-1379. A yes to the text as written settles it.
|
||||
- J-e. Versioning means the editor's tracked changes plus one git commit per save.
|
||||
- J-f. A converted chapter can be edited only in the Console while the stack is reachable. Obsidian no longer edits it offline.
|
||||
- J-g. The import takes Markdown only. Importing .doc files stays a separate task.
|
||||
- J-h. Autosave under REQ-LIB-9. Jason's Q226 F41 says "All changes are instantly committed and available to the agents." Mos's reading, recorded with that ruling, is "Each save is a commit at once, and agents read it at their next lookup." At the O2 design's D13 defaults, a save commits at most 2 seconds after a pause in typing or 15 seconds into steady typing, with no human action needed. Mos's reading in mos-1359 counts that delay as "instantly committed". Only a human changes the intervals. The PRD names no values, and the defaults stay in the design. Whether a delay of seconds fits his word "instantly" is his call, so this is marked for him.
|
||||
- J-i. In 1.17 a playground story that is DOCX can't become canon. That covers a playground Markdown file the human imports, a story the human starts in a playground in the editor, and the DOCX of a draft universe after it is made real. Today Melanie promotes a playground file by moving it into a book folder in Obsidian, and a DOCX in the writing store can't be moved that way. She can start a new story in the book and paste the text in, but it gets a new document id and the playground copy keeps the history. A later version adds DOCX promotion with C2-19, which comes after the slice.
|
||||
- J-j. Web links, text boxes and fields in a converted chapter. Jason's Q226 F41 says "All changes are instantly committed and available to the agents." The reader in this version can't read a web link, a text box, a field or hidden text. As written, the import turns each web link into plain text that keeps its label and address, and the human confirms that in the fidelity report. A web link that can't be kept safely as plain text refuses the import. If a later edit adds one of these, the save keeps it and the editor warns the human. Agents then get none of that part's text until a save takes it out.
|
||||
- J-k. The 1.12 note Jason approved says bus writes, C2-02 and C2-03b, don't gate 10-27. His Q226 "F42: ok" moved them into the 10-27 slice, and design 9.2 counts them in the smallest slice that lets Melanie start. Mos reads that as making them gate 10-27. The editor rows C2-11a and C2-11b still don't gate it, per his Q195 words "we need to get it moving as an add-on".
|
||||
- J-l. REQ-LIB-9 does not use REQ-PROJ-3's "permissive license" bar. It takes the licenses that the editor's independent security review accepted, because that review cleared fonts under the SIL Open Font License and the Ubuntu Font License, which not every reader counts as permissive. Mos's reading.
|
||||
|
||||
Marked as changes beyond P1 to P6, from the impact map (Q17, item 5):
|
||||
- A1 (archived scope and canon cites)
|
||||
- A2 (the conversion requirement, REQ-LIB-8)
|
||||
- A3 (outside the vocabulary, hard-wait list unchanged)
|
||||
- A6 (lookups across formats)
|
||||
- A7 (agent bounds)
|
||||
- A8 (DOCX cites)
|
||||
- Item 2 and mos-1375: each writing-store commit is pushed to a remote off the stack's host. Only a human sets it, it starts unset, and a repository on the stack's host doesn't count. Only the stack's host pushes to it, and no agent can reach it with any credential. Import and new story files stay closed until the remote is set and checked, and each import's archive push waits until the remote holds the DOCX commit. This keeps "Git is used for all changes -- local and remote" true for DOCX chapters.
|
||||
- Item 3 (the Hermes gate)
|
||||
- Item 4. Canon and playground story files convert one file at a time, including files in unmarked folders inside a book folder or a playground. Type-folder and supporting files stay Markdown. A story file outside every book folder and playground has no universe or book, so it converts only after a human maps its folder into a book folder or a playground. The mapping step is Mos's reading of P1 and Q30.
|
||||
|
||||
The F4 measurement goes with them.
|
||||
|
||||
## Files the row would own
|
||||
|
||||
The id count goes from 85 to 87. 1.16 owned three files because its count stayed at 85. Like 1.13, the last version that added ids, the row owns four files:
|
||||
- `docs/prd/mosaic-stack.md`
|
||||
- `packages/tasks/requirements.json`: the version 1.17, the two new ids REQ-LIB-8 and REQ-LIB-9 with their titles, and the changed titles of REQ-LIB-1, REQ-LIB-2 and REQ-LIB-4. The new ids go after REQ-LIB-7 and before REQ-INST-1, in the same order as the PRD's bullets.
|
||||
- `packages/tasks/tests/requirements.test.mjs`: the version pin 1.17, the id count of 87, and the duplicate-id message, which goes from `requirements[85].id: REQ-ROLE-1 twice` to `requirements[87].id: REQ-ROLE-1 twice`.
|
||||
- `packages/bus/tests/requirements.test.mjs`: the list length, which goes from 85 to 87.
|
||||
|
||||
The gate would match 1.16's:
|
||||
1. A reviewer approves the text.
|
||||
2. Jason says yes to the exact text through Mos.
|
||||
3. Both `requirements.test.mjs` files, in `packages/tasks/tests` and `packages/bus/tests`, and every `scripts/test-*.sh` that reads the PRD or `requirements.json` are green on Sage's gate.
|
||||
4. Mos gets the landing commit.
|
||||
@@ -1,747 +0,0 @@
|
||||
--- DRAFT-d7.md 2026-10-22 20:44:39.909606789 -0500
|
||||
+++ DRAFT.md 2026-10-23 06:16:54.370223847 -0500
|
||||
@@ -1,12 +1,12 @@
|
||||
# PRD 1.17 draft: Case 2 story files are DOCX (Q235 to Q237, P1 to P6)
|
||||
|
||||
-Sage, 2026-10-23, for mos-1366 item 1 and Vikunja 570. Draft 7. It is d6 plus Mos's ruling mos-1379 on Fenton's 571 B2 (see "d7 changes"). d6 is d5 with Webby's round 3 (webby-0207) fixed: B1 to B3 and N10 to N13, with N14 left for Mos (see "d6 changes"). d5 folds in:
|
||||
+Sage, 2026-10-23, for mos-1366 item 1 and Vikunja 570. Draft 8. It is d7 plus Mos's d8 fix list mos-1443 (see "d8 changes"). d7 is d6 plus Mos's ruling mos-1379 on Fenton's 571 B2 (see "d7 changes"). d6 is d5 with Webby's round 3 (webby-0207) fixed: B1 to B3 and N10 to N13, with N14 left for Mos (see "d6 changes"). d5 folds in:
|
||||
- Mos's d4 check ruling mos-1372 (D1 to D14; D15 was dropped).
|
||||
- mos-1374, which replaces J-c.
|
||||
- The impact map mos-1368 (jason-master-restart d183246, `projects/mosaic-mvp/case2-docx-impact-map.md`: A1 to A16, critic items C1 to C6, items 2 to 7).
|
||||
- Mos's F4 measurement.
|
||||
|
||||
-Review order (B5): Webby, then Mos, then Jason. Base: PRD 1.16, `docs/prd/mosaic-stack.md` blob a6db9b4a at 482e865ac.
|
||||
+Review order (mos-1367 B5): Webby, then Mos, then Jason. Base: PRD 1.16, `docs/prd/mosaic-stack.md` blob a6db9b4a at 482e865ac.
|
||||
1.16 lands first (row 291), and this text is a new version on top of it. Nothing here is built or queued. The impact map's queue changes (A24, A57 to A59) go through `scripts/mosaic queue` after 1.17 is approved (C9).
|
||||
|
||||
Sources, verbatim in Mos's DECISIONS:
|
||||
@@ -19,11 +19,12 @@
|
||||
|
||||
These stand as ruled. d5 changes only what mos-1372 changed.
|
||||
|
||||
-- **O1. Where a converted chapter lives.** The DOCX lives in the O2 writing store
|
||||
- (D12), and the archived Markdown stays in the user's repository under a
|
||||
+- **O1. Where a converted chapter lives.** The DOCX lives in the writing store of
|
||||
+ O2 design D12, and the archived Markdown stays in the user's repository under a
|
||||
human-marked archive folder. Ruled yes in B1, on the condition that the text
|
||||
says plainly that a converted chapter leaves the Gitea-mirrored repository and
|
||||
- lives in the stack's writing store. mos-1372 D7 adds a remote for the store.
|
||||
+ lives in the stack's writing store. mos-1372 D7 and mos-1375 add a remote for
|
||||
+ the store, off the stack's host.
|
||||
- **O2. The unit of conversion.** One story file per import, refusing a file
|
||||
that is already converted. Ruled yes in B2: each file gets its own fidelity
|
||||
report, human confirmation, manifest and commit.
|
||||
@@ -40,15 +41,16 @@
|
||||
universe, book, and canon or playground. A playground DOCX follows the
|
||||
playground rules and is never returned as canon. The import accepts canon and
|
||||
playground story files. Type-folder files and supporting files stay Markdown
|
||||
- (P4). This also settles the impact map's Q18 (item 4) without a narrowing for
|
||||
- Jason.
|
||||
+ (P4). This also settles the impact map's Q18, item 4. It leaves one narrowing
|
||||
+ for Jason, J-i. A playground DOCX can't become canon in 1.17.
|
||||
- **C2 stands.** The move keeps the file's path under the archive folder:
|
||||
`book1/ch3.md` goes to `<archive>/book1/ch3.md`. An archived file's universe
|
||||
and book are those of its old path.
|
||||
- **C3 is replaced by D3 and D14.** The archive commit is written by a new
|
||||
- human-only bus step (Vikunja 571) on the C2-02 write plumbing and pushed
|
||||
- through C2-03b. The order is the store commit, then the archive commit and its
|
||||
- push, then publication to the lookups.
|
||||
+ human-only bus step (Vikunja 571) on the C2-02 write plumbing and pushed through
|
||||
+ C2-03b. The order is the store commit and the remote's confirmation that it
|
||||
+ holds that commit, then the archive commit and its push, then publication to the
|
||||
+ lookups.
|
||||
- **N4 stands.** REQ-LIB-8 says "a real user's books". The PRD names no user
|
||||
anywhere in Case 2.
|
||||
|
||||
@@ -56,19 +58,33 @@
|
||||
|
||||
### Status and sources
|
||||
|
||||
-Status gains, after the 1.16 sentence: "Version 1.17 records Jason's rulings Q235
|
||||
-to Q237 of 2026-10-23: Case 2 story files are DOCX, Markdown stays for agent files
|
||||
-and documentation, and a human-started import converts a Markdown story file one
|
||||
-way. It changes what Case 2 requirements allow, so Mos puts the text to Jason as
|
||||
-written, and it lands only after his yes (mos-1366, Vikunja 570)."
|
||||
+In the Status bullet's first line, "- Status: approved, version 1.16." becomes
|
||||
+"- Status: approved, version 1.17." Status gains, after the two 1.16 sentences at
|
||||
+the end of the bullet: "Version 1.17 records Jason's rulings Q235 to Q237 of
|
||||
+2026-10-23: Case 2 story files are DOCX, Markdown stays for agent files and
|
||||
+documentation, and a human-started import converts a Markdown story file one way.
|
||||
+It also adds REQ-LIB-9, the Console's DOCX editor, from Jason's rulings Q195, Q226
|
||||
+and Q234. It changes what Case 2 requirements allow, so Mos puts the text to Jason
|
||||
+as written, and it lands only after his yes (mos-1366, Vikunja 570)."
|
||||
|
||||
New source line, above the 1.16 one: "Version 1.17 source: Jason's Q235, answering
|
||||
-Q36, his Q236 'For creative writing chapters, we need to utilize docx as the
|
||||
-standard. Markdown is acceptable for agent files, instructions, PRDs,
|
||||
-documentation, etc. The creative writing files should be docx for familiarity for
|
||||
-the user.', and his Q237 'Q38: It is correct for now (subject to future change)',
|
||||
-confirming Mos's reading P1 to P6. The storage follows the O2 design D10 and D12,
|
||||
-25c09f19f, as rewritten under Vikunja 571."
|
||||
+Q36: 'How about we see a markdown file, we convert the markdown file to docx, then
|
||||
+archive or mark the markdown file as converted. The new standard for files in the
|
||||
+creating writing use case is to use docx to handle versioning and WYSIWYG. We
|
||||
+eliminate the potential for confusion based on the files. Agents must understand
|
||||
+which files are what format and where they live. The system must allow for import
|
||||
+and conversion. We will not run the systems in parallel. There will be an
|
||||
+irreversible conversion of the files.' His Q236 says: 'For creative writing
|
||||
+chapters, we need to utilize docx as the standard. Markdown is acceptable for
|
||||
+agent files, instructions, PRDs, documentation, etc. The creative writing files
|
||||
+should be docx for familiarity for the user.' His Q237 says 'Q38: It is correct
|
||||
+for now (subject to future change)', which confirms Mos's reading P1 to P6.
|
||||
+REQ-LIB-9 rests on his Q195 request for 'a full WYSIWYG editor within Mosaic
|
||||
+Stack', his Q226 answer 'F41: We want to move editing into the WYSIWYG in the
|
||||
+WebUI. All changes are instantly committed and available to the agents.' and his
|
||||
+Q234 answer 'Q37: yes' to the exact security header for the editor's frame. The
|
||||
+storage follows the O2 design D10 to D12 as rewritten under Vikunja 571, at
|
||||
+b99ca86b9 on `refactor`."
|
||||
|
||||
### Creative library, section lead
|
||||
|
||||
@@ -92,20 +108,22 @@
|
||||
is playground, any other Markdown file in a book folder is canon, and everything
|
||||
else is unmapped and never returned. A folder in both lists is supporting." with:
|
||||
|
||||
-"A Markdown file's scope comes from its path alone, prefixes first: a Markdown
|
||||
-file under the archive folder is archived, one under a supporting prefix is
|
||||
-supporting, a Markdown file at a converted file's old path is unmapped
|
||||
-(REQ-LIB-8), one under a playground prefix at any level is playground, any other
|
||||
-Markdown file in a book folder is canon, and everything else is unmapped and never
|
||||
-returned. A folder in
|
||||
-both lists is supporting. The archive folder follows the same placement rules and
|
||||
-may not overlap another prefix or a book folder. An archived file keeps the path
|
||||
-it had under the archive folder, and its universe and book are those of that old
|
||||
-path. A DOCX document in the writing store keeps its source's scope: the
|
||||
-universe, the book if there is one, and canon or playground. Its source is the
|
||||
-Markdown file it was converted from or, for one the human starts in the editor,
|
||||
-the universe and book or the playground the human picks (REQ-LIB-8). A playground
|
||||
-DOCX follows the playground rules and is never returned as canon."
|
||||
+"A Markdown file's scope comes from its path and from past imports, prefixes
|
||||
+first: a Markdown file under the archive folder is archived, one under a
|
||||
+supporting prefix is supporting, a Markdown file at a converted file's old path is
|
||||
+unmapped under REQ-LIB-8 but flagged in the format map, one under a playground
|
||||
+prefix at any level is playground, any other Markdown file in a book folder is
|
||||
+canon, and everything else is unmapped and never returned. A folder in both lists
|
||||
+is supporting. The archive folder follows the same placement rules and may not
|
||||
+overlap another prefix or a book folder. An archived file keeps the path it had
|
||||
+under the archive folder, and its universe and book are those of that old path. A
|
||||
+DOCX document in the writing store keeps its source's scope: the universe, the
|
||||
+book if there is one, and canon or playground. Its source is the Markdown file it
|
||||
+was converted from or, for one the human starts in the editor, the universe and
|
||||
+book or the playground the human picks (REQ-LIB-8). A playground DOCX follows the
|
||||
+playground rules and is never returned as canon. It stays playground after its
|
||||
+draft universe is made real. In version 1.17 no promotion or mapping change makes
|
||||
+a playground DOCX canon. A later version of this PRD says how one becomes canon."
|
||||
|
||||
Replace "Lookups return canon unless the caller asks for playground or
|
||||
supporting." with "Lookups return canon unless the caller asks for playground,
|
||||
@@ -126,89 +144,110 @@
|
||||
Replace "The user commits and pushes with their own tools, today Obsidian with
|
||||
obsidian-git." with "The user commits and pushes Markdown with their own tools,
|
||||
today Obsidian with obsidian-git. A converted story file's current text is no
|
||||
-longer in that repository, which keeps only its archived Markdown (REQ-LIB-8). A
|
||||
-DOCX story file is saved in the Console's editor, and each accepted save is one
|
||||
-commit by the human in the stack's writing store (REQ-LIB-9). Each writing-store
|
||||
-commit is also pushed to a remote the human sets, never by force-push, and the
|
||||
-user sees a push that is pending or failed. Only the stack's host pushes to that
|
||||
-remote, and no agent credential reaches it. Agents read the local commit."
|
||||
-
|
||||
-Replace "Agents read only the mirror's served commit and never hold a copy of their
|
||||
-own" with "Agents read the user's repository only at the mirror's served commit,
|
||||
-read a DOCX story file only at a committed version in the writing store
|
||||
-(REQ-LIB-5), and never hold a copy of their own". The rest of that sentence, ", so
|
||||
-they see the user's push within about a minute.", is unchanged.
|
||||
+longer in that repository, which keeps only its archived Markdown (REQ-LIB-8)."
|
||||
|
||||
-Version tag: "and the sync items.)" becomes "and the sync items. Version 1.17.)"
|
||||
+Add, after "Bus writes and pushes come in later rows (C2-02, C2-03b).": "A DOCX
|
||||
+story file is saved in the Console's editor, and each accepted save is one commit
|
||||
+by the human in the stack's writing store (REQ-LIB-9). Each writing-store commit
|
||||
+is also pushed to a remote off the stack's host, never by force-push. The remote
|
||||
+is a setting only a human changes, and it starts unset. A repository on the
|
||||
+stack's host never counts as that remote. A missing remote or a failed push never
|
||||
+undoes a save, and the user sees each push that is pending or failed. Only the
|
||||
+stack's host pushes to that remote, and no agent can reach it with any credential.
|
||||
+Agents read the local commit."
|
||||
+
|
||||
+Replace "Agents read only the mirror's served commit and never hold a copy of
|
||||
+their own, so they see the user's push within about a minute." with "Agents read
|
||||
+the user's repository only at the mirror's served commit, except a story file
|
||||
+during its import under REQ-LIB-8. They read a DOCX story file only at a committed
|
||||
+version in the writing store, under REQ-LIB-5. They never hold a copy of their
|
||||
+own, so they see the user's Markdown push within about a minute and a DOCX save at
|
||||
+their next lookup after the editor reports it as committed."
|
||||
+
|
||||
+Version tag: "and the sync items.)" becomes "and the sync items. Version 1.17,
|
||||
+with Q222 for the remote setting.)"
|
||||
|
||||
### REQ-LIB-5
|
||||
|
||||
Add, after "Each answer names the commit it read.": "Each answer also names the
|
||||
file's format and where it lives: its path, or its document id in the writing
|
||||
store. A DOCX story file is read from its latest committed save, never from
|
||||
-unsaved text. A lookup that starts after a save is acknowledged returns that save
|
||||
-or a later one, and the answer names the version. Get, search and manuscript read
|
||||
-a DOCX story file as its extracted text with DOCX locators, never as lines. That
|
||||
+unsaved text. A lookup that starts after the editor reports a save as committed
|
||||
+returns that save or a later one, even while its push to the remote is pending or
|
||||
+has failed, and the answer names the version. Get, search and manuscript read a
|
||||
+DOCX story file as its extracted text with DOCX locators, never as lines. That
|
||||
text is the file with its tracked changes accepted. An agent reads a story file's
|
||||
comments, or its text with tracked deletions shown, only after a human turns on
|
||||
the matching setting. Both settings are off by default, and only a human changes
|
||||
-them. The manuscript lookup follows the book's chapter order across both formats (O2 design
|
||||
-D10), and the next chapter it names is never an archived file. Links out and in
|
||||
-resolve across both formats. The universe lookup returns the format map
|
||||
-(REQ-LIB-8)."
|
||||
+them. The reader in this version can't read some things a DOCX story file can
|
||||
+hold, such as a web link, a text box, a field or hidden text. The editor warns the
|
||||
+human when an edit adds one, and the human can still save it. Until a later save
|
||||
+takes it out, lookups give agents none of the text of the part that holds it,
|
||||
+whether that is the chapter's body, a note or a comment. The manuscript lookup
|
||||
+follows the book's chapter order across both formats (O2 design D10), and the next
|
||||
+chapter it names is never an archived file. Links out and in resolve across both
|
||||
+formats. The universe lookup returns the format map (REQ-LIB-8)."
|
||||
|
||||
Replace "The user sees them in Obsidian's graph and backlinks." with "The user sees
|
||||
a Markdown file's links in Obsidian's graph and backlinks. A DOCX story file's
|
||||
wikilinks stay clickable in the Console's editor (O2 design D11), and no graph
|
||||
shows them yet."
|
||||
|
||||
-Version tag: "and \"Connections are always visible\".)" becomes "and \"Connections
|
||||
-are always visible\". Version 1.17, with Q222 for the two settings.)"
|
||||
+Version tag: 'and "Connections are always visible".)' becomes 'and "Connections
|
||||
+are always visible". Version 1.17, with Q222 for the two settings.)'
|
||||
|
||||
### REQ-LIB-6
|
||||
|
||||
Replace "A reply may cite lines of the repository at a commit or pages the agent
|
||||
fetched, and the broker checks every citation before it stores the message." with
|
||||
-"A reply may cite lines of a Markdown file at a commit, a place in a committed DOCX
|
||||
-story file, or pages the agent fetched, and the broker checks every citation
|
||||
+"A reply may cite lines of a Markdown file at a commit, a place in a committed
|
||||
+DOCX story file, or pages the agent fetched, and the broker checks every citation
|
||||
before it stores the message. A DOCX citation never calls a paragraph a line. It
|
||||
names the document id, the committed version and a DOCX locator. A citation that
|
||||
-names an archived file as current is refused. `requireCitation` and a citation
|
||||
-marked as canon work the same way for both kinds."
|
||||
+names an archived file as current is refused. The `requireCitation` setting below
|
||||
+applies to Markdown and DOCX citations alike, and so does the rule for a citation
|
||||
+marked as canon."
|
||||
|
||||
Add, after "the broker refuses such a write before any git call.": "The writing
|
||||
store and the archive folder are read-only to a creative agent as well, and the
|
||||
broker's path check treats the archive folder as story. No agent creates, edits,
|
||||
deletes, converts, archives or restores a story file in any format, and no agent
|
||||
-writes a DOCX. No creative agent starts, requests or undoes a conversion
|
||||
-(REQ-LIB-8). Each creative role's contract states which files are DOCX and which
|
||||
-are Markdown, and cites a DOCX story file by its locator, never by line."
|
||||
+writes a DOCX. No creative agent starts or undoes a conversion, and none asks for
|
||||
+one through a tool or a decision it raises, as REQ-LIB-8 says. An agent may still
|
||||
+suggest a conversion to the human in chat. Each creative role's contract states
|
||||
+which files are DOCX and which are Markdown, and cites a DOCX story file by its
|
||||
+locator, never by line."
|
||||
|
||||
Version tag, inside the closing parenthesis: "Version 1.15.)" becomes "Version
|
||||
1.15. Version 1.17.)"
|
||||
|
||||
### New REQ-LIB-8
|
||||
|
||||
+This bullet goes after REQ-LIB-7 and before the "### Installer" heading.
|
||||
+
|
||||
"- **REQ-LIB-8.** Story files become DOCX. DOCX is the standard for chapters and
|
||||
the other story text in a Case 2 writing project, canon and playground alike. A
|
||||
story file becomes DOCX through a human's import (below), or when the human
|
||||
- starts it in the editor. From then on DOCX is its only working format, edited
|
||||
- in the Console's editor (REQ-LIB-9). Until its import a story file stays
|
||||
- Markdown. Files in a type folder (REQ-LIB-1), such as character and place
|
||||
- notes, stay Markdown. So do supporting files, agent files, instructions, PRDs
|
||||
- and documentation, including the character sheets, summaries and cross-links
|
||||
- agents keep under REQ-LIB-6.
|
||||
+ starts it in the editor. From then on DOCX is its only working format, edited in
|
||||
+ the Console's editor (REQ-LIB-9). A Markdown story file stays Markdown until its
|
||||
+ import. Files in a type folder (REQ-LIB-1), such as character and place notes,
|
||||
+ stay Markdown. So do supporting files, agent files, instructions, PRDs and
|
||||
+ documentation, including the character sheets, summaries and cross-links agents
|
||||
+ keep under REQ-LIB-6.
|
||||
- A converted story file's current text leaves the user's Gitea-mirrored
|
||||
repository. Its DOCX lives in the stack's writing store, on the stack's host,
|
||||
and not in the repository the user pushes or opens in Obsidian. Only its
|
||||
archived Markdown stays there.
|
||||
- - An import converts one Markdown story file, canon or playground, outside
|
||||
- every type folder (REQ-LIB-1), to a DOCX document in the writing store. It
|
||||
- refuses a supporting, archived or type-folder file, and a file that is
|
||||
+ - An import converts one Markdown story file, canon or playground, outside every
|
||||
+ type folder (REQ-LIB-1), to a DOCX document in the writing store. It refuses
|
||||
+ an unmapped, supporting, archived or type-folder file, and a file that is
|
||||
already converted. Each import has its own fidelity report, the human's
|
||||
- confirmation of that report, a manifest naming the source file and its
|
||||
- commit, and one commit in the store. The DOCX keeps every wiki link of the
|
||||
- source as written, and a lost link fails the fidelity report.
|
||||
+ confirmation of that report, a manifest naming the source file and its commit,
|
||||
+ and one commit in the store. The DOCX keeps every wiki link of the source as
|
||||
+ written, and a lost link to another library file fails the fidelity report. A
|
||||
+ web link becomes plain text that keeps its label and address, and the fidelity
|
||||
+ report lists it for the human to confirm. A web link that can't be kept safely
|
||||
+ as plain text refuses the import.
|
||||
- The human can also start a new story file in the editor, in a universe and
|
||||
book or a playground the human picks. It is a DOCX document in the writing
|
||||
store from its first commit, with no Markdown copy, and it opens under the
|
||||
@@ -219,61 +258,81 @@
|
||||
repository. A new human-only bus step (Vikunja 571) on the C2-02 write
|
||||
plumbing writes it, and C2-03b pushes it. The move keeps the bytes and the
|
||||
git history, so it isn't `data.delete`.
|
||||
- - The store commit comes first, then the archive commit and its push, then
|
||||
- publication to the lookups. Until publication the Markdown stays canon at
|
||||
- its old path, and agents read the source at the commit the import started
|
||||
- from. A refusal or failure before the push leaves the Markdown unmoved and
|
||||
- no DOCX that a lookup returns. A failure after the push leaves a pending
|
||||
- import that the human sees and can resume, never a claim that nothing moved.
|
||||
- - Each import writes one logged event naming the source file's path, commit
|
||||
- and blob and the new document id.
|
||||
+ - The store commit comes first, and the writing store's remote must confirm it
|
||||
+ holds that commit. Then come the archive commit and its push, then publication
|
||||
+ to the lookups. Until publication the Markdown at its old path keeps its canon
|
||||
+ or playground scope. Agents read that file at the commit the import started
|
||||
+ from, even after the mirror's served commit reaches the archive commit or a
|
||||
+ later one. No lookup returns the file's archived copy before publication, even
|
||||
+ one that asks for archived files. A refusal or failure before the archive push
|
||||
+ leaves the Markdown unmoved and no DOCX that a lookup returns. A failure after
|
||||
+ the archive push leaves a pending import that the human sees and can resume,
|
||||
+ never a claim that nothing moved. An archive push whose result is unknown
|
||||
+ counts as a failure after the archive push until the stack reads the result
|
||||
+ back from the user's remote.
|
||||
+ - Each stage of an import writes a logged event. The import's record on the
|
||||
+ stack's host names the source file's path, commit and blob and the new
|
||||
+ document id, and each event points to that record.
|
||||
- After a conversion, a Markdown file at the converted file's old path is neither
|
||||
canon nor playground. Lookups leave it out, the format map flags it, and the human is told.
|
||||
- A new Markdown story file in a book folder that holds converted files stays
|
||||
- canon until its import. The Console flags it and offers the import. Nothing
|
||||
+ canon until its import, unless it sits at a converted file's old path or under
|
||||
+ a playground prefix. The Console flags it and offers the import. Nothing
|
||||
converts it on its own.
|
||||
- A hybrid's exclusion that covers a converted file's old path also covers its
|
||||
- DOCX document (REQ-LIB-3). An exclusion can also name a DOCX document by its
|
||||
- id.
|
||||
+ DOCX document (REQ-LIB-3). An exclusion of a whole book folder also covers
|
||||
+ every DOCX document in that book, including one started in the editor. An
|
||||
+ exclusion can also name a DOCX document by its id.
|
||||
- Only a human starts an import or a new story file, from the CLI or a Console
|
||||
- session signed in as that human. Both are human verbs outside the agent
|
||||
- action vocabulary, so no role holds them, no agent can request them, and
|
||||
- REQ-WAIT-2's list is unchanged. In an organization with several humans, who
|
||||
- may start them is a setting only a human changes, and the default is the
|
||||
- owner only.
|
||||
- - Conversion is one way, with no parallel run. Neither the Console nor any
|
||||
- agent edits a converted story file as Markdown, and no DOCX edit syncs back
|
||||
- to Markdown. The Console's Markdown save refuses every file under the archive
|
||||
+ session signed in as that human. Both are human verbs outside the agent action
|
||||
+ vocabulary. Neither is added to `ACTIONS` in the business vocabulary or to the
|
||||
+ broker's always-gated list, including the import's action, `library.convert`.
|
||||
+ No role holds them, no agent can request them, and the hard-wait list in
|
||||
+ REQ-WAIT-1 doesn't change. In an organization with several humans, who may
|
||||
+ start them is a setting only a human changes, and the default is the owner
|
||||
+ only.
|
||||
+ - Conversion is one way, with no parallel run. Neither the Console nor any agent
|
||||
+ edits a converted story file as Markdown, and no DOCX edit syncs back to
|
||||
+ Markdown. The Console's Markdown save refuses every file under the archive
|
||||
folder. The user's own tools can still change the archived Markdown, and no
|
||||
such change reaches the DOCX. The old Markdown stays in git history, and
|
||||
nothing rewrites history. A promotion into a book folder (C2-19) runs the
|
||||
- import for a Markdown story file or is refused.
|
||||
+ import for a Markdown story file or is refused. A promotion of a playground
|
||||
+ DOCX is refused in version 1.17.
|
||||
- Agents get a format map: for each mapped folder and story file, its format,
|
||||
scope and where it lives, archived files, flagged files and pending imports
|
||||
included.
|
||||
- - The import and new story files ship closed. They open only after three things.
|
||||
- The editor ships. Agents can read committed DOCX story files through the
|
||||
- lookups and cite them (REQ-LIB-5, REQ-LIB-6). Any earlier agent system that
|
||||
- writes the user's files has stopped, which for Case 2 is the Hermes
|
||||
- retirement (#423 step 5). So agents never lose the current chapter, and no
|
||||
- second system writes the story. The first import of a real user's books
|
||||
- waits for Jason's go.
|
||||
+ - The import and new story files ship closed. They open only after four things.
|
||||
+ The editor ships. The human has set the writing store's remote, and the stack
|
||||
+ has checked that it can push there. Agents can read committed DOCX story files
|
||||
+ through the lookups and cite them (REQ-LIB-5, REQ-LIB-6). Any earlier agent
|
||||
+ system that writes the user's files has stopped, which for Case 2 is the
|
||||
+ Hermes retirement (#423 step 5). So the import itself never cuts agents off
|
||||
+ from a chapter, the chapter's current text never lives only on the stack's
|
||||
+ host, and no second system writes the story. The first import of a real user's
|
||||
+ books waits for Jason's go.
|
||||
(Q235, Q236, Q237: P1 to P6. Q222 for the setting. O2 design D10 to D12.
|
||||
Version 1.17.)"
|
||||
|
||||
### New REQ-LIB-9
|
||||
|
||||
+This bullet goes after REQ-LIB-8.
|
||||
+
|
||||
"- **REQ-LIB-9.** The Console's DOCX editor. The human edits a DOCX story file in
|
||||
- the Console's editor, on a page of its own. Only a human saves. Saves happen
|
||||
- on their own while the human types (Q226), at intervals only a human changes,
|
||||
- and each accepted save is one commit with the human as author, pushed as
|
||||
- REQ-LIB-4 says. A save made against an older version than the current one is
|
||||
+ the Console's editor, in a split pane with the agent chat alongside it. The
|
||||
+ human can pin an agent chat to a document. The human can select a word,
|
||||
+ right-click it, and choose a synonym from a thesaurus. Only a human saves. Saves
|
||||
+ happen on their own while the human types (Q226), at intervals only a human
|
||||
+ changes, and each accepted save is one commit with the human as author, pushed
|
||||
+ as REQ-LIB-4 says. A save made against an older version than the current one is
|
||||
refused. Agents never write a DOCX. Versioning is the editor's tracked changes
|
||||
- plus one git commit per save. The editor's code is vendored and pinned, with
|
||||
- its license and a hash per file, and nothing loads at runtime. The editor's
|
||||
- frame sends exactly the content security policy Jason approved in Q234, and
|
||||
- the WebUI shell's own header is unchanged. REQ-PROJ-3's project docs editor
|
||||
- is unchanged. (Q195, Q226, Q234, Q236. O2 design D10 and D14. Version 1.17.)"
|
||||
+ plus one git commit per save. The editor's code is vendored and pinned, with a
|
||||
+ hash per file and the licenses that its independent security review accepted. At
|
||||
+ runtime the editor loads only files that the stack itself serves, and it
|
||||
+ requests nothing from any other host. The editor's frame sends exactly the
|
||||
+ content security policy Jason approved in Q234, and the WebUI shell's own header
|
||||
+ is unchanged. REQ-PROJ-3's project docs editor is unchanged. (Q195, Q226, Q234,
|
||||
+ Q236. O2 design D3, D4, D6, D8, D10, D13, D14, D16 and D22. Version 1.17.)"
|
||||
|
||||
### Version 1.17 notes
|
||||
|
||||
@@ -285,40 +344,52 @@
|
||||
- The 10-27 Case 2 release ships on Markdown as built (P6). The 1.11 line 'The
|
||||
Case 2 MVP for 10-27 is the Markdown library (#416). The WYSIWYG editor (Q195,
|
||||
Q196) is an add-on that doesn't gate it.' still holds. Conversion opens after
|
||||
- 10-27, after W4b, and after Hermes is retired (#423 step 5).
|
||||
- - The 1.12 note says bus writes and the Console editor (C2-02, C2-03b, C2-11a,
|
||||
- C2-11b, C2-19) don't gate 10-27. Jason's Q226 F42 later moved three of them,
|
||||
- C2-02, C2-03b and C2-11b, into the 10-27 slice, and that later ruling holds.
|
||||
- C2-11a and C2-19 still don't gate 10-27. Where a plan or queue record names
|
||||
- a different set, F42 wins, and the record is corrected through its own
|
||||
- process.
|
||||
- 1.17 changes neither, and C2-11b's Markdown editor never edits a converted
|
||||
- story file.
|
||||
- - Q236 narrows Q176's editor choice to DOCX for story files (REQ-LIB-9).
|
||||
- - This replaces the superseded-notice proposal in O2 design D12 (Fenton F1),
|
||||
- which is withdrawn, and the keep-Markdown-at-its-path model of D11. Gyro's
|
||||
- rewrite of the O2 design (Vikunja 571) carries the details:
|
||||
+ 10-27, and only once REQ-LIB-8's four conditions are met. The editor ships,
|
||||
+ the writing store's remote is set and the stack has checked that it can push
|
||||
+ there, agents can read and cite committed DOCX story files through the
|
||||
+ lookups, and Hermes is retired, which is #423 step 5.
|
||||
+ - The 1.12 note says five bus write and Console editor rows, C2-02, C2-03b,
|
||||
+ C2-11a, C2-11b and C2-19, don't gate 10-27. Jason's Q226 F42 later moved
|
||||
+ C2-02, C2-03b and C2-11b into the 10-27 slice. The Case 2 design brings C2-11a
|
||||
+ in with them, because C2-11b needs it. C2-19 stays outside the slice. Mos's
|
||||
+ reading of F42 is that C2-02 and C2-03b now gate 10-27, because design 9.2
|
||||
+ puts them in 'the smallest slice that lets her start'. C2-11a and C2-11b are
|
||||
+ slice rows that still don't gate 10-27, because the editor is the Q195 add-on.
|
||||
+ The DOCX change in 1.17 leaves this slice as it is, and C2-11b's Markdown
|
||||
+ editor never edits a converted story file.
|
||||
+ - Q236 narrows Q176's editor choice to DOCX for story files (REQ-LIB-9). The
|
||||
+ 1.12 note that the Case 2 design keeps Obsidian now holds only for Markdown
|
||||
+ files, including story files not yet imported. A DOCX story file is edited
|
||||
+ only in the Console's editor under REQ-LIB-9.
|
||||
+ - This replaces two parts of the O2 design at 25c09f19f. The superseded-notice
|
||||
+ proposal from Fenton's F1 in D12 is withdrawn, and the
|
||||
+ keep-Markdown-at-its-path model of D11 is replaced. Gyro's rewrite of the O2
|
||||
+ design for Vikunja 571, landed on `refactor` at b99ca86b9, carries the
|
||||
+ details, and where it differs from this text, this text holds:
|
||||
- the import and archive steps, the mark, and the new bus step;
|
||||
- links from supporting files to a moved chapter;
|
||||
- the DOCX reader;
|
||||
- the user's unpushed or later changes to an archived file or at its old path,
|
||||
and pushing and closing the file in Obsidian before each import;
|
||||
- - the writing store's remote, with W4 7.4's no-remote and no-backup rule taken
|
||||
- out;
|
||||
- - import events counted by a stack restore, and recovery when a restore
|
||||
- predates an import;
|
||||
+ - the writing store's remote in W4 section 7.3, which replaces the no-remote
|
||||
+ and no-backup rule that W4 section 7.4 held before the rewrite, at
|
||||
+ 062646487;
|
||||
+ - import events counted by a bus restore, and recovery when a bus restore or a
|
||||
+ restore of the whole host predates an import;
|
||||
- manifest order for the manuscript lookup and its next chapter;
|
||||
- - the import verb kept out of `ACTIONS` (packages/business/src/vocabulary.mjs,
|
||||
- the hard-wait note and the pinned `GATED_ONLY` list).
|
||||
+ - `library.convert` kept out of `ACTIONS`, out of the hard-wait note and out
|
||||
+ of the pinned `GATED_ONLY` list in packages/business/src/vocabulary.mjs.
|
||||
- Agents read a converted story file through the Case 2 lookups under the same
|
||||
project and universe access as Markdown canon, in any thread or room. W4's
|
||||
- O2-only conversations, per-document grants and per-send sharing (W4 7.1, 7.2)
|
||||
- don't gate these lookups, and the 571 rewrite brings W4 into line. The
|
||||
- creative tool list in REQ-LIB-6 doesn't change.
|
||||
+ earlier O2-only conversations, per-document grants and per-send sharing don't
|
||||
+ gate these lookups. The 571 rewrite replaced them in W4 sections 7.1 and 7.2.
|
||||
+ The creative tool list in REQ-LIB-6 doesn't change.
|
||||
- The six creative role contracts row 213 landed say 'Every item cites the
|
||||
lines of the user's material it is about'. A build row under 571 changes that
|
||||
line for DOCX story files (REQ-LIB-6).
|
||||
- - A new Markdown file in a book folder is still canon in 1.17.
|
||||
+ - A new Markdown file in a book folder is still canon in 1.17. The 1.17
|
||||
+ exception is a file at a converted file's old path, which REQ-LIB-2 makes
|
||||
+ unmapped.
|
||||
- Story files convert whether canon or playground. Type-folder and supporting
|
||||
files stay Markdown.
|
||||
- Measured 2026-10-23 at about 01:21Z: the Case 2 user's library repository
|
||||
@@ -336,52 +407,130 @@
|
||||
canon unless the caller asks for playground or supporting." "so an agent
|
||||
can't cite a playground or supporting file as canon" "The Console shows
|
||||
each cite's scope."
|
||||
- - REQ-LIB-4, the 1.16 sentence: "The user commits and pushes with their own
|
||||
- tools, today Obsidian with obsidian-git." and the clause "Agents read only
|
||||
- the mirror's served commit and never hold a copy of their own".
|
||||
+ - REQ-LIB-4, the 1.16 sentences: "The user commits and pushes with their own
|
||||
+ tools, today Obsidian with obsidian-git." "Agents read only the mirror's
|
||||
+ served commit and never hold a copy of their own, so they see the user's
|
||||
+ push within about a minute."
|
||||
- REQ-LIB-5, the 1.16 sentence: "The user sees them in Obsidian's graph and
|
||||
backlinks." A converted chapter's connections show in Obsidian only as they
|
||||
- stood at conversion, until a WebUI view exists (Q226).
|
||||
+ stood at conversion, until a Console view of their links exists. Q226
|
||||
+ records that view as a later option.
|
||||
- REQ-LIB-6, the 1.16 sentence: "A reply may cite lines of the repository at
|
||||
a commit or pages the agent fetched, and the broker checks every citation
|
||||
before it stores the message."
|
||||
- REQ-LIB-1 only gains sentences.
|
||||
- REQ-LIB-3's text and REQ-LIB-7 are unchanged. REQ-LIB-8 adds one form of
|
||||
- exclusion REQ-LIB-3 doesn't have: naming a DOCX document by its id. An archived file and a DOCX document
|
||||
- keep a universe, and a book where their source has one, so every lookup still
|
||||
- names one universe. REQ-PROJ-3, the project docs editor, is not Case 2 and is
|
||||
- unchanged.
|
||||
+ exclusion REQ-LIB-3 doesn't have: naming a DOCX document by its id. A path
|
||||
+ exclusion also covers DOCX documents, through a converted file's old path or a
|
||||
+ whole book folder. An archived file and a DOCX document keep a universe, and a
|
||||
+ book where their source has one, so every lookup still names one universe.
|
||||
+ REQ-PROJ-3, the Console editor for a project's spec and docs, is unchanged.
|
||||
+ C2-11b opens the library's Markdown files in that same editor.
|
||||
- In `packages/tasks/requirements.json` the titles of REQ-LIB-1, REQ-LIB-2 and
|
||||
REQ-LIB-4 change, and those of REQ-LIB-5 and REQ-LIB-6 stay. REQ-LIB-1 becomes
|
||||
'A human-set library maps the user's repository onto universes, books, types,
|
||||
playgrounds, supporting and archive folders'. REQ-LIB-2 becomes 'Scope comes
|
||||
from the path or a DOCX's source, lookups default to canon, and only canon
|
||||
- files are ever cited as canon'. REQ-LIB-4 becomes 'Git holds every change;
|
||||
- the bus fast-forwards a read-only mirror every 60 seconds and agents read
|
||||
- Markdown only there'. REQ-LIB-8 and REQ-LIB-9 add two ids, so the count goes
|
||||
- from 85 to 87. REQ-LIB-8 is titled 'Case 2 story files become DOCX by a human-only one-way import or in the editor; Markdown stays for notes and docs', and REQ-LIB-9 'The Console's DOCX editor: only a human saves, each save is one commit, and the editor code is vendored and pinned'.
|
||||
+ files are ever cited as canon'. REQ-LIB-4 becomes 'Git holds every change. The
|
||||
+ bus fast-forwards a read-only mirror every 60 seconds, the one place agents
|
||||
+ read Markdown'. REQ-LIB-8 and REQ-LIB-9 add two ids, so the count goes from 85
|
||||
+ to 87. REQ-LIB-8 is titled 'Case 2 story files become DOCX by a human-only
|
||||
+ one-way import or in the editor; Markdown stays for notes and docs', and
|
||||
+ REQ-LIB-9 'The Console's DOCX editor: only a human saves, each save is one
|
||||
+ commit, and the editor code is vendored and pinned'.
|
||||
- Open points O1 to O4 of draft 1 were ruled by Mos in mos-1367 B1 to B4.
|
||||
- Sage files the build rows under Vikunja 570 and 571 after the rewrite is
|
||||
approved. This amendment adds the requirements only."
|
||||
|
||||
### Risks
|
||||
|
||||
-New lines:
|
||||
+The new lines go at the end of "## Risks and open questions", after the bullet
|
||||
+that begins "Trusted mode lets an agent" and before the "## Milestones" heading.
|
||||
- "A DOCX file is a zip archive, so git can't show a line diff of a chapter.
|
||||
Review of a story change goes through the editor and the committed reader,
|
||||
not `git diff`. (Version 1.17.)"
|
||||
-- "Converted chapters leave Obsidian's graph. Their links show only in the
|
||||
- editor until a graph view exists. (Version 1.17.)"
|
||||
+- "A converted chapter's DOCX is not in Obsidian's graph. Obsidian shows the
|
||||
+ chapter only through its archived Markdown, and no DOCX edit reaches that file's
|
||||
+ links. The DOCX's current links show only in the Console's editor until a
|
||||
+ Console view of them exists. (Version 1.17.)"
|
||||
- "Conversion can't be undone in place. Front matter, wiki link forms and
|
||||
unsupported blocks may not survive it, and the mirror can't refuse the user's
|
||||
push to an archived file. The controls are the fidelity report, the human's
|
||||
confirmation, an untouched original on refusal, and the kept archive.
|
||||
(Version 1.17.)"
|
||||
-- "A stack restore from a backup taken before an import drops the import's
|
||||
- logged event, while the archive commit and the DOCX stay. Restore counts
|
||||
- import events, and the import's recovery covers this case (Vikunja 571).
|
||||
+- "A restore of the stack's bus alone from a backup taken before an import drops
|
||||
+ the import's logged events, while the archive commit and the DOCX stay. A
|
||||
+ restore of the stack's whole host from such a backup also takes the writing
|
||||
+ store and the host's import records back to before the import. The archive
|
||||
+ commit stays in the user's Gitea repository and the DOCX stays on the writing
|
||||
+ store's remote, but the host keeps no record of the import. A bus restore counts
|
||||
+ import events, and the import's recovery covers both cases (Vikunja 571).
|
||||
(Version 1.17.)"
|
||||
|
||||
+## d8 changes (Mos's d8 fix list, check wf_63bba879-180)
|
||||
+
|
||||
+- R1: REQ-LIB-4's tail covers DOCX saves, which agents see at their next lookup after the editor reports them as committed. The notes quote the whole 1.16 sentence. Source: nit/jason/F10.
|
||||
+- R2: REQ-LIB-4's new title says the mirror is "the one place agents read Markdown". Source: decisions.n14.
|
||||
+- R3: J-b asks whether 1.17 requires the Console Connections view, with Mos's recommendation of yes. Sources: mos1372/F9, jason/F2, anchors/F5.
|
||||
+- R4: C2-02 and C2-03b gate 10-27, C2-11a and C2-11b are slice rows that don't, and "F42 wins" is gone. New J-k. Sources: anchors/F6, jason/F5.
|
||||
+- R5: where the landed 571 design differs, this text holds. Sources: anchors/F8, adversarial/F8 item 1, jason/F8, critic/C6, G16's design follow-on.
|
||||
+- R6: `library.convert` stays out of `ACTIONS`, and REQ-WAIT-1's hard-wait list doesn't change. Sources: gyro571/F1, adversarial/F8 item 3, critic/C6.
|
||||
+- R7: a repository on the stack's host never counts as the writing store's remote, and Item 2 says so. Sources: mos1372/F2, adversarial/F1, gyro571/F2.
|
||||
+- R8: "no agent credential reaches it" becomes "no agent can reach it with any credential". Source: Fenton's B1 under mos-1379.
|
||||
+- R9: no playground DOCX becomes canon in 1.17, and a promotion of one is refused. New J-i. Sources: mos1372/F8, adversarial/F2.
|
||||
+- R10: REQ-LIB-9 restates Q195's pin and right-click thesaurus, and its cite gains D4 and D22. Source: critic/C4.
|
||||
+- R11: REQ-LIB-9's license bar is the licenses its independent security review accepted. New J-l. Source: critic/C3.
|
||||
+- R12: no text for D16's narrow-window tabs. Mos records that reading in STATE. Sources: jason/F1, second verifier vote.
|
||||
+- R13: no lookup returns a file's archived copy before publication. Source: adversarial/F5 part 3.
|
||||
+- R14: a restore of the whole host from a backup taken before an import is a fourth recovery case. Source: adversarial/F6.
|
||||
+- M1: REQ-LIB-4's writing-store sentences follow the later bus rows sentence and add the off-host remote rules and DOCX read timing. The note quotes both 1.16 sentences. Sources: mos1372/F2, adversarial/F1, gyro571/F2, anchors/F4, nit/jason/F10, adversarial/F5 part 1, Fenton B1.
|
||||
+- M2: REQ-LIB-8's order bullet adds the remote's confirmation, the old-path read rule and "archive push". Sources: mos1372/F2 and the other remote findings, mos1372/F7, adversarial/F5 parts 2 to 4.
|
||||
+- M3: REQ-LIB-8's gate bullet has four conditions, adding the remote. Sources: the remote findings, critic/C1 and C2 edit 2.
|
||||
+- M4: the 1.17 note on when conversion opens restates the four conditions and drops W4b. Sources: jason/F5, the remote findings.
|
||||
+- M5: Item 2 rewritten with the remote rules. Sources: the remote findings.
|
||||
+- M6: the 1.12 gating note rewritten. Sources: anchors/F6, jason/F5.
|
||||
+- M7: REQ-LIB-9 gains the split pane, the pin, the thesaurus, the license bar and the runtime load rule, and cites more of the design. Sources: jason/F1, critic/C4, critic/C3, nit/anchors/F12, nit/gyro571/F9.
|
||||
+- M8: REQ-LIB-2, the one-way bullet and the C1 note keep a playground DOCX out of canon in 1.17. Sources: mos1372/F8, adversarial/F2.
|
||||
+- M9: REQ-LIB-5 says what the reader can't read, and the import turns web links into plain text. New J-j. Sources: critic/C1, critic/C2.
|
||||
+- M10: an exclusion of a whole book folder covers that book's DOCX documents. Source: adversarial/F3, with B5.
|
||||
+- M11: the human-verbs sentence and the 571 list item name `library.convert` and REQ-WAIT-1. Sources: gyro571/F1, adversarial/F8 item 3, critic/C6.
|
||||
+- M12: J-b rewritten. Sources: mos1372/F9, jason/F2, anchors/F5, gyro571/F3, critic/C6.
|
||||
+- M13: J-d puts the agent read model to Jason as his call. Source: mos1372/F1.
|
||||
+- M14: Status moves to version 1.17 and names REQ-LIB-9. Sources: anchors/F2, mos1372/F4, critic/C7.
|
||||
+- M15: the 1.17 source line quotes Q235 in full (mos-1446) and the REQ-LIB-9 sources, at b99ca86b9. Sources: critic/C5, anchors/F9, jason/F8 pin part, nit/gyro571/F8, critic/C6 pin part.
|
||||
+- M16: the 571 list lead names the two replaced design parts and the landed design. Sources: anchors/F9, anchors/F8, adversarial/F8 item 1, jason/F8, critic/C6.
|
||||
+- Landing swap: Gyro's docs round for R5, R6 and R14 landed as b99ca86b9 (Fenton fenton-0015), so M15 and M16 cite b99ca86b9 in place of 767bb62c7, as the d8 fix list's header says. J-b keeps 767bb62c7 for its line numbers.
|
||||
+- M17: W4 section numbers in the remote item and the lookups note. Sources: gyro571/F5, nit/adversarial/F11.
|
||||
+- M18: the D7 landing line. Sources: gyro571/F5, the remote findings.
|
||||
+- M19: a logged event for each import stage, in REQ-LIB-8 and A2. Source: gyro571/F7.
|
||||
+- M20: the Risks line on restores adds the whole-host case. Sources: adversarial/F6, gyro571/F7.
|
||||
+- M21: the 571 restore item adds the whole-host case. Source: adversarial/F6.
|
||||
+- M22: the graph Risks line and the REQ-LIB-5 note name a Console view. Sources: anchors/F5, jason/F2.
|
||||
+- M23: the d6 B3 line drops "F42 wins". Source: anchors/F6.
|
||||
+- M24: new Markdown in a converted book, with the old-path and playground exceptions. Source: mos1372/F6.
|
||||
+- M25: J-c's last sentence is Mos's reading. Source: mos1372/F10.
|
||||
+- M26: J-h rewritten with the D13 defaults. Source: jason/F3.
|
||||
+- M27: Item 4 rewritten. Sources: jason/F4, gyro571/F4, decisions.unmarked_folders.
|
||||
+- M28: the "Not taken" note on unmarked folders. Sources: jason/F4, gyro571/F4, decisions.unmarked_folders.
|
||||
+- M29: the import refuses an unmapped file. Sources: gyro571/F4, decisions.unmarked_folders.
|
||||
+- M30: placement notes for REQ-LIB-8, REQ-LIB-9 and the Risks lines. Sources: anchors/F3, nit/anchors/F14.
|
||||
+- M31: REQ-LIB-4's title and the D11 landing line. Source: decisions.n14.
|
||||
+- M32: the Q236 note limits the 1.12 Obsidian note to Markdown files. Source: critic/C8.
|
||||
+- M33: the exclusion note adds path exclusions of DOCX documents. Source: anchors/F7.
|
||||
+- M34: A9 moves from "Mine" to the impact-map list. Source: decisions.exclusion_by_id.
|
||||
+- M35: the D5 landing line. Sources: anchors/F10, mos1372/F5, nit/adversarial/F12.
|
||||
+- M36: the D9 and D14 landing lines. Source: mos1372/F1.
|
||||
+- M37: the O1 and C3 notes add the off-host remote and its confirmation. Sources: the remote findings.
|
||||
+- M38: the REQ-PROJ-3 note. Source: nit/anchors/F11.
|
||||
+- M39: REQ-LIB-5's freshness sentence keys on the editor reporting a save as committed. Source: nit/adversarial/F9.
|
||||
+- M40: REQ-LIB-6 bars agent requests for a conversion and allows a suggestion in chat. Source: nit/jason/F9.
|
||||
+- M41: REQ-LIB-2's opening and old-path rule, and the "Mine" note. Source: nit/adversarial/F10.
|
||||
+- M42: REQ-LIB-8's lead sentence on Markdown story files. Source: nit/mos1372/F12.
|
||||
+- M43: REQ-LIB-6's citation sentence. Source: nit/anchors/F13.
|
||||
+- M44: REQ-LIB-5's version tag uses plain quotes. Source: nit/anchors/F15.
|
||||
+- M45: reference codes B5, D12, D10 and B4 name their source. Source: nit/mos1372/F11.
|
||||
+- Files the row would own: four files, with the id count going to 87. Sources: anchors/F1, adversarial/F4, decisions.n14 F4.
|
||||
+
|
||||
## d7 changes (mos-1379, Fenton's 571 B2)
|
||||
|
||||
- REQ-LIB-5 gains Mos's three sentences after the extracted-text sentence. The text agents read has tracked changes accepted. Comments, and text with tracked deletions shown, each wait for a setting only a human turns on, off by default. Its version tag cites Q222 for the two settings, which is the only text here beyond Mos's.
|
||||
@@ -392,7 +541,7 @@
|
||||
|
||||
- B1: titles for REQ-LIB-8 and REQ-LIB-9 in the requirements.json note and the file list. REQ-LIB-9 takes Webby's title. REQ-LIB-8 keeps mine, because Webby's ("...one-way import that archives the Markdown under its old path") leaves out D2's story files started in the editor.
|
||||
- B2: REQ-LIB-2 makes a Markdown file at a converted file's old path unmapped, ahead of the playground and canon rules, so a playground conversion is covered too. REQ-LIB-8's old-path bullet says "neither canon nor playground".
|
||||
-- B3: the slice note names Q226 F42's three rows (C2-02, C2-03b, C2-11b). C2-11a doesn't gate 10-27. F42 wins where case2-rows.md:1284-1285 or the impact map's A57 says otherwise.
|
||||
+- B3: the slice note names Q226 F42's three rows (C2-02, C2-03b, C2-11b). C2-11a joined the slice with C2-11b, because C2-11b needs it. Both are slice rows that don't gate 10-27, as design 9.2, case2-rows.md:1655 and the impact map's A57 say. The 'F42 wins' sentence is gone from the note in d8, so no queue change follows from it.
|
||||
- N10: the cite-scope replacement is scoped to REQ-LIB-2. The 1.14 note's copy stays.
|
||||
- N11: the notes say REQ-LIB-8 adds the by-id exclusion form REQ-LIB-3 doesn't have.
|
||||
- N12: J-h marks the autosave intervals for Jason.
|
||||
@@ -405,57 +554,61 @@
|
||||
- D2: REQ-LIB-2's "for one the human starts in the editor" and the REQ-LIB-8 new-story-file bullet. The universe-and-book note is now true.
|
||||
- D3: the REQ-LIB-8 order bullet. This also settles N8.
|
||||
- D4: REQ-LIB-8's one-way bullet, which carries the archive refusal and consequence F2's text, and the 571 list item.
|
||||
-- D5: REQ-LIB-2's "unless its path is a converted file's old path" and the REQ-LIB-8 old-path bullet.
|
||||
+- D5: it landed in REQ-LIB-2's "a Markdown file at a converted file's old path is unmapped" in Webby's B2 form, and in the REQ-LIB-8 old-path bullet.
|
||||
- D6: REQ-LIB-5's freshness sentences.
|
||||
-- D7: REQ-LIB-4's remote sentences, plus the 571 list item that takes out W4 7.4's rule. The impact map's item 2 adds "only the stack's host pushes, and no agent credential reaches it".
|
||||
+- D7 and mos-1375: REQ-LIB-4's remote sentences, the remote step in REQ-LIB-8's order bullet, the fourth opening condition and the 1.17 note on when conversion opens, plus the 571 list item on W4 section 7.3, which replaces the no-remote rule of the old W4 section 7.4. The impact map's item 2 adds "only the stack's host pushes, and no agent credential reaches it".
|
||||
- D8: the REQ-LIB-5 replacement, the import bullet's wiki-link sentence, the Risks line, the note quoting the old sentence, and "REQ-LIB-1 only gains sentences".
|
||||
-- D9: B2's note.
|
||||
-- D10: B5's sentence, in REQ-LIB-8.
|
||||
-- D11: internal F3's clause and title, in the REQ-LIB-4 section and the notes.
|
||||
+- D9: the 1.17 note that agents read a converted story file through the Case 2 lookups, from the d4 check's consistency B2, and J-d, which puts the read model to Jason as his call.
|
||||
+- D10: the d4 check's B5 sentence, in REQ-LIB-8.
|
||||
+- D11: internal F3's clause in the REQ-LIB-4 section, and in the notes the title as Mos amended it for N14.
|
||||
- D12: the whole 1.16 sentence replaced, and quoted in full in the notes.
|
||||
- D13: consequence F1's text, in REQ-LIB-4 and REQ-LIB-8's first bullet.
|
||||
-- D14: B1's row text, in the mark-and-move bullet and C3 above.
|
||||
+- D14: the row text from the d4 check's consistency B1, in the mark-and-move bullet and C3 above.
|
||||
|
||||
## What d5 adds beyond mos-1372 (for Webby and Mos to check)
|
||||
|
||||
From the impact map, folded as mos-1368 item 1 asked:
|
||||
- A1: the Console shows a cite's format and converted state (REQ-LIB-2).
|
||||
-- A2: the logged event and the several-humans setting, default owner only (Q222).
|
||||
+- A2: the logged events and the several-humans setting, default owner only, under Q222.
|
||||
- A3: the import is outside the vocabulary, the hard-wait list is unchanged, and the archive move isn't `data.delete`. The C6 code site is in the 571 list.
|
||||
- A4: the section lead and REQ-LIB-1's writing-store sentence.
|
||||
- A6: format and location in every answer, extracted text with DOCX locators, links across formats.
|
||||
- A7: read-only extends to the store and the archive, no agent action on a story file in any format, no agent DOCX write, and role contracts state the formats. C1's role contract line is a 571 build item.
|
||||
- A8: the DOCX cite shape, and a cite naming an archived file as current is refused.
|
||||
+- A9: a hybrid sees a source's DOCX canon through REQ-LIB-2's source scope, and REQ-LIB-8 lets an exclusion name a DOCX document by its id. The id form lets the human exclude a single DOCX started in the editor, which has no old path. An archived file isn't canon, so no hybrid sees it.
|
||||
- A10: REQ-LIB-9, so the count is 87, not 86.
|
||||
- A11: the Hermes gate, from item 3.
|
||||
- A12: the C2-19 promotion sentence.
|
||||
- A13: the broker's path check treats the archive folder as story.
|
||||
- A14 and C5: two Risks lines.
|
||||
-- A15: the flagged-new-file bullet. It sits beside B4's "a new Markdown file in a book folder is still canon" note: the file stays canon and is offered for import.
|
||||
+- A15: the flagged-new-file bullet. It sits beside the note from the d4 check's B4, "a new Markdown file in a book folder is still canon". The file stays canon and is offered for import.
|
||||
- A16: three titles change and two stay.
|
||||
- C2: manifest order for the manuscript lookup.
|
||||
- F3: the C2-02 gating note.
|
||||
- F4: Mos's measurement.
|
||||
|
||||
Mine, beyond either source:
|
||||
-- REQ-LIB-2 opens "A Markdown file's scope comes from its path alone". DOCX scope comes from the source, so "a file's" would be false.
|
||||
-- REQ-LIB-8's exclusion-by-id sentence. A DOCX started in the editor has no old path, so without it a hybrid couldn't exclude one.
|
||||
+- REQ-LIB-2 opens "A Markdown file's scope comes from its path and from past imports". DOCX scope comes from the source, so "a file's" would be false.
|
||||
- REQ-LIB-9's autosave sentence. It is Mos's reading of F41's "instantly committed", with human-set intervals. The exact intervals stay in the design.
|
||||
|
||||
Not taken:
|
||||
-- Impact map item 4's "files in unmarked folders are eligible one at a time". D1 names canon and playground story files only, and an unmapped file has no scope for a DOCX to keep. If Mos wants unmarked folders in, the human would map them first.
|
||||
+- Impact map item 4's "files in unmarked folders are eligible one at a time", for folders outside every book folder and playground only. Their files are unmapped under REQ-LIB-2, so a DOCX made from one would have no universe or book to keep. The human maps such a folder into a book folder or a playground first, under REQ-LIB-1. A file in an unmarked folder inside a book folder or a playground is canon or playground, and the import takes it one file at a time.
|
||||
- A6's named chapter-links view. D8 takes B8's "no graph shows them yet", and J-b puts the view to Jason.
|
||||
|
||||
## Marked for Jason (additions in the text he sees)
|
||||
|
||||
- J-a. Whether "We will not run the systems in parallel" applies per chapter or as one switch per book. His call. As written, it applies per chapter.
|
||||
-- J-b. Converted chapters leave Obsidian's graph, and 1.17 has no other graph. REQ-LIB-5 still carries its "Connections are always visible" tag, and Q226 leaves room for "another way to handle the visual brain map". As written, that tag holds for Markdown files and for links inside the editor, and a graph of DOCX links waits for that other way.
|
||||
-- J-c (mos-1374): "The store pushes to a remote (D7), and the Case 2 VM is in the nightly PBS backup. For a fixed restore point before her first real import, a manual backup of VM 1012 with PBS protect runs first. That step is reversible and needs no reboot." This belongs to the P5 go step, so no new question.
|
||||
-- J-d. The agent read model in D9. A converted chapter is read through the ordinary Case 2 lookups in any thread or room, not through W4's per-document grants. Mos's reading of F41 and REQ-LIB-7. Comments and tracked deletions stay hidden from agents until a human turns on a setting for each. Markdown has neither, so the default keeps agents at the access Markdown gives them (mos-1379).
|
||||
+- J-b. A converted chapter's DOCX is not in Obsidian's graph. Obsidian shows the chapter only through its archived Markdown, and no DOCX edit reaches that file's links. REQ-LIB-5 still cites two TARGET lines, "Visualization of data via Obsidian or equivalent is required" and "Connections are always visible". Mos's reading is that 1.17 as written meets neither line for converted chapters. Their current links show to the user only as clickable text inside the editor, and no graph or list shows them. Q226 leaves room for "another way to handle the visual brain map". The O2 design that landed for Vikunja 571 at 767bb62c7 holds a Console Connections view and its tests as later work that waits for this answer. His call whether 1.17 requires that view. As written, it does not. Mos recommends that it does, because impact map A6 says "Recommended: name the view" and TARGET says "Connections are always visible".
|
||||
+- J-c (mos-1374): "The store pushes to a remote (D7), and the Case 2 VM is in the nightly PBS backup. For a fixed restore point before her first real import, a manual backup of VM 1012 with PBS protect runs first. That step is reversible and needs no reboot." Mos's reading is that this sits inside the P5 go step, so it needs no new question.
|
||||
+- J-d. How agents read a converted chapter, D9. His call. As written, an agent reads it through the ordinary Case 2 lookups in any thread or room, under the same project and universe access as Markdown canon. This is Mos's reading of F41 and REQ-LIB-7. The other choice is the model in the earlier O2 design, W4 sections 7.1 and 7.2. Under it, an agent reads a converted chapter only in a new writing conversation that holds one human and one agent, only after the business owner grants that agent access to that document, and by default only what the human attaches to each message. Comments and tracked deletions stay hidden from agents until a human turns on a setting for each. Markdown has neither, so the default keeps agents at the access Markdown gives them. Those two sentences are Mos's ruling mos-1379. A yes to the text as written settles it.
|
||||
- J-e. Versioning means the editor's tracked changes plus one git commit per save.
|
||||
- J-f. A converted chapter can be edited only in the Console while the stack is reachable. Obsidian no longer edits it offline.
|
||||
- J-g. The import takes Markdown only. Importing .doc files stays a separate task.
|
||||
-- J-h. Autosave (REQ-LIB-9) runs at intervals only a human changes. F41 says saves are "instantly committed". The intervals are text beyond that, so they are marked for him. The exact values stay in the design.
|
||||
+- J-h. Autosave under REQ-LIB-9. Jason's Q226 F41 says "All changes are instantly committed and available to the agents." Mos's reading, recorded with that ruling, is "Each save is a commit at once, and agents read it at their next lookup." At the O2 design's D13 defaults, a save commits at most 2 seconds after a pause in typing or 15 seconds into steady typing, with no human action needed. Mos's reading in mos-1359 counts that delay as "instantly committed". Only a human changes the intervals. The PRD names no values, and the defaults stay in the design. Whether a delay of seconds fits his word "instantly" is his call, so this is marked for him.
|
||||
+- J-i. In 1.17 a playground story that is DOCX can't become canon. That covers a playground Markdown file the human imports, a story the human starts in a playground in the editor, and the DOCX of a draft universe after it is made real. Today Melanie promotes a playground file by moving it into a book folder in Obsidian, and a DOCX in the writing store can't be moved that way. She can start a new story in the book and paste the text in, but it gets a new document id and the playground copy keeps the history. A later version adds DOCX promotion with C2-19, which comes after the slice.
|
||||
+- J-j. Web links, text boxes and fields in a converted chapter. Jason's Q226 F41 says "All changes are instantly committed and available to the agents." The reader in this version can't read a web link, a text box, a field or hidden text. As written, the import turns each web link into plain text that keeps its label and address, and the human confirms that in the fidelity report. A web link that can't be kept safely as plain text refuses the import. If a later edit adds one of these, the save keeps it and the editor warns the human. Agents then get none of that part's text until a save takes it out.
|
||||
+- J-k. The 1.12 note Jason approved says bus writes, C2-02 and C2-03b, don't gate 10-27. His Q226 "F42: ok" moved them into the 10-27 slice, and design 9.2 counts them in the smallest slice that lets Melanie start. Mos reads that as making them gate 10-27. The editor rows C2-11a and C2-11b still don't gate it, per his Q195 words "we need to get it moving as an add-on".
|
||||
+- J-l. REQ-LIB-9 does not use REQ-PROJ-3's "permissive license" bar. It takes the licenses that the editor's independent security review accepted, because that review cleared fonts under the SIL Open Font License and the Ubuntu Font License, which not every reader counts as permissive. Mos's reading.
|
||||
|
||||
Marked as changes beyond P1 to P6, from the impact map (Q17, item 5):
|
||||
- A1 (archived scope and canon cites)
|
||||
@@ -464,21 +617,22 @@
|
||||
- A6 (lookups across formats)
|
||||
- A7 (agent bounds)
|
||||
- A8 (DOCX cites)
|
||||
-- Item 2 (the remote only the stack's host pushes)
|
||||
+- Item 2 and mos-1375: each writing-store commit is pushed to a remote off the stack's host. Only a human sets it, it starts unset, and a repository on the stack's host doesn't count. Only the stack's host pushes to it, and no agent can reach it with any credential. Import and new story files stay closed until the remote is set and checked, and each import's archive push waits until the remote holds the DOCX commit. This keeps "Git is used for all changes -- local and remote" true for DOCX chapters.
|
||||
- Item 3 (the Hermes gate)
|
||||
-- Item 4 (canon and playground convert, type folders stay Markdown)
|
||||
+- Item 4. Canon and playground story files convert one file at a time, including files in unmarked folders inside a book folder or a playground. Type-folder and supporting files stay Markdown. A story file outside every book folder and playground has no universe or book, so it converts only after a human maps its folder into a book folder or a playground. The mapping step is Mos's reading of P1 and Q30.
|
||||
|
||||
The F4 measurement goes with them.
|
||||
|
||||
## Files the row would own
|
||||
|
||||
-As with 1.16, the row owns three files:
|
||||
+The id count goes from 85 to 87. 1.16 owned three files because its count stayed at 85. Like 1.13, the last version that added ids, the row owns four files:
|
||||
- `docs/prd/mosaic-stack.md`
|
||||
-- `packages/tasks/requirements.json`: the version, the two new ids with their titles (REQ-LIB-8 and REQ-LIB-9), and the changed titles of REQ-LIB-1, REQ-LIB-2 and REQ-LIB-4.
|
||||
-- `packages/tasks/tests/requirements.test.mjs`: the version pin and the id count of 87.
|
||||
+- `packages/tasks/requirements.json`: the version 1.17, the two new ids REQ-LIB-8 and REQ-LIB-9 with their titles, and the changed titles of REQ-LIB-1, REQ-LIB-2 and REQ-LIB-4. The new ids go after REQ-LIB-7 and before REQ-INST-1, in the same order as the PRD's bullets.
|
||||
+- `packages/tasks/tests/requirements.test.mjs`: the version pin 1.17, the id count of 87, and the duplicate-id message, which goes from `requirements[85].id: REQ-ROLE-1 twice` to `requirements[87].id: REQ-ROLE-1 twice`.
|
||||
+- `packages/bus/tests/requirements.test.mjs`: the list length, which goes from 85 to 87.
|
||||
|
||||
The gate would match 1.16's:
|
||||
1. A reviewer approves the text.
|
||||
2. Jason says yes to the exact text through Mos.
|
||||
-3. `requirements.test.mjs` and every `scripts/test-*.sh` that reads the PRD or `requirements.json` are green on Sage's gate.
|
||||
+3. Both `requirements.test.mjs` files, in `packages/tasks/tests` and `packages/bus/tests`, and every `scripts/test-*.sh` that reads the PRD or `requirements.json` are green on Sage's gate.
|
||||
4. Mos gets the landing commit.
|
||||
@@ -1575,4 +1575,3 @@ are never rewritten or removed; corrections are new entries.
|
||||
- 2026-10-23T07:59:57Z | filbert (Claude Opus 5.5, T3 048f3c63) | row 299 manifest round 1 (#1806, Vikunja 573, Gander, manifest 277ace0b on ffa93b054) | approve in 31084, rev 3485; static on git objects (blobs = reviewed 1ec2b9765, product = base 80793d824); gate receipts 63db96d8b read, not rerun: case1 53/0 x3, cli 917/0 (59 files), M1-M6 killed; N1 M1 margin 0.02 s
|
||||
- 2026-10-23T08:10:29Z | sage (Opus 5.5, 1ef1e4f8) | 299 gate and landing, 303 review, 219/295 rebases | 299 LANDED ffb2fedfb 08:03Z (done 3487, #1806 c31087); queue-commit 8a35ffadb (revs 3474-3487); 303 Duckworth approve rev 3480; requests posted as sage for 303 (c31082) and 299 (c31083); 219 full restart on bfa421b6c from 08:08Z (sage-3283)
|
||||
- 2026-10-23T10:48:40Z | sage (Opus 5.5, 1ef1e4f8) | 302/295/219 landings, Docker pool diag, 590/591 briefs, 272 rebase | 302 LANDED 3ed9fd754, 295 LANDED 2efd127ce, 219 LANDED 5fdfd7275 (#1720 c31110, P19 416 c913); test-release 11/3 from exhausted Docker pools, 18 networks removed (mos-1437/1438); queue-commit 90633c864 (revs 3495-3510, 3510 Huey's); 272 rebase and fallback ruled (sage-3357)
|
||||
2026-10-23T11:03:46Z | Gyro (Codex gpt-6.1-sol, mos-1444) | Vikunja571 PRD d8 docs alignment | R6 vocabulary boundary, mapped-folder eligibility and R14 whole-host recovery updated in parent/W4; static checks only, no tests or live changes. Fenton reviews; Sage lands.
|
||||
@@ -265,9 +265,7 @@ After each file's conversion publication, the authorized format map is a typed h
|
||||
sourceCommit,conversionCommit}`. kind is chapter or supporting-document; current chapter
|
||||
format is docx, supporting format markdown; state is current or converted-archive. scope distinguishes canon, playground, supporting
|
||||
and archived without format-based promotion. Type-folder entity notes remain Markdown;
|
||||
a story file in an unmarked folder inside a book or playground is eligible for human selection,
|
||||
one file at a time. A story file outside every book and playground is unmapped and converts
|
||||
only after the human maps its folder, per PRD 1.17 REQ-LIB-8 and mos-1368 Q18. location
|
||||
an unmarked-folder story is eligible for human selection, one file at a time (mos-1368 Q18). location
|
||||
is an opaque owned location, never a host path/capability. Publish only entries the caller's
|
||||
live scopes allow, no title/path leak from denied documents. Agents get this map through
|
||||
reviewed library/universe lookup results and normal authorized Case 2 context so they know formats
|
||||
@@ -323,9 +321,8 @@ amendment, W4b PASS and live committed-reader/citation readiness, W7 reviewed im
|
||||
release, Hermes retirement (#423 step 5, with its old write/store access removed), verified
|
||||
host-only off-host durability and an authenticated human start. `library.convert` is a
|
||||
human-only CLI/Console verb run through the host async processing adapter, outside agent
|
||||
vocabulary/role grants and off the read-verb list. It is not in ACTIONS or ROUTED and never
|
||||
reaches the broker. A role file naming an action outside the vocabulary is already refused.
|
||||
REQ-WAIT-1 and its hard-wait test remain unchanged (mos-1444 R6).
|
||||
vocabulary/role grants and off the read-verb list. Its action remains a hard wait under
|
||||
REQ-WAIT-2/3 until the approved PRD says otherwise; it never joins ROUTED silently.
|
||||
`editor.conversionHumans` is human-only, default business owner only. Folder setting/mapping
|
||||
have one authoritative archive-prefix value; the library mapping and editor cannot disagree.
|
||||
Archive prefixes cannot overlap playground/supporting prefixes. Conversion preserves bytes
|
||||
@@ -1158,7 +1155,7 @@ The source archive and private DOCX repository cannot publish atomically through
|
||||
`packages/bus/tests/{writing-save.test.mjs,chapter-format.test.mjs,schema.test.mjs,conversion-events.test.mjs}`,
|
||||
`packages/harness/src/tools.mjs`, `packages/harness/tests/chapter-format.test.mjs`,
|
||||
`packages/business/src/{vocabulary.mjs,business.mjs}`,
|
||||
`packages/business/tests/{vocabulary.test.mjs,business.test.mjs}`,
|
||||
`packages/business/tests/{vocabulary.test.mjs,business.test.mjs,hard-waits.test.mjs}`,
|
||||
`scripts/mosaic`, `packages/cli/src/library.mjs`, `packages/cli/tests/library-convert.test.mjs`,
|
||||
`roles/{companion,continuity,fact-checker,ideas,proofreader,research}.md`,
|
||||
`packages/webui/src/{writing-http.mjs,library-http.mjs,cli.mjs,serve.mjs,bus.mjs}`,
|
||||
@@ -1217,11 +1214,6 @@ bus restore. Test the third case explicitly: convert, then rollback --restore a
|
||||
backup, losing the bus conversion event while archive and DOCX commits remain. The normal
|
||||
counted-event approval/loss protocol applies; reconcile immutable commits/journal with new
|
||||
recovery events before lookups resume. Never revive Markdown or replay authorization grants.
|
||||
The fourth recovery case restores the whole host from a backup taken before an import,
|
||||
losing its writing store and host import records as well as bus events. Rebuild the host
|
||||
record from the import manifests on the writing store's off-host remote and the archive
|
||||
commit in Gitea. Chapter lookups refuse until recovery proves one current version.
|
||||
Restoring VM 1012 boots it, so Jason is present under Q185 (mos-1444 R14).
|
||||
Old release capability preflight must refuse converted projects it cannot interpret.
|
||||
|
||||
Update the six creative .md role contracts' obsolete 'Every item cites the lines' text:
|
||||
@@ -1230,9 +1222,8 @@ source format/scope from the map, archived never canon, and no story/conversion
|
||||
still use only their approved lookups/message/supporting-write tools. Schema/role expansion
|
||||
waits for the approved PRD, and existing role JSON never grants library.convert. Expose the
|
||||
human CLI/Console conversion verb through runtime/processing.work and async readback, not
|
||||
the agent tool list. library.convert is absent from ACTIONS and ROUTED; host processing
|
||||
never sends it to the broker. Role vocabulary validation already refuses an unknown action.
|
||||
REQ-WAIT-1 and packages/business/tests/hard-waits.test.mjs remain unchanged (mos-1444 R6).
|
||||
the agent tool list. Hard-wait tests are at business/tests/hard-waits.test.mjs:22; the new
|
||||
action remains GATED_ONLY unless the approved PRD explicitly changes it.
|
||||
|
||||
The importer lives at `packages/writing/src/import-markdown.mjs`, owns a reviewed AST mapping
|
||||
from vendored markdown-it to the WordCraft DOCX model, and validates source token/metadata,
|
||||
|
||||
@@ -15,9 +15,8 @@ from the reviewed baseline except their replaced per-document-scope wording.
|
||||
Q235–Q237 P1–P6 and mos-1372 D1/D2 settle the design basis: canon and playground story
|
||||
files become DOCX, retaining universe/book and source scope. Type-folder notes, agent files,
|
||||
instructions, PRDs, character sheets, summaries and supporting documentation stay Markdown.
|
||||
A story file in an unmarked folder inside a book or playground is eligible, and the human
|
||||
selects one story file at a time. An unmapped story file converts only after the human maps
|
||||
its folder. New stories start directly as DOCX in the human-selected universe/book or playground, without a
|
||||
An unmarked-folder story is eligible; the human selects one story file at a time. New
|
||||
stories start directly as DOCX in the human-selected universe/book or playground, without a
|
||||
Markdown precursor, under the same production-opening gate as import.
|
||||
|
||||
The October 27 release stays Markdown. Production import/new-story opening waits for W4b,
|
||||
@@ -25,9 +24,7 @@ W7, the post-10-27 release, the approved Case 2 PRD/brief amendment, Hermes reti
|
||||
(#423 step 5) and configured off-host durability. The first real use on Melanie's books
|
||||
also waits for Jason's scoped go and mos-1374's protected manual VM1012 backup before the
|
||||
first real import, handled by its authorized human operator, not this design seat. All starts are human-only; `library.convert` has no role
|
||||
grant or agent request path. It is not in ACTIONS or ROUTED; the human host processing
|
||||
adapter never sends it to the broker. A role file naming an action outside the vocabulary
|
||||
is already refused. REQ-WAIT-1 and its hard-wait test remain unchanged (mos-1444 R6).
|
||||
grant or agent request path and stays a hard wait unless an approved PRD changes it.
|
||||
Nothing in this document authorizes conversion, new private story creation or deployment.
|
||||
Q234's exact frame CSP, mos-1363 and S0 M1–M14 remain unchanged implementation gates.
|
||||
|
||||
@@ -595,10 +592,9 @@ join stack-release COUNTED and T46 exactly once, so post-backup conversion event
|
||||
to --events and the existing restore approval/counting behavior. No new private conversation,
|
||||
per-document grant or per-send share tables are created for D9.
|
||||
|
||||
Four recovery cases are required: (1) crash after durable DOCX staging but before archive
|
||||
Three recovery cases are required: (1) crash after durable DOCX staging but before archive
|
||||
push, (2) crash after archive push before publication, and (3) rollback --restore from a
|
||||
pre-conversion bus backup while archive commits and O2 documents remain, and (4) a whole-host
|
||||
restore from a backup taken before an import. The source is pinned
|
||||
pre-conversion bus backup while archive commits and O2 documents remain. The source is pinned
|
||||
until final publication in cases1/2; after archive push state is visibly pending, never
|
||||
'original untouched'. Case3 drops conversion rows only through the counted/approved restore
|
||||
path. The durable host conversion journal/format registry is not restored from that older bus
|
||||
@@ -610,12 +606,6 @@ pending operation to the human. Do not replay chapter text into an old index or
|
||||
Incompatible old binaries cannot activate converted projects through the supported controller;
|
||||
raw privileged rollback tampering is outside the guarantee. Never rewrite git/run history.
|
||||
|
||||
Case4 also loses the local writing store and host import records. Recovery rebuilds the
|
||||
host record from the import manifests on the writing store's off-host remote and the
|
||||
archive commit in Gitea. Chapter lookups refuse until it proves one current version;
|
||||
missing or inconsistent remote evidence cannot revive old Markdown as current. Restoring
|
||||
VM 1012 boots it, so Jason is present under Q185 (mos-1444 R14).
|
||||
|
||||
Hermes retirement (#423 step5) is a production-opening prerequisite, with old story-write and
|
||||
store-read access removed before any conversion/new-story operation. W7 checks its retirement
|
||||
receipt and host capability preflight; no design seat retires services or accesses Melanie's
|
||||
@@ -654,7 +644,7 @@ These are required future fixture gates, not implementation results.
|
||||
| A24 | Full page and oversized paragraph | end before overflow; first oversized row refuses without text; no unreachable subrange claim |
|
||||
| A25 | Every read/write/tool surface uses existing Case 2 isolation | same document ID across business/universe or replayed cursor refuses |
|
||||
| A26 | Host-only off-host remote and per-save push | unset/local-only/helper-readable/unexpected remote refuses opening; real helper denial tested; push outage visible, local next lookup still fresh |
|
||||
| A27 | Conversion restore accounting and durable journal reconciliation | pre-conversion bus --restore or whole-host restore reconciles remote manifests and archive commit; lookups refuse until one current version is proven; no lost-event concealment |
|
||||
| A27 | Conversion restore accounting and durable journal reconciliation | pre-conversion --restore loses counted row but cannot revive Markdown; no lost-event concealment |
|
||||
| A28 | Reopened M1 supports same-thread DOCX-read then supporting-note write | any room/project-authorized caller works; no per-document/share token; story/archive write refuses |
|
||||
| A29 | Readiness is reviewed runtime/extractor plus approved PRD, not caller fields | no request/go/setting can assert release or Hermes retirement |
|
||||
| A30 | Canonical schemas and complete selections | unknown keys, inconsistent ranges, xmlId null mismatch and noncanonical story IDs refuse |
|
||||
|
||||
+2
-5
@@ -33,7 +33,7 @@ Gaps found while working go to `docs/plans/DEFERRED.md`, not here.
|
||||
|
||||
<!-- mosaic-queue:begin -->
|
||||
|
||||
Generated from `docs/plans/queue.json` revision 3530 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
Generated from `docs/plans/queue.json` revision 3510 by `queue render`. Do not edit between the markers; change the queue with `scripts/mosaic queue`.
|
||||
|
||||
| # | Piece | Owner | Issues | State | After | Gate | Brief | Note |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
@@ -308,7 +308,7 @@ Generated from `docs/plans/queue.json` revision 3530 by `queue render`. Do not e
|
||||
| 269 | 264b T1 item 7: per-session native store, workspace and single-writer fence | gizmoduck; reviewers duckworth | #1774 | done | 264 done | Duckworth approves this slice's manifest. Its design tests run whole plus every touched suite on Sage's slot, and its mutants are killed (RULINGS Q1). Tests T1 run half, T2 workspace and path mutants; whichever of 191 and 264b lands second wires 191's admission checks (Q5). (sage) | `docs/plans/2026-10-21_t1-sessions.md` § T1 item 7: independent sessions, compaction counts and clear context | Landed efcc9ea8d fast-forward on 94c33a43c (13 commits, 12 paths, manifest 455c12ee). r3 is a carry of r2 aafcc857c, range-diff = (Duckworth 0194, c30756, rev 3307). Gate r3 18:37-18:50Z all green, 0 skips: bus 834, seat 172, cli 869, case2-unit 43, singles 38. M1-M12 kills carry. Re-pin needs the Console restart by Jason or Mos right after the host. A 264a rollback refuses a v2 sessions.json, see BUILD.md Rollback. |
|
||||
| 270 | 264c T1 item 7: compaction count, exact for Pi | gizmoduck; reviewers duckworth | #1775 | done | 269 done | Duckworth approves this slice's manifest. Its design tests run whole plus every touched suite on Sage's slot, and its mutants are killed (RULINGS Q1). Test T3 Pi half; Claude shows unknown with the Vikunja 466 reason (Q6). (sage) | `docs/plans/2026-10-21_t1-sessions.md` § T1 item 7: independent sessions, compaction counts and clear context | LANDED 7328da8ca (with 271, mos-1351) 02:13Z 10-23 on 767bb62c7: 33 commits cherry-picked from gizmoduck/row270-271-r4 49cee846e (base 25c09f19f), range-diff all '=', 40 paths identical to 49cee846e. Manifest f4174458 (15 paths) matches the tip. Duckworth APPROVE c30930 rev 3389. C2 run 5 GREEN on 53406f3e4: bus 873, seat 202, cli 905, ten scripts, 38/38 mutants killed. #1775 closes. |
|
||||
| 271 | 264d T1 item 7: clear context through row 194's lifecycle stop | gizmoduck; reviewers duckworth | #1776 | done | 194 done, 269 done | Duckworth approves this slice's manifest. Its design tests run whole plus every touched suite on Sage's slot, and its mutants are killed (RULINGS Q1). Tests T4 and T6; rebased onto 194's landing with no 194 code copied (Q4). (sage) | `docs/plans/2026-10-21_t1-sessions.md` § T1 item 7: independent sessions, compaction counts and clear context | LANDED 7328da8ca (with 270, mos-1351) 02:13Z 10-23: tip 2b964a082 is in the 33-commit pick, range-diff all '='. Manifest 3ab1f5c8 (33 paths): 29 match the tip; BUILD.md(270), bus README, launcher.mjs and compactions.mjs moved under 270 and match 270's f4174458. Duckworth APPROVE rev 3380. Combined C2 run 5 GREEN, 271 M1-M14 killed. #1776 closes. |
|
||||
| 272 | 264e T1 item 7: mosaic session CLI and Console chooser | huey; reviewers scrooge | #1777 | in-review, round 2, request posted | 264 done | Duckworth approves this slice's manifest. Its design tests run whole plus every touched suite on Sage's slot, and its mutants are killed (RULINGS Q1). Tests T5 legacy single human and T7 Console half; controls for unlanded verbs refuse with a reason (Q1, Q7). (sage) | `docs/plans/2026-10-21_t1-sessions.md` § T1 item 7: independent sessions, compaction counts and clear context | — |
|
||||
| 272 | 264e T1 item 7: mosaic session CLI and Console chooser | huey; reviewers scrooge | #1777 | in-progress | 264 done | Duckworth approves this slice's manifest. Its design tests run whole plus every touched suite on Sage's slot, and its mutants are killed (RULINGS Q1). Tests T5 legacy single human and T7 Console half; controls for unlanded verbs refuse with a reason (Q1, Q7). (sage) | `docs/plans/2026-10-21_t1-sessions.md` § T1 item 7: independent sessions, compaction counts and clear context | — |
|
||||
| 273 | Q175 phase 2: stack-release.sh activate --send and --no-sso (F39, mos-1246) | darkwing; reviewers filbert | #1778 | done | — | Filbert approves the manifest. stack-release.test.mjs and stack-release-external.test.mjs run whole plus scripts/test-release.sh on Sage's slot, and the brief's mutants are killed. (sage) | `docs/plans/2026-10-22_activate-send-nosso.md` § Brief: activate --send and --no-sso | landed 0bbf0f6d1 03:35:55Z, FF of 378a76b85; rebase of cac7d0f67, 6 range-diff pairs =, patch-ids equal, manifest e1031023 unchanged. Gate by Darkwing on 0bbf0f6d1: stack-release.test 218/218, external 25/25, test-release.sh rc 0, T58 c0 pass c1 fail, M1-M7 killed. Filbert APPROVE rev 3111 c30308, carry c30319. Docs 5365adaef (TOOLS.md N1 + BUILD-LOG). #1778. |
|
||||
| 274 | FED R3: broker user principal (#414) | morgana; reviewers dewey | #1779 | done | — | Dewey approves the manifest. The bus and harness suites and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-22_federation-r3.md` § Brief: FED R3, the broker user principal | LANDED 4c485c63b ff from 47a35bf43 (6 Morgana commits). Dewey APPROVE c30487 on 4c485c63b (manifest 00047b52, 13 paths). Gate 10:09-10:22Z: 23 touched files 0 fail, bus 787, harness 151, business 228, cli 832, seat 167, 10 scripts rc=0 (skips test-queue 1, test-task 2), 22/22 mutants. M3x wall code not-holder (kit comment said human-required). r5 f58cfc361 red, void. Overlap 13/257 clean. |
|
||||
| 275 | 193b1b: viewer verbs and board refusals (also after FED R4 when filed) | morgana; reviewers duckworth | #1780 | done | 205 done, 274 done | Duckworth approves the manifest. The bus suite and every scripts/test-*.sh are green on Sage's gate, and the mutants are killed. (sage) | `docs/plans/2026-10-20_human-users-build.md` § Brief: 193b1b, viewer verbs and board refusals | Landed 3410df7c3 on refactor (fast-forward from 48e450ce8, 3 commits; landed sha = candidate, so range-diff and patch-id are identical by construction). Manifest 39847b15 (4 paths) blobs match the commit. Gate: whole files 7/22/6, bus 834, cli 861, harness 151, business 231, seat 167, 0 fail; 10 scripts/test-*.sh rc 0 with 3 named skips; M6 and M10 killed. Duckworth APPROVE round 1, Gitea #1780 comment 30717. |
|
||||
@@ -340,9 +340,6 @@ Generated from `docs/plans/queue.json` revision 3530 by `queue render`. Do not e
|
||||
| 301 | R6-N4: fold user-bus.mjs back into bus.mjs (294 N4) | launchpad; reviewers duckworth | #1808 | briefed | 294 done | Duckworth approves the manifest; channel-proof.test, webui suite and 294 user-transport tests whole and green; re-pin only with Mos go (sage) | `docs/plans/2026-10-23_r6-followup-rows.md` § Brief: R6-N4, fold user-bus.mjs back into bus.mjs | — |
|
||||
| 302 | Idle-stop race: an idle-released run's last call ends it session-invalid/22 (Vikunja 588) | gizmoduck; reviewers dewey | #1809 | done | 292 done | Dewey approves the design, then the manifest; forcing test, compactions-launch.test whole, bus/cli/harness suites, all scripts/test-*.sh; fix-drop mutant dies (sage) | `docs/plans/2026-10-23_idle-stop-race-row.md` § Brief: the idle-stop race (Vikunja 588) | Landed 3ed9fd754 08:49Z 10-23: Sage cherry-picked 0e30a85fa..2a8281a6f (7 commits) onto 1ac655005; range-diff all equal, patch-ids match, tree equals gated merge 783602e06 plus packet-only 2a8281a6f files. Gate run 2 green (bus 876, harness 151, cli 918, ten test-*.sh, M1-M5 M7-M9 killed). Dewey approve rev 3492 c31092. mos-1430 fixed launcher-released.test:89. mos-1411 rerun allowance ends. |
|
||||
| 303 | R9 shows its output when rehearse makes no directory (Vikunja 589) | launchpad; reviewers duckworth | #1810 | in-review, round 1, request posted | 294 done | Duckworth approves the diff; stack-release.test.mjs whole and green on Sage's gate, in a gap (sage) | `docs/plans/2026-10-23_r9-guard-row.md` § Brief: R9 shows its output when rehearse makes no directory (Vikunja 589) | — |
|
||||
| 304 | claude-session test builds the memory slug the way the CLI does (Vikunja 590) | rocko; reviewers dewey | #1811 | in-review, round 1, request posted | — | Dewey approves the diff; claude-session.test.mjs whole and green 3x (mktemp, underscore, space TMPDIRs) on Sage's gate, in a gap; old-regex mutant red at :298 (sage) | `docs/plans/2026-10-23_gate-env-rows.md` § Brief: claude-session test builds the memory slug the way the CLI does (Vikunja 590) | — |
|
||||
| 305 | Shell suites remove the compose network they create (Vikunja 591) | gizmoduck; reviewers filbert | #1812 | in-review, round 1, request posted | — | Filbert approves the diff; test-release.sh and test-task.sh whole and green on Sage's gate, in a gap, project network absent after each run; dropped-rm mutant red (sage) | `docs/plans/2026-10-23_gate-env-rows.md` § Brief: shell suites remove the compose network they create (Vikunja 591) | — |
|
||||
| 306 | A revoked run's late bus call stops it instead of exiting 22 (295 N1) | morgana; reviewers dewey | #1813 | briefed | 272 done | Dewey approves the design, then the manifest; bus, harness and cli suites and every scripts/test-*.sh green on Sage's gate (sage) | `docs/plans/2026-10-23_gate-env-rows.md` § Brief: a revoked run's late bus call stops it instead of exiting 22 (295 N1) | — |
|
||||
|
||||
<!-- mosaic-queue:end -->
|
||||
|
||||
|
||||
+4
-789
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"canonicalRoot": "/mnt/storage/src/mosaic-stack",
|
||||
"revision": 3530,
|
||||
"revision": 3510,
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
@@ -27980,7 +27980,7 @@
|
||||
"closes": [
|
||||
1777
|
||||
],
|
||||
"state": "in-review",
|
||||
"state": "in-progress",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
@@ -28059,51 +28059,6 @@
|
||||
"candidate": "0c3dc2edde0634ee531dadd12aedbcc372d82f3f16345f2b521c5f696271e9a6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": 2,
|
||||
"op": "huey-272-review-20261023-2",
|
||||
"by": "huey",
|
||||
"at": "2026-10-23T10:57:07.240Z",
|
||||
"issue": 1777,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "b44332a9360504291dda3f81131c934b286f3226",
|
||||
"text": null
|
||||
},
|
||||
"request": "comment",
|
||||
"attempts": [
|
||||
{
|
||||
"op": "huey-272-review-20261023-2",
|
||||
"by": "huey",
|
||||
"at": "2026-10-23T10:57:07.240Z",
|
||||
"state": "failed",
|
||||
"comment": null,
|
||||
"transport": {
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"resolutions": []
|
||||
},
|
||||
{
|
||||
"op": "sage-3365",
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:00:02.830Z",
|
||||
"state": "posted",
|
||||
"comment": 31120,
|
||||
"transport": {
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31120,
|
||||
"detail": "created"
|
||||
},
|
||||
"resolutions": []
|
||||
}
|
||||
],
|
||||
"duplicateRisk": false,
|
||||
"receipts": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -28114,8 +28069,8 @@
|
||||
"note": null,
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-10-22T00:11:15.380Z",
|
||||
"updatedAt": "2026-10-23T11:00:48.036Z",
|
||||
"updatedBy": "sage"
|
||||
"updatedAt": "2026-10-23T10:43:59.038Z",
|
||||
"updatedBy": "huey"
|
||||
},
|
||||
{
|
||||
"id": 273,
|
||||
@@ -30578,212 +30533,6 @@
|
||||
"createdAt": "2026-10-23T07:07:24.046Z",
|
||||
"updatedAt": "2026-10-23T07:53:06.871Z",
|
||||
"updatedBy": "duckworth"
|
||||
},
|
||||
{
|
||||
"id": 304,
|
||||
"piece": "claude-session test builds the memory slug the way the CLI does (Vikunja 590)",
|
||||
"owner": "rocko",
|
||||
"issues": [
|
||||
1811
|
||||
],
|
||||
"closes": [
|
||||
1811
|
||||
],
|
||||
"state": "in-review",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Dewey approves the diff; claude-session.test.mjs whole and green 3x (mktemp, underscore, space TMPDIRs) on Sage's gate, in a gap; old-regex mutant red at :298",
|
||||
"gateOwner": "sage",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: claude-session test builds the memory slug the way the CLI does (Vikunja 590)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"dewey"
|
||||
],
|
||||
"review": {
|
||||
"rounds": [
|
||||
{
|
||||
"n": 1,
|
||||
"op": "rocko-304-inreview-r1",
|
||||
"by": "rocko",
|
||||
"at": "2026-10-23T11:21:27.231Z",
|
||||
"issue": 1811,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "5e8354ebbb29213e63e979b01db5eb78d02cd8e2",
|
||||
"text": null
|
||||
},
|
||||
"request": "comment",
|
||||
"attempts": [
|
||||
{
|
||||
"op": "rocko-304-inreview-r1",
|
||||
"by": "rocko",
|
||||
"at": "2026-10-23T11:21:27.231Z",
|
||||
"state": "failed",
|
||||
"comment": null,
|
||||
"transport": {
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"resolutions": []
|
||||
},
|
||||
{
|
||||
"op": "sage-3389",
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:24:42.204Z",
|
||||
"state": "posted",
|
||||
"comment": 31128,
|
||||
"transport": {
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31128,
|
||||
"detail": "created"
|
||||
},
|
||||
"resolutions": []
|
||||
}
|
||||
],
|
||||
"duplicateRisk": false,
|
||||
"receipts": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"claim": {
|
||||
"seat": "rocko",
|
||||
"op": "rocko-304-start-r1"
|
||||
},
|
||||
"note": null,
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-10-23T10:52:32.326Z",
|
||||
"updatedAt": "2026-10-23T11:25:26.615Z",
|
||||
"updatedBy": "sage"
|
||||
},
|
||||
{
|
||||
"id": 305,
|
||||
"piece": "Shell suites remove the compose network they create (Vikunja 591)",
|
||||
"owner": "gizmoduck",
|
||||
"issues": [
|
||||
1812
|
||||
],
|
||||
"closes": [
|
||||
1812
|
||||
],
|
||||
"state": "in-review",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Filbert approves the diff; test-release.sh and test-task.sh whole and green on Sage's gate, in a gap, project network absent after each run; dropped-rm mutant red",
|
||||
"gateOwner": "sage",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: shell suites remove the compose network they create (Vikunja 591)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"review": {
|
||||
"rounds": [
|
||||
{
|
||||
"n": 1,
|
||||
"op": "gizmoduck-305-review-1",
|
||||
"by": "gizmoduck",
|
||||
"at": "2026-10-23T11:16:24.801Z",
|
||||
"issue": 1812,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "7e8218a2ed32ad7813d397577bf752ad37bac0d9",
|
||||
"text": null
|
||||
},
|
||||
"request": "comment",
|
||||
"attempts": [
|
||||
{
|
||||
"op": "gizmoduck-305-review-1",
|
||||
"by": "gizmoduck",
|
||||
"at": "2026-10-23T11:16:24.801Z",
|
||||
"state": "failed",
|
||||
"comment": null,
|
||||
"transport": {
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"resolutions": []
|
||||
},
|
||||
{
|
||||
"op": "sage-3384",
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:18:11.927Z",
|
||||
"state": "posted",
|
||||
"comment": 31126,
|
||||
"transport": {
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31126,
|
||||
"detail": "created"
|
||||
},
|
||||
"resolutions": []
|
||||
}
|
||||
],
|
||||
"duplicateRisk": false,
|
||||
"receipts": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"claim": {
|
||||
"seat": "gizmoduck",
|
||||
"op": "gizmoduck-305-claim"
|
||||
},
|
||||
"note": null,
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-10-23T10:53:17.130Z",
|
||||
"updatedAt": "2026-10-23T11:18:57.401Z",
|
||||
"updatedBy": "sage"
|
||||
},
|
||||
{
|
||||
"id": 306,
|
||||
"piece": "A revoked run's late bus call stops it instead of exiting 22 (295 N1)",
|
||||
"owner": "morgana",
|
||||
"issues": [
|
||||
1813
|
||||
],
|
||||
"closes": [
|
||||
1813
|
||||
],
|
||||
"state": "briefed",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Dewey approves the design, then the manifest; bus, harness and cli suites and every scripts/test-*.sh green on Sage's gate",
|
||||
"gateOwner": "sage",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: a revoked run's late bus call stops it instead of exiting 22 (295 N1)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"after": [
|
||||
{
|
||||
"id": 272,
|
||||
"when": "done"
|
||||
}
|
||||
],
|
||||
"reviewers": [
|
||||
"dewey"
|
||||
],
|
||||
"review": null,
|
||||
"claim": null,
|
||||
"note": null,
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-10-23T10:54:05.081Z",
|
||||
"updatedAt": "2026-10-23T10:56:18.572Z",
|
||||
"updatedBy": "sage"
|
||||
}
|
||||
],
|
||||
"log": [
|
||||
@@ -123104,540 +122853,6 @@
|
||||
"receipt": "ok huey-272-rebase-20261023-2 rev 3510 row 272 in-review→in-progress"
|
||||
},
|
||||
"viewSha": "a8a705067d71f07a5bd3c988f4c823be148c4fcd85512721d256e584a91dfede"
|
||||
},
|
||||
{
|
||||
"rev": 3511,
|
||||
"op": "sage-590-add",
|
||||
"verb": "add",
|
||||
"args": {
|
||||
"piece": "claude-session test builds the memory slug the way the CLI does (Vikunja 590)",
|
||||
"gate": "Dewey approves the diff; claude-session.test.mjs whole and green 3x (mktemp, underscore, space TMPDIRs) on Sage's gate, in a gap; old-regex mutant red at :298",
|
||||
"brief": "docs/plans/2026-10-23_gate-env-rows.md#Brief: claude-session test builds the memory slug the way the CLI does (Vikunja 590)",
|
||||
"issues": [
|
||||
1811
|
||||
],
|
||||
"note": null,
|
||||
"owner": "rocko",
|
||||
"gateOwner": "sage",
|
||||
"after": null,
|
||||
"reviewers": [
|
||||
"dewey"
|
||||
],
|
||||
"required": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:52:32.326Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"from": null,
|
||||
"to": "queued",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: claude-session test builds the memory slug the way the CLI does (Vikunja 590)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"receipt": "ok sage-590-add rev 3511 row 304 none→queued"
|
||||
},
|
||||
"viewSha": "a26bfc22d1bf02c5886a604b2351dba4258f7d2ce475150355416b51ee91c502"
|
||||
},
|
||||
{
|
||||
"rev": 3512,
|
||||
"op": "sage-591-add",
|
||||
"verb": "add",
|
||||
"args": {
|
||||
"piece": "Shell suites remove the compose network they create (Vikunja 591)",
|
||||
"gate": "Filbert approves the diff; test-release.sh and test-task.sh whole and green on Sage's gate, in a gap, project network absent after each run; dropped-rm mutant red",
|
||||
"brief": "docs/plans/2026-10-23_gate-env-rows.md#Brief: shell suites remove the compose network they create (Vikunja 591)",
|
||||
"issues": [
|
||||
1812
|
||||
],
|
||||
"note": null,
|
||||
"owner": "gizmoduck",
|
||||
"gateOwner": "sage",
|
||||
"after": null,
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"required": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:53:17.130Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"from": null,
|
||||
"to": "queued",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: shell suites remove the compose network they create (Vikunja 591)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"receipt": "ok sage-591-add rev 3512 row 305 none→queued"
|
||||
},
|
||||
"viewSha": "f799274a6952d5350258c467212f7045a5ae931c4b4fd16691d6ef98ca412bad"
|
||||
},
|
||||
{
|
||||
"rev": 3513,
|
||||
"op": "sage-revoke-add",
|
||||
"verb": "add",
|
||||
"args": {
|
||||
"piece": "A revoked run's late bus call stops it instead of exiting 22 (295 N1)",
|
||||
"gate": "Dewey approves the design, then the manifest; bus, harness and cli suites and every scripts/test-*.sh green on Sage's gate",
|
||||
"brief": "docs/plans/2026-10-23_gate-env-rows.md#Brief: a revoked run's late bus call stops it instead of exiting 22 (295 N1)",
|
||||
"issues": [
|
||||
1813
|
||||
],
|
||||
"note": null,
|
||||
"owner": "morgana",
|
||||
"gateOwner": "sage",
|
||||
"after": [
|
||||
{
|
||||
"id": 272,
|
||||
"when": "done"
|
||||
}
|
||||
],
|
||||
"reviewers": [
|
||||
"dewey"
|
||||
],
|
||||
"required": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:54:05.081Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 306,
|
||||
"from": null,
|
||||
"to": "queued",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-10-23_gate-env-rows.md",
|
||||
"anchor": "Brief: a revoked run's late bus call stops it instead of exiting 22 (295 N1)",
|
||||
"blob": "2283f33e6553c8f767f3f756660e6182c8b59a10"
|
||||
},
|
||||
"receipt": "ok sage-revoke-add rev 3513 row 306 none→queued"
|
||||
},
|
||||
"viewSha": "d7443f23b81baa516395b25bfa1d76a827f98cf749faa4e05e3a0f77791bb76c"
|
||||
},
|
||||
{
|
||||
"rev": 3514,
|
||||
"op": "sage-304-brief",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 304,
|
||||
"to": "briefed",
|
||||
"reason": null,
|
||||
"candidate": null,
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:54:49.183Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"from": "queued",
|
||||
"to": "briefed",
|
||||
"round": null,
|
||||
"issue": null,
|
||||
"candidate": null,
|
||||
"receipt": "ok sage-304-brief rev 3514 row 304 queued→briefed"
|
||||
},
|
||||
"viewSha": "f8fa13caab165d2c41927e6afd46f40f5ab9094aca22b5a658363a9b4c6874a1"
|
||||
},
|
||||
{
|
||||
"rev": 3515,
|
||||
"op": "sage-305-brief",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 305,
|
||||
"to": "briefed",
|
||||
"reason": null,
|
||||
"candidate": null,
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:55:33.716Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"from": "queued",
|
||||
"to": "briefed",
|
||||
"round": null,
|
||||
"issue": null,
|
||||
"candidate": null,
|
||||
"receipt": "ok sage-305-brief rev 3515 row 305 queued→briefed"
|
||||
},
|
||||
"viewSha": "edea729fb7decc1d99e0abec9673a88c168eb559c5955e16ad7352ec32645d67"
|
||||
},
|
||||
{
|
||||
"rev": 3516,
|
||||
"op": "sage-306-brief",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 306,
|
||||
"to": "briefed",
|
||||
"reason": null,
|
||||
"candidate": null,
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T10:56:18.572Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 306,
|
||||
"from": "queued",
|
||||
"to": "briefed",
|
||||
"round": null,
|
||||
"issue": null,
|
||||
"candidate": null,
|
||||
"receipt": "ok sage-306-brief rev 3516 row 306 queued→briefed"
|
||||
},
|
||||
"viewSha": "1ffac5c9bd665eade67ad63f2855c39dbcad1b7ae2d9c935835ef0a3d2b5bedd"
|
||||
},
|
||||
{
|
||||
"rev": 3517,
|
||||
"op": "huey-272-review-20261023-2",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 272,
|
||||
"to": "in-review",
|
||||
"reason": null,
|
||||
"candidate": "b44332a9360504291dda3f81131c934b286f3226",
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "huey",
|
||||
"at": "2026-10-23T10:57:07.240Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 272,
|
||||
"from": "in-progress",
|
||||
"to": "in-review",
|
||||
"round": 2,
|
||||
"issue": 1777,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "b44332a9360504291dda3f81131c934b286f3226",
|
||||
"text": null
|
||||
},
|
||||
"receipt": "ok huey-272-review-20261023-2 rev 3517 row 272 in-progress→in-review round 2 on #1777; request huey-272-review-20261023-2 requesting"
|
||||
},
|
||||
"viewSha": "329fceeba0bae0f19c1f7e8028b923f58d523f4e4ce3f4879bb86314e24c2073"
|
||||
},
|
||||
{
|
||||
"rev": 3518,
|
||||
"op": "huey-272-review-20261023-2.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 272,
|
||||
"attempt": "huey-272-review-20261023-2",
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"by": "huey",
|
||||
"at": "2026-10-23T10:57:51.419Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 272,
|
||||
"round": 2,
|
||||
"attempt": "huey-272-review-20261023-2",
|
||||
"state": "failed",
|
||||
"receipt": "ok huey-272-review-20261023-2.outcome rev 3518 row 272 round 2 request huey-272-review-20261023-2 failed"
|
||||
},
|
||||
"viewSha": "cb46a6668d7ada6c491a3ee46aab5cc4106246c2761a946cfa3e13588b5e5521"
|
||||
},
|
||||
{
|
||||
"rev": 3519,
|
||||
"op": "sage-3365",
|
||||
"verb": "review-request",
|
||||
"args": {
|
||||
"id": 272
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:00:02.830Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 272,
|
||||
"round": 2,
|
||||
"attempt": "sage-3365",
|
||||
"state": "requesting",
|
||||
"receipt": "ok sage-3365 rev 3519 row 272 round 2 request sage-3365 requesting"
|
||||
},
|
||||
"viewSha": "d945eb7288f69c9417c5fff6cddbe5fe399deb9cc95694744348e0a90726d548"
|
||||
},
|
||||
{
|
||||
"rev": 3520,
|
||||
"op": "sage-3365.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 272,
|
||||
"attempt": "sage-3365",
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31120,
|
||||
"detail": "created"
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:00:48.036Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 272,
|
||||
"round": 2,
|
||||
"attempt": "sage-3365",
|
||||
"state": "posted",
|
||||
"receipt": "ok sage-3365.outcome rev 3520 row 272 round 2 request sage-3365 posted comment 31120"
|
||||
},
|
||||
"viewSha": "707b758ea2d53c121c93afe484be5af1efd4dd1077831ba605d53a8429bc767a"
|
||||
},
|
||||
{
|
||||
"rev": 3521,
|
||||
"op": "rocko-304-start-r1",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 304,
|
||||
"to": "in-progress",
|
||||
"reason": null,
|
||||
"candidate": null,
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "rocko",
|
||||
"at": "2026-10-23T11:04:23.003Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"from": "briefed",
|
||||
"to": "in-progress",
|
||||
"round": null,
|
||||
"issue": null,
|
||||
"candidate": null,
|
||||
"receipt": "ok rocko-304-start-r1 rev 3521 row 304 briefed→in-progress"
|
||||
},
|
||||
"viewSha": "fc965e5336eb549ad0b853519a64437ab4248309b61ec4c2bc4dd545face0e76"
|
||||
},
|
||||
{
|
||||
"rev": 3522,
|
||||
"op": "gizmoduck-305-claim",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 305,
|
||||
"to": "in-progress",
|
||||
"reason": null,
|
||||
"candidate": null,
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "gizmoduck",
|
||||
"at": "2026-10-23T11:12:53.930Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"from": "briefed",
|
||||
"to": "in-progress",
|
||||
"round": null,
|
||||
"issue": null,
|
||||
"candidate": null,
|
||||
"receipt": "ok gizmoduck-305-claim rev 3522 row 305 briefed→in-progress"
|
||||
},
|
||||
"viewSha": "d57f4a6223f592a772062ffcdab95793decbcf7065d8fbf1898031ae9b4a8e36"
|
||||
},
|
||||
{
|
||||
"rev": 3523,
|
||||
"op": "gizmoduck-305-review-1",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 305,
|
||||
"to": "in-review",
|
||||
"reason": null,
|
||||
"candidate": "7e8218a2ed32ad7813d397577bf752ad37bac0d9",
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "gizmoduck",
|
||||
"at": "2026-10-23T11:16:24.801Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"from": "in-progress",
|
||||
"to": "in-review",
|
||||
"round": 1,
|
||||
"issue": 1812,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "7e8218a2ed32ad7813d397577bf752ad37bac0d9",
|
||||
"text": null
|
||||
},
|
||||
"receipt": "ok gizmoduck-305-review-1 rev 3523 row 305 in-progress→in-review round 1 on #1812; request gizmoduck-305-review-1 requesting"
|
||||
},
|
||||
"viewSha": "d44f8b9ac68b93a2c2977a90b9615fa556e1a98d647cb65790400344663ed8b5"
|
||||
},
|
||||
{
|
||||
"rev": 3524,
|
||||
"op": "gizmoduck-305-review-1.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 305,
|
||||
"attempt": "gizmoduck-305-review-1",
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"by": "gizmoduck",
|
||||
"at": "2026-10-23T11:17:09.278Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"round": 1,
|
||||
"attempt": "gizmoduck-305-review-1",
|
||||
"state": "failed",
|
||||
"receipt": "ok gizmoduck-305-review-1.outcome rev 3524 row 305 round 1 request gizmoduck-305-review-1 failed"
|
||||
},
|
||||
"viewSha": "569d1d643931c96645cf13016da9282b2012039b436c82f3441625d1a9252edd"
|
||||
},
|
||||
{
|
||||
"rev": 3525,
|
||||
"op": "sage-3384",
|
||||
"verb": "review-request",
|
||||
"args": {
|
||||
"id": 305
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:18:11.927Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"round": 1,
|
||||
"attempt": "sage-3384",
|
||||
"state": "requesting",
|
||||
"receipt": "ok sage-3384 rev 3525 row 305 round 1 request sage-3384 requesting"
|
||||
},
|
||||
"viewSha": "82835f9b81f99439ca8ec21e7b7bd0188244317993217598a7c5b60795074763"
|
||||
},
|
||||
{
|
||||
"rev": 3526,
|
||||
"op": "sage-3384.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 305,
|
||||
"attempt": "sage-3384",
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31126,
|
||||
"detail": "created"
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:18:57.401Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 305,
|
||||
"round": 1,
|
||||
"attempt": "sage-3384",
|
||||
"state": "posted",
|
||||
"receipt": "ok sage-3384.outcome rev 3526 row 305 round 1 request sage-3384 posted comment 31126"
|
||||
},
|
||||
"viewSha": "e6dfab0a2e5a2be5e6793f5adbe06cc97413f194ec5bbfaa3d22eacc3d044c08"
|
||||
},
|
||||
{
|
||||
"rev": 3527,
|
||||
"op": "rocko-304-inreview-r1",
|
||||
"verb": "move",
|
||||
"args": {
|
||||
"id": 304,
|
||||
"to": "in-review",
|
||||
"reason": null,
|
||||
"candidate": "5e8354ebbb29213e63e979b01db5eb78d02cd8e2",
|
||||
"evidence": null,
|
||||
"issue": null
|
||||
},
|
||||
"by": "rocko",
|
||||
"at": "2026-10-23T11:21:27.231Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"from": "in-progress",
|
||||
"to": "in-review",
|
||||
"round": 1,
|
||||
"issue": 1811,
|
||||
"candidate": {
|
||||
"kind": "commit",
|
||||
"digest": "5e8354ebbb29213e63e979b01db5eb78d02cd8e2",
|
||||
"text": null
|
||||
},
|
||||
"receipt": "ok rocko-304-inreview-r1 rev 3527 row 304 in-progress→in-review round 1 on #1811; request rocko-304-inreview-r1 requesting"
|
||||
},
|
||||
"viewSha": "3a95f602dcc8535bb69946fcb6bced5b37b812308763e67e7273b93fa95cb0a6"
|
||||
},
|
||||
{
|
||||
"rev": 3528,
|
||||
"op": "rocko-304-inreview-r1.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 304,
|
||||
"attempt": "rocko-304-inreview-r1",
|
||||
"outcome": "failed",
|
||||
"status": null,
|
||||
"comment": null,
|
||||
"detail": "pre-send: the credential or account check failed"
|
||||
},
|
||||
"by": "rocko",
|
||||
"at": "2026-10-23T11:22:12.599Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"round": 1,
|
||||
"attempt": "rocko-304-inreview-r1",
|
||||
"state": "failed",
|
||||
"receipt": "ok rocko-304-inreview-r1.outcome rev 3528 row 304 round 1 request rocko-304-inreview-r1 failed"
|
||||
},
|
||||
"viewSha": "509732e75c087a8ef263343fb13ac95fae8fa1cd77b5f18b8e596e7aa9a17dac"
|
||||
},
|
||||
{
|
||||
"rev": 3529,
|
||||
"op": "sage-3389",
|
||||
"verb": "review-request",
|
||||
"args": {
|
||||
"id": 304
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:24:42.204Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"round": 1,
|
||||
"attempt": "sage-3389",
|
||||
"state": "requesting",
|
||||
"receipt": "ok sage-3389 rev 3529 row 304 round 1 request sage-3389 requesting"
|
||||
},
|
||||
"viewSha": "4d4d870a9bbfa7588ddb50ac19b2ef49793de1a33af1e1b23cd6afe9e99a211e"
|
||||
},
|
||||
{
|
||||
"rev": 3530,
|
||||
"op": "sage-3389.outcome",
|
||||
"verb": "review-outcome",
|
||||
"args": {
|
||||
"id": 304,
|
||||
"attempt": "sage-3389",
|
||||
"outcome": "posted",
|
||||
"status": 201,
|
||||
"comment": 31128,
|
||||
"detail": "created"
|
||||
},
|
||||
"by": "sage",
|
||||
"at": "2026-10-23T11:25:26.615Z",
|
||||
"semantics": 2,
|
||||
"result": {
|
||||
"row": 304,
|
||||
"round": 1,
|
||||
"attempt": "sage-3389",
|
||||
"state": "posted",
|
||||
"receipt": "ok sage-3389.outcome rev 3530 row 304 round 1 request sage-3389 posted comment 31128"
|
||||
},
|
||||
"viewSha": "87599e0506c236d84a6833de991592eb826cefd48859901cacc1d6ef2246a436"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
// R6-N1 (#1807, row 294 N1): the user-session option swap in serve.mjs, driven through HTTP.
|
||||
// granted-user.test.mjs G4 stops every owner route at the userRoute gate, so it never reaches the
|
||||
// swap behind it. Here serve.mjs loads with that gate stubbed open (a load hook keyed on one query
|
||||
// string; the product file is unchanged), and every owner route a user session might try must reach
|
||||
// no owner option. The owner transport may carry only the plugins read mos-1394 allowed.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { request } from 'node:http';
|
||||
import { registerHooks } from 'node:module';
|
||||
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { Store } from '../../bus/src/store.mjs';
|
||||
import { Broker } from '../../bus/src/broker.mjs';
|
||||
import { createSso, SESSION_COOKIE } from '../src/sso.mjs';
|
||||
import { consoleAccess } from '../src/access.mjs';
|
||||
import { userOptionsFor } from '../src/console-bus.mjs';
|
||||
import { BusReadError } from '../src/bus.mjs';
|
||||
import { close } from './fixture.mjs';
|
||||
import { fakeOidc } from './helpers/fake-oidc.mjs';
|
||||
|
||||
const SERVE = new URL('../src/serve.mjs', import.meta.url).href, OPEN = `${SERVE}?gate=open`;
|
||||
const GATE = 'export function userRoute(path, method) {';
|
||||
registerHooks({
|
||||
load(url, context, next) {
|
||||
const r = next(url, context);
|
||||
if (url !== OPEN) return r;
|
||||
const source = String(r.source);
|
||||
// A renamed gate fails here rather than leaving the test on the closed gate.
|
||||
if (source.split(GATE).length !== 2) throw new Error('serve.mjs: the userRoute gate is not there exactly once');
|
||||
return { ...r, source: source.replace(GATE, `${GATE} return true;`) };
|
||||
},
|
||||
});
|
||||
const { startServer, userRoute } = await import(OPEN);
|
||||
|
||||
const HOST = 'console.example.test', ORIGIN = `https://${HOST}`;
|
||||
|
||||
function call(port, { method = 'GET', path = '/', headers = {}, body } = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const length = body === undefined ? {} : { 'content-length': Buffer.byteLength(body) };
|
||||
const req = request({ host: '127.0.0.1', port, method, path, headers: { host: HOST, ...length, ...headers } }, res => {
|
||||
let text = '';
|
||||
res.on('data', c => (text += c));
|
||||
res.on('end', () => resolve({ status: res.statusCode, headers: res.headers, body: text }));
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.end(body);
|
||||
});
|
||||
}
|
||||
const setCookies = r => [r.headers['set-cookie'] ?? []].flat();
|
||||
const writeHeaders = cookie => ({ cookie, origin: ORIGIN, 'sec-fetch-site': 'same-origin', 'content-type': 'application/json' });
|
||||
|
||||
// As granted-user.test.mjs setup: the fake OP, a broker for `demo`, createSso with the access hook,
|
||||
// counting owner stubs, and consoleBus over alice's transport for her session. Only startServer
|
||||
// differs: it is the gate-open copy.
|
||||
async function setup(t) {
|
||||
const op = await fakeOidc();
|
||||
t.after(() => op.close());
|
||||
const iss = op.issuer('a');
|
||||
const root = mkdtempSync(join(tmpdir(), 'webui-option-swap-'));
|
||||
const store = new Store(root);
|
||||
t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); });
|
||||
const doc = { accessVersion: 1, revision: 1, users: [{ id: 'alice', home: 'local', subjects: [{ provider: 'a', sub: 'alice-sub' }] }],
|
||||
grants: [{ id: 'g-1', user: 'alice', business: 'demo', projects: ['*'], instances: ['assistant'], level: 'collaborator' }] };
|
||||
const load = () => doc;
|
||||
const broker = new Broker({
|
||||
store,
|
||||
businesses: {
|
||||
demo: {
|
||||
id: 'demo', human: 'jason', arbiters: { technical: 'chief', delivery: 'chief' }, vars: {},
|
||||
roles: {
|
||||
chief: { definition: 'chief-of-staff', authority: { withinRole: ['message.send'], crossRole: [] } },
|
||||
assistant: { definition: 'assistant', authority: { withinRole: ['message.send'], crossRole: [] } },
|
||||
},
|
||||
definitions: { 'chief-of-staff': {}, assistant: { messaging: JSON.parse(readFileSync(new URL('../../../roles/assistant.json', import.meta.url), 'utf8')).messaging } },
|
||||
},
|
||||
},
|
||||
access: load,
|
||||
});
|
||||
const owner = [], user = [], opened = [];
|
||||
const userTransport = name => async (verb, args = {}) => {
|
||||
user.push(verb);
|
||||
try { return broker.request(broker.bindUser({ business: 'demo', user: name }), { verb, args }); }
|
||||
catch (e) { throw new BusReadError(e.code ?? 'invalid-response'); }
|
||||
};
|
||||
const ownerCall = async (verb, args) => { owner.push(['transport', verb, args]); return { plugins: { channel: ['webui'] } }; };
|
||||
const userOptions = userOptionsFor({ owner: ownerCall, send: true, transport: name => { opened.push(name); return userTransport(name); } });
|
||||
const lines = [];
|
||||
const config = { publicOrigin: ORIGIN, providers: [{ id: 'a', issuer: iss.issuer, clientId: iss.clientId, clientSecret: { slot: 'a' }, algs: ['RS256'], subjects: [{ sub: 'owner-sub', name: 'jason' }] }] };
|
||||
const sso = await createSso(config, { secrets: new Map([['a', iss.clientSecret]]), fetch: op.fetch, log: l => lines.push(l), users: consoleAccess({ load, business: () => 'demo' }) });
|
||||
t.after(() => sso.close());
|
||||
// Every owner option is a stub that records its own name.
|
||||
const stub = name => async () => { owner.push(['option', name]); return name === 'send' ? { id: 'msg-0001' } : [{ verb: name }]; };
|
||||
const options = {
|
||||
bus: Object.fromEntries(['inbox', 'tasks', 'agents', 'trail', 'decisions', 'names', 'instances', 'routes', 'thread.claims'].map(v => [v, stub(`bus.${v}`)])),
|
||||
send: stub('send'), settingsWrite: stub('settingsWrite'), projectFiles: stub('projectFiles'), projectFile: stub('projectFile'), projectSave: stub('projectSave'),
|
||||
nameWrite: stub('nameWrite'), assistantStop: stub('assistantStop'), instancesWrite: stub('instancesWrite'), routesWrite: stub('routesWrite'), agentWrite: stub('agentWrite'),
|
||||
processing: { read: stub('processing.read'), halt: stub('processing.halt'), resume: stub('processing.resume') },
|
||||
reads: Object.fromEntries(['settings', 'business', 'busStatus', 'queue', 'row'].map(v => [v, stub(`reads.${v}`)])),
|
||||
chat: Object.fromEntries(['projects', 'threads', 'messages', 'send', 'open', 'createProject', 'createThread'].map(v => [v, stub(`chat.${v}`)])),
|
||||
};
|
||||
const web = await startServer({ port: 0, board: 'http://127.0.0.1:9', sso, log: l => lines.push(l), ...options, userOptions });
|
||||
t.after(() => close(web));
|
||||
return { op, iss, owner, user, opened, lines, port: web.address().port };
|
||||
}
|
||||
|
||||
async function signIn(env, sub) {
|
||||
const start = await call(env.port, { path: '/auth/login' });
|
||||
assert.equal(start.status, 303);
|
||||
const cookie = setCookies(start)[0].split(';')[0];
|
||||
const location = start.headers.location;
|
||||
const g = env.op.grant(env.iss, location, { sub });
|
||||
const q = new URLSearchParams({ code: g.code, state: new URL(location).searchParams.get('state') });
|
||||
const r = await call(env.port, { path: `/auth/callback?${q}`, headers: { cookie } });
|
||||
const session = setCookies(r).find(c => c.startsWith(`${SESSION_COOKIE}=`) && !c.includes('Max-Age=0'))?.split(';')[0];
|
||||
assert.ok(session, `${sub}: no session cookie (${r.status})`);
|
||||
return session;
|
||||
}
|
||||
|
||||
// granted-user.test.mjs G4's owner routes, plus the chat routes a user session reaches anyway.
|
||||
const ROUTES = [
|
||||
['GET', '/api/bus/inbox'], ['GET', '/api/bus/tasks'], ['GET', '/api/bus/names'], ['GET', '/api/bus/thread.claims'],
|
||||
['POST', '/api/bus/message', { to: 'coder', body: 'hi' }],
|
||||
['GET', '/api/settings'], ['POST', '/api/settings', { revision: 'x' }],
|
||||
['POST', '/api/name', { role: 'assistant', name: 'x' }], ['POST', '/api/assistant/stop', {}],
|
||||
['POST', '/api/instances', { instance: 'x' }], ['POST', '/api/routes', { routes: [] }],
|
||||
['POST', '/api/agent/launch', { instance: 'x' }], ['GET', '/api/agent/request?id=x'],
|
||||
['GET', '/api/processing'], ['POST', '/api/processing/halt', {}],
|
||||
['GET', '/api/project-files?project=p'], ['GET', '/api/project-file?project=p&path=a'], ['POST', '/api/project-file', { project: 'p' }],
|
||||
['GET', '/api/board'], ['GET', '/api/conversations'], ['POST', '/api/seen', {}], ['POST', '/api/reply', {}],
|
||||
['GET', '/api/queue'], ['GET', '/api/queue/1'], ['GET', '/api/business'], ['GET', '/api/bus-status'], ['GET', '/api/task-fields'],
|
||||
['GET', '/api/chat/projects'], ['GET', '/api/chat/instances'],
|
||||
['GET', '/app.js'], ['GET', '/bus.js'], ['GET', '/agents.js'], ['GET', '/editor.js'], ['GET', '/shared/app.css'], ['GET', '/index.html'],
|
||||
];
|
||||
const go = (env, session, [method, path, value]) => call(env.port, { method, path, headers: value === undefined ? { cookie: session } : writeHeaders(session), body: value === undefined ? undefined : JSON.stringify(value) });
|
||||
|
||||
test('R6-N1 with the userRoute gate open, a user session reaches no owner option over HTTP', async t => {
|
||||
// The stub took: the gate-open copy lets an owner route through.
|
||||
assert.equal(userRoute('/api/bus/message', 'POST'), true);
|
||||
const env = await setup(t);
|
||||
// Positive control: the owner's session reaches the owner's send on this route.
|
||||
const ownerSession = await signIn(env, 'owner-sub');
|
||||
const sent = await go(env, ownerSession, ['POST', '/api/bus/message', { to: 'coder', body: 'hi' }]);
|
||||
assert.deepEqual(env.owner, [['option', 'send']], `the owner's send did not run: ${sent.status} ${sent.body}`);
|
||||
env.owner.length = 0;
|
||||
const session = await signIn(env, 'alice-sub');
|
||||
for (const route of ROUTES) {
|
||||
const r = await go(env, session, route);
|
||||
assert.doesNotMatch(r.body, /owner-only/, `${route[0]} ${route[1]}: the gate is still closed`);
|
||||
// Only the plugins read with {}, as granted-user.test.mjs G9 pins for the chat.
|
||||
for (const entry of env.owner) assert.deepEqual(entry, ['transport', 'plugins', {}], `${route[0]} ${route[1]}: ${JSON.stringify(entry)}`);
|
||||
}
|
||||
assert.ok(env.user.includes('message.send'), 'the message route never reached the user transport');
|
||||
assert.ok(env.opened.length > 0 && env.opened.every(name => name === 'alice'));
|
||||
});
|
||||
+30
-1
@@ -12,7 +12,22 @@ RELEASE_BACKUP="$(mktemp)"
|
||||
cp RELEASE "$RELEASE_BACKUP"
|
||||
# One exit trap: the repo RELEASE is ALWAYS restored from the backup,
|
||||
# regardless of how the test run ends.
|
||||
trap 'cp "$RELEASE_BACKUP" RELEASE 2>/dev/null; rm -rf "$SANDBOX" "$RELEASE_BACKUP"' EXIT
|
||||
# Compose names the project after the checkout directory unless told otherwise,
|
||||
# and `compose run --rm` leaves the project's <project>_default network behind.
|
||||
# Every run gets its own project, and the exit trap removes that one network
|
||||
# (row 305). It never runs `compose down` and never touches another network.
|
||||
COMPOSE_ID="$(basename "$SANDBOX")"
|
||||
COMPOSE_ID="$(printf '%s' "${COMPOSE_ID##*.}" | tr -cd '[:alnum:]' | tr '[:upper:]' '[:lower:]')"
|
||||
export COMPOSE_PROJECT_NAME="mosaic-test-release-$COMPOSE_ID"
|
||||
remove_compose_network() { # absent is fine; any other failure is one stderr line, never a status
|
||||
command -v docker >/dev/null 2>&1 || return 0
|
||||
local net="${COMPOSE_PROJECT_NAME}_default" err
|
||||
err="$(docker network rm "$net" 2>&1 >/dev/null)" && return 0
|
||||
case "$err" in *"not found"*|*"No such network"*) return 0 ;; esac
|
||||
echo "test-release: could not remove network $net: ${err%%$'\n'*}" >&2
|
||||
return 0
|
||||
}
|
||||
trap 'cp "$RELEASE_BACKUP" RELEASE 2>/dev/null; rm -rf "$SANDBOX" "$RELEASE_BACKUP"; remove_compose_network' EXIT
|
||||
# Compose mounts PI_AUTH_FILE. Point it at a fixture so no activation reaches
|
||||
# the host's pi credential (row 244). chmod after the write: umask-proof (row 243).
|
||||
{ mkdir -p "$SANDBOX/pi" && printf '{}' > "$SANDBOX/pi/auth.json" && chmod 600 "$SANDBOX/pi/auth.json"; } \
|
||||
@@ -108,6 +123,20 @@ else
|
||||
echo "skip state-machine cases (docker daemon unavailable)"
|
||||
fi
|
||||
|
||||
# The compose network goes with the run (row 305). Present before the remove
|
||||
# proves compose used this run's project name; absent after proves the trap's
|
||||
# cleanup removes it (mos-1445).
|
||||
if docker info >/dev/null 2>&1; then
|
||||
NET="${COMPOSE_PROJECT_NAME}_default"
|
||||
BEFORE="$(docker network ls -q --filter "name=^${NET}\$")" && [ -n "$BEFORE" ] \
|
||||
&& remove_compose_network \
|
||||
&& AFTER="$(docker network ls -q --filter "name=^${NET}\$")" && [ -z "$AFTER" ] \
|
||||
&& check "compose network made under the run's project and removed after the run" 0 \
|
||||
|| check "compose network made under the run's project and removed after the run" 1
|
||||
else
|
||||
echo "skip compose network check (docker daemon unavailable)"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "selftest: $PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
+30
-1
@@ -8,7 +8,22 @@ set -uo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
SANDBOX="$(mktemp -d)"
|
||||
trap 'rm -rf "$SANDBOX"' EXIT
|
||||
# Compose names the project after the checkout directory unless told otherwise,
|
||||
# and `compose run --rm` leaves the project's <project>_default network behind.
|
||||
# Every run gets its own project, and the exit trap removes that one network
|
||||
# (row 305). It never runs `compose down` and never touches another network.
|
||||
COMPOSE_ID="$(basename "$SANDBOX")"
|
||||
COMPOSE_ID="$(printf '%s' "${COMPOSE_ID##*.}" | tr -cd '[:alnum:]' | tr '[:upper:]' '[:lower:]')"
|
||||
export COMPOSE_PROJECT_NAME="mosaic-test-task-$COMPOSE_ID"
|
||||
remove_compose_network() { # absent is fine; any other failure is one stderr line, never a status
|
||||
command -v docker >/dev/null 2>&1 || return 0
|
||||
local net="${COMPOSE_PROJECT_NAME}_default" err
|
||||
err="$(docker network rm "$net" 2>&1 >/dev/null)" && return 0
|
||||
case "$err" in *"not found"*|*"No such network"*) return 0 ;; esac
|
||||
echo "test-task: could not remove network $net: ${err%%$'\n'*}" >&2
|
||||
return 0
|
||||
}
|
||||
trap 'rm -rf "$SANDBOX"; remove_compose_network' EXIT
|
||||
# Real-model cases need the operator's credential and a billed provider call,
|
||||
# so they run only on request (row 244, sage-2061). The gate lane never passes
|
||||
# MOSAIC_LIVE_PROVIDER through.
|
||||
@@ -558,6 +573,20 @@ fi
|
||||
git -C "$SANDBOX/repo" rev-parse >/dev/null 2>&1 || true
|
||||
unset MOSAIC_CONFIG
|
||||
|
||||
# The compose network goes with the run (row 305). Present before the remove
|
||||
# proves compose used this run's project name; absent after proves the trap's
|
||||
# cleanup removes it (mos-1445).
|
||||
if docker info >/dev/null 2>&1; then
|
||||
NET="${COMPOSE_PROJECT_NAME}_default"
|
||||
BEFORE="$(docker network ls -q --filter "name=^${NET}\$")" && [ -n "$BEFORE" ] \
|
||||
&& remove_compose_network \
|
||||
&& AFTER="$(docker network ls -q --filter "name=^${NET}\$")" && [ -z "$AFTER" ] \
|
||||
&& check "compose network made under the run's project and removed after the run" 0 \
|
||||
|| check "compose network made under the run's project and removed after the run" 1
|
||||
else
|
||||
echo "skip compose network check (docker daemon unavailable)"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "selftest: $PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
Reference in new issue
Block a user