researcher: row 71 round 1 packet on ac6b56ee, tasks 89/0, bus 115/0, mutants killed (#1565)

Haiku subagent build under decision 129. Candidate manifest 9ac3a56e
names packages/tasks/src/fake.mjs and packages/tasks/tests/tree.test.mjs.
Gate and both named mutants ran in Sage's slot.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 09:50:00 -05:00
co-authored by Claude Opus 5.5
parent ac6b56ee55
commit 471f5cf202
29 changed files with 3036 additions and 0 deletions
@@ -0,0 +1,83 @@
# Row 71 (#1565) build, round 1
Phase B done. Gate passed; both mutants killed. Nothing committed, queue row not moved, no Gitea or tracker writes.
## Identity
- Row 71: tree read follow-up, confirm-read tests and the fake's view 404.
- Brief: `docs/plans/2026-10-11_tree-read-follow-up.md` (not edited; blob 499c6cdc).
- Owner: researcher (queue owner; decisions 122 and 129). Reviewers: Dewey and Filbert. Sage runs the landing gate.
- Base: `ac6b56ee55278077d61f39e6ca42513725427154` (`base.txt`).
- Worktree: `.claude/worktrees/agent-a44468a48c485520e`, detached at the base, candidate uncommitted.
## Changes
`packages/tasks/src/fake.mjs`
- A missing kanban view answers 404 with code 3014, not 13001, in both `_buckets` and `_board`. The detail string is unchanged.
- The `deleteView` comment cites the live record `agents/sage/work/vikunja-setup/2026-10-11_tick-62.json` (`deletedViewProbe`).
`packages/tasks/tests/tree.test.mjs`
- Test 18 comment says 3014 and cites the same record.
- Three steps added after the existing "404 on the list, 503 on the project read" step. Each sets the child's task list to 404, then the confirm read to one of three answers. Each expects `tracker-not-found` and a refused tick with the child kept:
- confirm read 429 (Filbert N3, `r3-confirm-4xx`)
- confirm read 401 (Filbert N3)
- confirm read status 0, a failed call (Dewey, `r3-confirm-error-on-throw`)
`build.patch` covers these two paths only (64 lines, `git diff --binary` against the base). It applies cleanly to the base with `git apply --cached --check` on a temporary index.
## Rulings applied
1. Dewey's mutant is the status-0 form. Both mutants were defined from the brief; neither text exists in the repo. They are in `mutants.py`.
2. Owner: built as researcher. The brief names Darkwing as owner. The brief is not edited, and the mismatch is recorded here.
3. The fake keeps the existing detail string.
4. A view under another project: the fake returns 3014 for both cases. That case was never read live, and the fake does not separate it.
## Deviations and notes
- Rebase: the two edits were set aside as a tagged stash entry, checked out at the base, reapplied by SHA, and the entry was dropped by its ref. Other stash entries were not touched.
- Node suites run with `--test-reporter=tap` so the counts parse. They are otherwise the commands Sage named.
- Only `test-task.sh` gets `DOCKER_HOST=unix:///nonexistent.sock`. The node suites get it too, as ruled.
- Test 18 stops at its first failing assertion. The 401 step is not isolated by a named mutant. The 4xx mutant would also fail it, but the run stopped at the 429 step.
- The deleted-view case itself was not read live. The probe in tick-62 used a view id that no view has, as the brief notes.
- No baseline run against the pre-change tests. The claim that the two mutants survive the old tests is Filbert's and Dewey's, not reproduced here.
## Gate (steps 1 and 2)
Run by `gate.sh` from the worktree root, chained by `chain.sh`. Each child ran in its own session, under `run_group.py`, which kills the process group on timeout. No timeouts occurred. Manifest check at gate start: both files OK.
| step | command | result | UTC start-end |
| --- | --- | --- | --- |
| node tasks | `node --test packages/tasks/tests/*.test.mjs` | 89 tests, 89 pass, 0 fail, rc 0 | 14:46:36-14:46:37 |
| node bus | `node --test packages/bus/tests/*.test.mjs` | 115 tests, 115 pass, 0 fail, rc 0 | 14:46:37-14:46:38 |
| test-auth | `scripts/test-auth.sh` | selftest 15 passed, 0 failed | 14:46:38 |
| test-conductor | `scripts/test-conductor.sh` | selftest 17 passed, 0 failed | 14:46:38-14:46:44 |
| test-config | `scripts/test-config.sh` | selftest 24 passed, 0 failed | 14:46:44-14:46:46 |
| test-discord | `scripts/test-discord.sh` | discord suite 66 passed, 0 failed | 14:46:46-14:46:53 |
| test-extension-package | `scripts/test-extension-package.sh` | selftest 18 passed, 0 failed | 14:46:53-14:46:54 |
| test-foundation | `scripts/test-foundation.sh` | selftest 44 passed, 0 failed | 14:46:54-14:47:32 |
| test-queue | `scripts/test-queue.sh` | queue suite 27 passed, 0 failed | 14:47:32-14:47:52 |
| test-release | `scripts/test-release.sh` | selftest 14 passed, 0 failed | 14:47:52-14:48:02 |
| test-task | `scripts/test-task.sh` (DOCKER_HOST dead) | selftest 26 passed, 0 failed | 14:48:02-14:48:04 |
Gate PASS at 14:48:04 UTC. The script suites print their own pass lines, not TAP, so the summary holds only the exit status for them. The full logs are in `out/`.
## Mutants (steps 3, after gate PASS)
Each mutant was applied alone to `packages/tasks/src/sync.mjs`, then the tasks suite ran. The file was restored from bytes held in memory and checked after each restore.
| mutant | edit to sync.mjs | result | killing test | failing assertion |
| --- | --- | --- | --- | --- |
| `r3-confirm-4xx` | `return r.status >= 400 && r.status < 500;` | killed (rc 1; 89 run, 88 pass, 1 fail) | test 18, "a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only" | `tree.test.mjs:465`, the 429 confirm step |
| `r3-confirm-error-on-throw` | `return r.status === 403 \|\| r.status === 404 \|\| r.status === 0;` | killed (rc 1; 89 run, 88 pass, 1 fail) | same test | `tree.test.mjs:472`, the status-0 confirm step |
Mutant window: 14:48:04-14:48:06 UTC. After restore, `sync.mjs` sha256 is `35e79dc2ac56af8047bef11a5aaf5f1d37ce3e11513f9968454053068f59ebcf`, the original, and `git diff` shows no change to it.
## Files in this packet
- `base.txt`, `build.patch`, `files.txt`, `candidate-manifest.sha256`
- `run_group.py` (process-group runner), `gate.sh` (steps 1 and 2), `chain.sh` (gate, then mutants on pass), `mutants.py` (steps 3)
- `out/`: `gate-summary.txt`, `gate-stdout.txt`, `manifest-check.txt`, `node-tasks.log`, `node-bus.log`, `test-*.log`, `mutant-*.log`, `mutants-summary.txt`, `mutants-stdout.txt`, `chain-start.txt`, `chain-rc.txt`
## Process check
No test, node or chromium process of mine remains. Checked at 14:48 UTC by scanning `/proc` cwd links inside this worktree. The one leftover was my own `tail -F` monitor, stopped.
@@ -0,0 +1 @@
ac6b56ee55278077d61f39e6ca42513725427154
@@ -0,0 +1,64 @@
diff --git a/packages/tasks/src/fake.mjs b/packages/tasks/src/fake.mjs
index 633224db8..57314be46 100644
--- a/packages/tasks/src/fake.mjs
+++ b/packages/tasks/src/fake.mjs
@@ -138,7 +138,8 @@ export class FakeVikunja {
for (const id of gone) this.#projects.delete(id);
}
// Drops a view, its buckets and the tasks' places in them. The project still reads, and a read
- // of the view answers 404 with code 13001.
+ // of the view answers 404 with code 3014, as tasks.woltje.com v2.7.0 does (Sage's live probe,
+ // agents/sage/work/vikunja-setup/2026-10-11_tick-62.json, deletedViewProbe).
deleteView(view) {
for (const [id, b] of this.#buckets) if (b.view === view) this.#buckets.delete(id);
for (const t of this.#tasks.values()) t.buckets.delete(view);
@@ -473,14 +474,14 @@ export class FakeVikunja {
_buckets(user, [p, k], q) {
const r = this.#projectFor(user, p);
if (r.error) return r.error;
- if (this.#views.get(k)?.project !== p) return { status: 404, body: { title: 'Not Found', status: 404, detail: 'This project view does not exist.', code: 13001 } };
+ if (this.#views.get(k)?.project !== p) return { status: 404, body: { title: 'Not Found', status: 404, detail: 'This project view does not exist.', code: 3014 } };
return { status: 200, body: page([...this.#buckets.values()].filter((b) => b.view === k).map((b) => this.#bucketJson(b)), q) };
}
_board(user, [p, k], q) {
const r = this.#projectFor(user, p);
if (r.error) return r.error;
const v = this.#views.get(k);
- if (v?.project !== p) return { status: 404, body: { title: 'Not Found', status: 404, detail: 'This project view does not exist.', code: 13001 } };
+ if (v?.project !== p) return { status: 404, body: { title: 'Not Found', status: 404, detail: 'This project view does not exist.', code: 3014 } };
const f = q.get('filter') ?? '';
if (f && f !== 'done = false') return { status: 400, body: bad('unsupported filter in the fake') };
const per = Math.min(Number(q.get('per_page')) || 50, 50),
diff --git a/packages/tasks/tests/tree.test.mjs b/packages/tasks/tests/tree.test.mjs
index 5ac99ae51..e325be398 100644
--- a/packages/tasks/tests/tree.test.mjs
+++ b/packages/tasks/tests/tree.test.mjs
@@ -430,8 +430,8 @@ test('a child whose kanban view is deleted still refuses the tick, and the recon
const rootTask = await add(w, w.project, 'root');
await ready(w);
const rows = () => w.store.get('SELECT (SELECT count(*) FROM events) + (SELECT count(*) FROM task_snapshots) n').n;
- // The board answers 404 with code 13001, and the project still reads, so the child hasn't left
- // the tree. The tick reads the project, fails, and writes nothing, not even the root's edit.
+ // The board answers 404 with code 3014 (the live v2.7.0 answer, tick-62 record), and the project
+ // still reads, so the child hasn't left the tree. The tick reads the project, fails, and writes nothing, not even the root's edit.
w.fake.deleteView(w.fake.kanban(child).id);
await w.ui('PATCH', `/tasks/${rootTask}`, { title: 'root renamed' });
await sleep(20);
@@ -459,6 +459,17 @@ test('a child whose kanban view is deleted still refuses the tick, and the recon
w.fake.fault('GET', new RegExp(`^/projects/${child}/tasks$`), 404);
w.fake.fault('GET', new RegExp(`^/projects/${child}$`), 503);
await assert.rejects(w.adapter.tick('demo'), { code: 'tracker-not-found' });
+ // The confirm read answers another 4xx: the tick still refuses, and the child stays.
+ w.fake.fault('GET', new RegExp(`^/projects/${child}/tasks$`), 404);
+ w.fake.fault('GET', new RegExp(`^/projects/${child}$`), 429);
+ await assert.rejects(w.adapter.tick('demo'), { code: 'tracker-not-found' });
+ w.fake.fault('GET', new RegExp(`^/projects/${child}/tasks$`), 404);
+ w.fake.fault('GET', new RegExp(`^/projects/${child}$`), 401);
+ await assert.rejects(w.adapter.tick('demo'), { code: 'tracker-not-found' });
+ // The confirm read's call fails (status 0, which the client returns for a thrown fetch): the tick refuses.
+ w.fake.fault('GET', new RegExp(`^/projects/${child}/tasks$`), 404);
+ w.fake.fault('GET', new RegExp(`^/projects/${child}$`), 0);
+ await assert.rejects(w.adapter.tick('demo'), { code: 'tracker-not-found' });
await w.ui('PATCH', `/tasks/${task}`, { title: 'child renamed' });
await sleep(20);
await w.adapter.tick('demo');
@@ -0,0 +1,2 @@
feb4a6f8927471ce445082d5a28e0e29377b000aabec97ea14378dafe88ec065 packages/tasks/src/fake.mjs
bc081ac487671bfb79c9afbc5bb9788560d1643f1975fa92bb31865022b2cba9 packages/tasks/tests/tree.test.mjs
@@ -0,0 +1,12 @@
#!/bin/bash
# Row 71 round 1 chain: the gate (steps 1 and 2), then the mutants only if the gate exits 0.
# Run from the worktree root.
P=agents/researcher/work/queue-71/r1
mkdir -p "$P/out"
date -u > "$P/out/chain-start.txt"
bash "$P/gate.sh" > "$P/out/gate-stdout.txt" 2>&1 \
&& python3 "$P/mutants.py" > "$P/out/mutants-stdout.txt" 2>&1
rc=$?
echo "chain rc=$rc" > "$P/out/chain-rc.txt"
date -u >> "$P/out/chain-rc.txt"
exit $rc
@@ -0,0 +1,2 @@
packages/tasks/src/fake.mjs
packages/tasks/tests/tree.test.mjs
@@ -0,0 +1,45 @@
#!/bin/bash
# Row 71 round 1 gate, run from the worktree root (base ac6b56ee5 plus build.patch).
# Steps chain with && and stop at the first failure. Each child runs through run_group.py,
# which kills its whole process group on timeout.
P=agents/researcher/work/queue-71/r1
OUT=$P/out
RUN="python3 $P/run_group.py"
S=$OUT/gate-summary.txt
mkdir -p "$OUT"
: > "$S"
stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; }
note() { echo "$*" >> "$S"; }
# step NAME TIMEOUT_S LOGNAME -- CMD...
step() {
local name=$1 t=$2 log=$OUT/$3 rc t0
shift 3
shift # the --
t0=$(stamp)
$RUN "$t" "$log" "$PWD" -- "$@"
rc=$?
note "$name rc=$rc start=$t0 end=$(stamp) $(grep -E '^# (tests|pass|fail|cancelled|skipped|todo) ' "$log" | tr -s ' ' | tr '\n' ' ')"
[ "$rc" -eq 0 ] || note "$name FAILED; last line: $(grep -v '^\s*$' "$log" | tail -1 | cut -c1-200)"
return "$rc"
}
note "gate start $(stamp) base $(git rev-parse HEAD)"
if sha256sum -c "$P/candidate-manifest.sha256" > "$OUT/manifest-check.txt" 2>&1 \
&& step node-tasks 900 node-tasks.log -- env DOCKER_HOST=unix:///nonexistent.sock node --test --test-reporter=tap 'packages/tasks/tests/*.test.mjs' \
&& step node-bus 900 node-bus.log -- env DOCKER_HOST=unix:///nonexistent.sock node --test --test-reporter=tap 'packages/bus/tests/*.test.mjs' \
&& step test-auth 1200 test-auth.log -- env -u DOCKER_HOST bash scripts/test-auth.sh \
&& step test-conductor 1200 test-conductor.log -- env -u DOCKER_HOST bash scripts/test-conductor.sh \
&& step test-config 1200 test-config.log -- env -u DOCKER_HOST bash scripts/test-config.sh \
&& step test-discord 1200 test-discord.log -- env -u DOCKER_HOST bash scripts/test-discord.sh \
&& step test-extension-package 1200 test-extension-package.log -- env -u DOCKER_HOST bash scripts/test-extension-package.sh \
&& step test-foundation 1200 test-foundation.log -- env -u DOCKER_HOST bash scripts/test-foundation.sh \
&& step test-queue 1200 test-queue.log -- env -u DOCKER_HOST bash scripts/test-queue.sh \
&& step test-release 1200 test-release.log -- env -u DOCKER_HOST bash scripts/test-release.sh \
&& step test-task 1200 test-task.log -- env DOCKER_HOST=unix:///nonexistent.sock bash scripts/test-task.sh
then
note "GATE PASS $(stamp)"
exit 0
fi
note "GATE STOPPED $(stamp)"
exit 1
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""Row 71 round 1 mutants, run from the worktree root after gate.sh passes.
Each mutant is one edit to packages/tasks/src/sync.mjs, applied alone, followed by
the tasks suite. The original bytes are held in memory and written back in a
finally block, and the sha256 is checked after the last restore.
A mutant is killed when the suite exits nonzero. A 124 exit is a timeout and is
reported as such, not as a kill.
"""
import datetime
import hashlib
import os
import re
import subprocess
import sys
SYNC = 'packages/tasks/src/sync.mjs'
P = 'agents/researcher/work/queue-71/r1'
OUT = P + '/out'
ORIG_SHA = '35e79dc2ac56af8047bef11a5aaf5f1d37ce3e11513f9968454053068f59ebcf'
LINE = ' return r.status === 403 || r.status === 404;'
MUTANTS = [
# Filbert N3: the confirm read treats any 4xx as "left".
('r3-confirm-4xx', LINE, ' return r.status >= 400 && r.status < 500;'),
# Dewey: the confirm read's failed call (status 0) counts as "left".
('r3-confirm-error-on-throw', LINE, ' return r.status === 403 || r.status === 404 || r.status === 0;'),
]
def stamp():
return datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
def sha(path):
with open(path, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
def write(path, data):
with open(path, 'wb') as f:
f.write(data)
def run_suite(name):
log = f'{OUT}/mutant-{name}.log'
cmd = ['env', 'DOCKER_HOST=unix:///nonexistent.sock', 'node', '--test', '--test-reporter=tap', 'packages/tasks/tests/*.test.mjs']
rc = subprocess.run(['python3', P + '/run_group.py', '900', log, os.getcwd(), '--'] + cmd).returncode
with open(log, encoding='utf-8', errors='replace') as f:
text = f.read()
failing = []
for m in re.finditer(r'^\s*not ok \d+ - (.+)$', text, re.M):
name_ = m.group(1).strip()
if name_ not in failing:
failing.append(name_)
counts = ' '.join(re.findall(r'^# (?:tests|pass|fail) \d+', text, re.M))
return rc, failing, counts
def main():
if not os.path.isfile(SYNC):
sys.exit('run from the worktree root')
os.makedirs(OUT, exist_ok=True)
original = open(SYNC, 'rb').read()
if hashlib.sha256(original).hexdigest() != ORIG_SHA:
sys.exit('sync.mjs is not the candidate copy; refusing to mutate it')
text = original.decode('utf-8')
summary = []
try:
for name, old, new in MUTANTS:
if text.count(old + '\n') != 1:
sys.exit(f'{name}: target line must occur exactly once')
mutated = text.replace(old + '\n', new + '\n').encode('utf-8')
write(SYNC, mutated)
t0 = stamp()
rc, failing, counts = run_suite(name)
t1 = stamp()
write(SYNC, original)
if sha(SYNC) != ORIG_SHA:
sys.exit(f'{name}: restore did not reproduce the original sha256')
status = 'killed' if rc not in (0, 124) else ('timeout' if rc == 124 else 'SURVIVED')
summary.append(f'{name} {status} rc={rc} start={t0} end={t1} {counts}')
for n in failing:
summary.append(f' not ok: {n}')
finally:
write(SYNC, original)
final = sha(SYNC)
summary.append(f'restored {SYNC} sha256 {final} {"OK" if final == ORIG_SHA else "MISMATCH"}')
with open(OUT + '/mutants-summary.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(summary) + '\n')
print('\n'.join(summary))
sys.exit(0 if final == ORIG_SHA else 1)
if __name__ == '__main__':
main()
@@ -0,0 +1,2 @@
chain rc=0
Tue Oct 13 02:48:06 PM UTC 2026
@@ -0,0 +1 @@
Tue Oct 13 02:46:36 PM UTC 2026
@@ -0,0 +1,13 @@
gate start 2026-10-13T14:46:36Z base ac6b56ee55278077d61f39e6ca42513725427154
node-tasks rc=0 start=2026-10-13T14:46:36Z end=2026-10-13T14:46:37Z # tests 89 # pass 89 # fail 0 # cancelled 0 # skipped 0 # todo 0
node-bus rc=0 start=2026-10-13T14:46:37Z end=2026-10-13T14:46:38Z # tests 115 # pass 115 # fail 0 # cancelled 0 # skipped 0 # todo 0
test-auth rc=0 start=2026-10-13T14:46:38Z end=2026-10-13T14:46:38Z
test-conductor rc=0 start=2026-10-13T14:46:38Z end=2026-10-13T14:46:44Z
test-config rc=0 start=2026-10-13T14:46:44Z end=2026-10-13T14:46:46Z
test-discord rc=0 start=2026-10-13T14:46:46Z end=2026-10-13T14:46:53Z
test-extension-package rc=0 start=2026-10-13T14:46:53Z end=2026-10-13T14:46:54Z
test-foundation rc=0 start=2026-10-13T14:46:54Z end=2026-10-13T14:47:32Z
test-queue rc=0 start=2026-10-13T14:47:32Z end=2026-10-13T14:47:52Z
test-release rc=0 start=2026-10-13T14:47:52Z end=2026-10-13T14:48:02Z
test-task rc=0 start=2026-10-13T14:48:02Z end=2026-10-13T14:48:04Z
GATE PASS 2026-10-13T14:48:04Z
@@ -0,0 +1,2 @@
packages/tasks/src/fake.mjs: OK
packages/tasks/tests/tree.test.mjs: OK
@@ -0,0 +1,556 @@
TAP version 13
# Subtest: the boot config is checked before anything starts
ok 1 - the boot config is checked before anything starts
---
duration_ms: 14.985128
type: 'test'
...
# Subtest: a business with no tracker entry refuses task verbs
ok 2 - a business with no tracker entry refuses task verbs
---
duration_ms: 14.714455
type: 'test'
...
# Subtest: credential.expiring and .expired are recorded once per instance
ok 3 - credential.expiring and .expired are recorded once per instance
---
duration_ms: 27.882089
type: 'test'
...
# Subtest: a token file that changes on disk records credential.changed
ok 4 - a token file that changes on disk records credential.changed
---
duration_ms: 13.348847
type: 'test'
...
# Subtest: autostart polls, reconciles and retries a startup the tracker was down for
ok 5 - autostart polls, reconciles and retries a startup the tracker was down for
---
duration_ms: 36.23427
type: 'test'
...
# Subtest: a refusal a restart must clear is not retried by the poll
ok 6 - a refusal a restart must clear is not retried by the poll
---
duration_ms: 10.973461
type: 'test'
...
# Subtest: a poll that fires while two are queued is dropped
ok 7 - a poll that fires while two are queued is dropped
---
duration_ms: 14.054849
type: 'test'
...
# Subtest: close waits for a running verb and refuses one that has not started
ok 8 - close waits for a running verb and refuses one that has not started
---
duration_ms: 44.044153
type: 'test'
...
# Subtest: the bundled Vikunja is the pinned upstream image the runbook names
ok 9 - the bundled Vikunja is the pinned upstream image the runbook names
---
duration_ms: 0.711278
type: 'test'
...
# Subtest: every published port is on 127.0.0.1, and no secret is in the file
ok 10 - every published port is on 127.0.0.1, and no secret is in the file
---
duration_ms: 0.258663
type: 'test'
...
# Subtest: the committed table loads frozen; its verbs are the broker task verbs
ok 11 - the committed table loads frozen; its verbs are the broker task verbs
---
duration_ms: 1.669028
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 12 - the schema refuses any other shape
---
duration_ms: 3.318884
type: 'test'
...
# Subtest: each verb refuses, asks for a decision and writes as the table and the role files say
ok 13 - each verb refuses, asks for a decision and writes as the table and the role files say
---
duration_ms: 155.091502
type: 'test'
...
# Subtest: the list holds the PRD's requirement ids, in its order, at its version
ok 14 - the list holds the PRD's requirement ids, in its order, at its version
---
duration_ms: 5.451833
type: 'test'
...
# Subtest: the committed list loads frozen
ok 15 - the committed list loads frozen
---
duration_ms: 0.657564
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 16 - the schema refuses any other shape
---
duration_ms: 1.923796
type: 'test'
...
# Subtest: the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
ok 17 - the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
---
duration_ms: 91.483598
type: 'test'
...
# Subtest: the project list holds recorded project objects in the recorded list envelope
ok 18 - the project list holds recorded project objects in the recorded list envelope
---
duration_ms: 9.898596
type: 'test'
...
# Subtest: the recorded task bodies pass the checks S3 applies to every read
ok 19 - the recorded task bodies pass the checks S3 applies to every read
---
duration_ms: 0.43417
type: 'test'
...
# Subtest: the client works against the fake over real HTTP with the platform fetch
ok 20 - the client works against the fake over real HTTP with the platform fetch
---
duration_ms: 99.305719
type: 'test'
...
# Subtest: a correct install starts, and the first reconcile records tasks that already exist
ok 21 - a correct install starts, and the first reconcile records tasks that already exist
---
duration_ms: 26.885137
type: 'test'
...
# Subtest: verbs refuse while a business is starting and after startup refused it
ok 22 - verbs refuse while a business is starting and after startup refused it
---
duration_ms: 15.866064
type: 'test'
...
# Subtest: startup refuses a token that can do more than its role needs
ok 23 - startup refuses a token that can do more than its role needs
---
duration_ms: 39.459007
type: 'test'
...
# Subtest: startup refuses an unsupported version and flags an untested one
ok 24 - startup refuses an unsupported version and flags an untested one
---
duration_ms: 29.725668
type: 'test'
...
# Subtest: startup refuses a board that the runbook did not install
ok 25 - startup refuses a board that the runbook did not install
---
duration_ms: 40.235276
type: 'test'
...
# Subtest: startup refuses a project the sync bot cannot read
ok 26 - startup refuses a project the sync bot cannot read
---
duration_ms: 8.170918
type: 'test'
...
# Subtest: startup refuses a configured label the pm bot cannot see
ok 27 - startup refuses a configured label the pm bot cannot see
---
duration_ms: 9.844785
type: 'test'
...
# Subtest: startup refuses an expired credential and a missing sync credential
ok 28 - startup refuses an expired credential and a missing sync credential
---
duration_ms: 16.9923
type: 'test'
...
# Subtest: an unreachable tracker refuses with tracker-unavailable
ok 29 - an unreachable tracker refuses with tracker-unavailable
---
duration_ms: 6.645521
type: 'test'
...
# Subtest: an edit in the UI is recorded once, with the fields that changed
ok 30 - an edit in the UI is recorded once, with the fields that changed
---
duration_ms: 77.08308
type: 'test'
...
# Subtest: a move between open buckets is seen on the board, though updated does not change
ok 31 - a move between open buckets is seen on the board, though updated does not change
---
duration_ms: 39.81042
type: 'test'
...
# Subtest: a person's comment is counted and a bot's is not
ok 32 - a person's comment is counted and a bot's is not
---
duration_ms: 73.111456
type: 'test'
...
# Subtest: the hourly reconcile catches a comment through comment_count
ok 33 - the hourly reconcile catches a comment through comment_count
---
duration_ms: 76.173236
type: 'test'
...
# Subtest: a task closed in the UI leaves the open view with its done bucket
ok 34 - a task closed in the UI leaves the open view with its done bucket
---
duration_ms: 113.942375
type: 'test'
...
# Subtest: a task that leaves the board is recorded as deleted, moved or out of reach
ok 35 - a task that leaves the board is recorded as deleted, moved or out of reach
---
duration_ms: 64.372593
type: 'test'
...
# Subtest: a poll that read before a verb wrote does not overwrite the verb
ok 36 - a poll that read before a verb wrote does not overwrite the verb
---
duration_ms: 35.608068
type: 'test'
...
# Subtest: a tracker fault during a tick is reported and the next tick catches up
ok 37 - a tracker fault during a tick is reported and the next tick catches up
---
duration_ms: 35.704917
type: 'test'
...
# Subtest: a malformed answer refuses the tick with tracker-shape
ok 38 - a malformed answer refuses the tick with tracker-shape
---
duration_ms: 13.652804
type: 'test'
...
# Subtest: no token value reaches the database, the log or a refusal
ok 39 - no token value reaches the database, the log or a refusal
---
duration_ms: 43.73452
type: 'test'
...
# Subtest: the first look at a task counts only comments inside the window
ok 40 - the first look at a task counts only comments inside the window
---
duration_ms: 33.293957
type: 'test'
...
# Subtest: with descendants off the adapter reads no project list and no child, as in v0
ok 41 - with descendants off the adapter reads no project list and no child, as in v0
---
duration_ms: 46.419107
type: 'test'
...
# Subtest: a three-level tree is read per project, and a project outside it is not
ok 42 - a three-level tree is read per project, and a project outside it is not
---
duration_ms: 19.063862
type: 'test'
...
# Subtest: a watch-only child keeps the business ready, and a failed child read refuses as transient
ok 43 - a watch-only child keeps the business ready, and a failed child read refuses as transient
---
duration_ms: 24.274217
type: 'test'
...
# Subtest: a root without the installed buckets refuses with descendants on
ok 44 - a root without the installed buckets refuses with descendants on
---
duration_ms: 10.156206
type: 'test'
...
# Subtest: the project list refuses without read_all, and skips archived projects and saved filters
ok 45 - the project list refuses without read_all, and skips archived projects and saved filters
---
duration_ms: 22.653056
type: 'test'
...
# Subtest: descendants must be true or false
ok 46 - descendants must be true or false
---
duration_ms: 11.059931
type: 'test'
...
# Subtest: a move inside the tree is a moved tombstone plus a snapshot under the new ref
ok 47 - a move inside the tree is a moved tombstone plus a snapshot under the new ref
---
duration_ms: 65.339785
type: 'test'
...
# Subtest: a child made after startup joins the tree at the next reconcile
ok 48 - a child made after startup joins the tree at the next reconcile
---
duration_ms: 52.570713
type: 'test'
...
# Subtest: a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
ok 49 - a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
---
duration_ms: 58.458871
type: 'test'
...
# Subtest: a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
ok 50 - a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
---
duration_ms: 82.229086
type: 'test'
...
# Subtest: a reconcile that fails keeps the previous tree
ok 51 - a reconcile that fails keeps the previous tree
---
duration_ms: 32.227599
type: 'test'
...
# Subtest: a closed task the cursor missed takes its own project's done bucket
ok 52 - a closed task the cursor missed takes its own project's done bucket
---
duration_ms: 32.350006
type: 'test'
...
# Subtest: closed tasks read at startup take their own project's done bucket
ok 53 - closed tasks read at startup take their own project's done bucket
---
duration_ms: 8.718222
type: 'test'
...
# Subtest: a closed task the cursor returns takes its own project's done bucket
ok 54 - a closed task the cursor returns takes its own project's done bucket
---
duration_ms: 32.245047
type: 'test'
...
# Subtest: a task moved out of a child that leaves the tree at the same time is moved, not no-access
ok 55 - a task moved out of a child that leaves the tree at the same time is moved, not no-access
---
duration_ms: 31.487855
type: 'test'
...
# Subtest: a task in a bucket outside the five keeps its raw bucket id
ok 56 - a task in a bucket outside the five keeps its raw bucket id
---
duration_ms: 30.317739
type: 'test'
...
# Subtest: bucket 0 on a watch-only task never becomes a bucket or a state
ok 57 - bucket 0 on a watch-only task never becomes a bucket or a state
---
duration_ms: 76.762699
type: 'test'
...
# Subtest: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
not ok 58 - a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
---
duration_ms: 34.653246
type: 'test'
location: '/mnt/storage/src/mosaic-stack/.claude/worktrees/agent-a44468a48c485520e/packages/tasks/tests/tree.test.mjs:425:1'
failureType: 'testCodeFailure'
error: 'Missing expected rejection.'
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected:
code: 'tracker-not-found'
operator: 'rejects'
stack: |-
async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack/.claude/worktrees/agent-a44468a48c485520e/packages/tasks/tests/tree.test.mjs:465:3)
async Test.run (node:internal/test_runner/test:1409:7)
async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
...
# Subtest: a child dropped at a tick comes back at the next reconcile once the bot reads it again
ok 59 - a child dropped at a tick comes back at the next reconcile once the bot reads it again
---
duration_ms: 39.468458
type: 'test'
...
# Subtest: task.create needs a recorded human request and a requirement id
ok 60 - task.create needs a recorded human request and a requirement id
---
duration_ms: 37.76007
type: 'test'
...
# Subtest: task.create takes only an approved requirement id
ok 61 - task.create takes only an approved requirement id
---
duration_ms: 24.103231
type: 'test'
...
# Subtest: task.create cites the request a received message carries, not the message's id
ok 62 - task.create cites the request a received message carries, not the message's id
---
duration_ms: 19.530799
type: 'test'
...
# Subtest: only labels named in the business file can be written
ok 63 - only labels named in the business file can be written
---
duration_ms: 25.956217
type: 'test'
...
# Subtest: task.schedule sets and clears a due date and relations
ok 64 - task.schedule sets and clears a due date and relations
---
duration_ms: 38.314616
type: 'test'
...
# Subtest: assign and reassign move the role bots and record task.assigned
ok 65 - assign and reassign move the role bots and record task.assigned
---
duration_ms: 55.376954
type: 'test'
...
# Subtest: task.update.assigned is for the assignee and records task.state
ok 66 - task.update.assigned is for the assignee and records task.state
---
duration_ms: 43.392796
type: 'test'
...
# Subtest: a wrong expected digest records task.conflict and writes nothing
ok 67 - a wrong expected digest records task.conflict and writes nothing
---
duration_ms: 19.114486
type: 'test'
...
# Subtest: a cross-role verb needs a resolved decision, used once
ok 68 - a cross-role verb needs a resolved decision, used once
---
duration_ms: 20.735188
type: 'test'
...
# Subtest: task.close needs a verdict; after it every verb refuses with task-done
ok 69 - task.close needs a verdict; after it every verb refuses with task-done
---
duration_ms: 21.0694
type: 'test'
...
# Subtest: a lost answer is settled by a re-read and never retried
ok 70 - a lost answer is settled by a re-read and never retried
---
duration_ms: 25.470917
type: 'test'
...
# Subtest: a create whose answer is lost is reported uncertain, and the poll finds the task
ok 71 - a create whose answer is lost is reported uncertain, and the poll finds the task
---
duration_ms: 34.598261
type: 'test'
...
# Subtest: a task the sync bot cannot read refuses and records nothing
ok 72 - a task the sync bot cannot read refuses and records nothing
---
duration_ms: 17.107712
type: 'test'
...
# Subtest: verbs and polls for one business run one at a time
ok 73 - verbs and polls for one business run one at a time
---
duration_ms: 87.088201
type: 'test'
...
# Subtest: a due date with milliseconds is written to the second
ok 74 - a due date with milliseconds is written to the second
---
duration_ms: 62.660034
type: 'test'
...
# Subtest: every write landed and the final read failed: the verb succeeds and records what it wrote
ok 75 - every write landed and the final read failed: the verb succeeds and records what it wrote
---
duration_ms: 35.866185
type: 'test'
...
# Subtest: some writes landed and the final read failed: write-uncertain, and nothing is recorded
ok 76 - some writes landed and the final read failed: write-uncertain, and nothing is recorded
---
duration_ms: 13.780501
type: 'test'
...
# Subtest: a create whose final read fails succeeds and records task.created
ok 77 - a create whose final read fails succeeds and records task.created
---
duration_ms: 31.439164
type: 'test'
...
# Subtest: an edit between the last write and the final read shows as external on the next poll
ok 78 - an edit between the last write and the final read shows as external on the next poll
---
duration_ms: 34.514959
type: 'test'
...
# Subtest: task.created is recorded when a later label write fails
ok 79 - task.created is recorded when a later label write fails
---
duration_ms: 15.127095
type: 'test'
...
# Subtest: every verb acts in an installed child, on the child's own board
ok 80 - every verb acts in an installed child, on the child's own board
---
duration_ms: 54.093416
type: 'test'
...
# Subtest: task.create refuses a project outside the tree, a watch-only one and one that is not an id
ok 81 - task.create refuses a project outside the tree, a watch-only one and one that is not an id
---
duration_ms: 28.174679
type: 'test'
...
# Subtest: with descendants off, task.create takes only the root project
ok 82 - with descendants off, task.create takes only the root project
---
duration_ms: 14.206089
type: 'test'
...
# Subtest: a verb on a watch-only task, or a relation to one, refuses with project-not-installed
ok 83 - a verb on a watch-only task, or a relation to one, refuses with project-not-installed
---
duration_ms: 19.361082
type: 'test'
...
# Subtest: a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
ok 84 - a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
---
duration_ms: 24.895956
type: 'test'
...
# Subtest: a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
ok 85 - a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
---
duration_ms: 17.406278
type: 'test'
...
# Subtest: a verb and a create in the child record the final read of the child's board
ok 86 - a verb and a create in the child record the final read of the child's board
---
duration_ms: 15.833158
type: 'test'
...
# Subtest: a create in the child whose final read fails records the child's todo bucket
ok 87 - a create in the child whose final read fails records the child's todo bucket
---
duration_ms: 35.839631
type: 'test'
...
# Subtest: a lost answer in the child is settled by a re-read of the child's board
ok 88 - a lost answer in the child is settled by a re-read of the child's board
---
duration_ms: 23.642965
type: 'test'
...
# Subtest: every related task is read before authority, not only the first
ok 89 - every related task is read before authority, not only the first
---
duration_ms: 18.46152
type: 'test'
...
1..89
# tests 89
# suites 0
# pass 88
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 1018.079754
@@ -0,0 +1,556 @@
TAP version 13
# Subtest: the boot config is checked before anything starts
ok 1 - the boot config is checked before anything starts
---
duration_ms: 30.211993
type: 'test'
...
# Subtest: a business with no tracker entry refuses task verbs
ok 2 - a business with no tracker entry refuses task verbs
---
duration_ms: 13.221941
type: 'test'
...
# Subtest: credential.expiring and .expired are recorded once per instance
ok 3 - credential.expiring and .expired are recorded once per instance
---
duration_ms: 30.026771
type: 'test'
...
# Subtest: a token file that changes on disk records credential.changed
ok 4 - a token file that changes on disk records credential.changed
---
duration_ms: 13.716724
type: 'test'
...
# Subtest: autostart polls, reconciles and retries a startup the tracker was down for
ok 5 - autostart polls, reconciles and retries a startup the tracker was down for
---
duration_ms: 37.157349
type: 'test'
...
# Subtest: a refusal a restart must clear is not retried by the poll
ok 6 - a refusal a restart must clear is not retried by the poll
---
duration_ms: 12.484131
type: 'test'
...
# Subtest: a poll that fires while two are queued is dropped
ok 7 - a poll that fires while two are queued is dropped
---
duration_ms: 14.564878
type: 'test'
...
# Subtest: close waits for a running verb and refuses one that has not started
ok 8 - close waits for a running verb and refuses one that has not started
---
duration_ms: 43.010075
type: 'test'
...
# Subtest: the bundled Vikunja is the pinned upstream image the runbook names
ok 9 - the bundled Vikunja is the pinned upstream image the runbook names
---
duration_ms: 0.782649
type: 'test'
...
# Subtest: every published port is on 127.0.0.1, and no secret is in the file
ok 10 - every published port is on 127.0.0.1, and no secret is in the file
---
duration_ms: 0.284211
type: 'test'
...
# Subtest: the committed table loads frozen; its verbs are the broker task verbs
ok 11 - the committed table loads frozen; its verbs are the broker task verbs
---
duration_ms: 1.550886
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 12 - the schema refuses any other shape
---
duration_ms: 3.798377
type: 'test'
...
# Subtest: each verb refuses, asks for a decision and writes as the table and the role files say
ok 13 - each verb refuses, asks for a decision and writes as the table and the role files say
---
duration_ms: 161.456593
type: 'test'
...
# Subtest: the list holds the PRD's requirement ids, in its order, at its version
ok 14 - the list holds the PRD's requirement ids, in its order, at its version
---
duration_ms: 5.001933
type: 'test'
...
# Subtest: the committed list loads frozen
ok 15 - the committed list loads frozen
---
duration_ms: 0.513652
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 16 - the schema refuses any other shape
---
duration_ms: 2.118521
type: 'test'
...
# Subtest: the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
ok 17 - the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
---
duration_ms: 100.558772
type: 'test'
...
# Subtest: the project list holds recorded project objects in the recorded list envelope
ok 18 - the project list holds recorded project objects in the recorded list envelope
---
duration_ms: 9.625038
type: 'test'
...
# Subtest: the recorded task bodies pass the checks S3 applies to every read
ok 19 - the recorded task bodies pass the checks S3 applies to every read
---
duration_ms: 0.510864
type: 'test'
...
# Subtest: the client works against the fake over real HTTP with the platform fetch
ok 20 - the client works against the fake over real HTTP with the platform fetch
---
duration_ms: 99.450496
type: 'test'
...
# Subtest: a correct install starts, and the first reconcile records tasks that already exist
ok 21 - a correct install starts, and the first reconcile records tasks that already exist
---
duration_ms: 35.875385
type: 'test'
...
# Subtest: verbs refuse while a business is starting and after startup refused it
ok 22 - verbs refuse while a business is starting and after startup refused it
---
duration_ms: 15.070202
type: 'test'
...
# Subtest: startup refuses a token that can do more than its role needs
ok 23 - startup refuses a token that can do more than its role needs
---
duration_ms: 44.434924
type: 'test'
...
# Subtest: startup refuses an unsupported version and flags an untested one
ok 24 - startup refuses an unsupported version and flags an untested one
---
duration_ms: 30.974458
type: 'test'
...
# Subtest: startup refuses a board that the runbook did not install
ok 25 - startup refuses a board that the runbook did not install
---
duration_ms: 39.732346
type: 'test'
...
# Subtest: startup refuses a project the sync bot cannot read
ok 26 - startup refuses a project the sync bot cannot read
---
duration_ms: 6.867169
type: 'test'
...
# Subtest: startup refuses a configured label the pm bot cannot see
ok 27 - startup refuses a configured label the pm bot cannot see
---
duration_ms: 8.904923
type: 'test'
...
# Subtest: startup refuses an expired credential and a missing sync credential
ok 28 - startup refuses an expired credential and a missing sync credential
---
duration_ms: 13.255291
type: 'test'
...
# Subtest: an unreachable tracker refuses with tracker-unavailable
ok 29 - an unreachable tracker refuses with tracker-unavailable
---
duration_ms: 6.283231
type: 'test'
...
# Subtest: an edit in the UI is recorded once, with the fields that changed
ok 30 - an edit in the UI is recorded once, with the fields that changed
---
duration_ms: 79.358718
type: 'test'
...
# Subtest: a move between open buckets is seen on the board, though updated does not change
ok 31 - a move between open buckets is seen on the board, though updated does not change
---
duration_ms: 41.16021
type: 'test'
...
# Subtest: a person's comment is counted and a bot's is not
ok 32 - a person's comment is counted and a bot's is not
---
duration_ms: 72.985532
type: 'test'
...
# Subtest: the hourly reconcile catches a comment through comment_count
ok 33 - the hourly reconcile catches a comment through comment_count
---
duration_ms: 76.813791
type: 'test'
...
# Subtest: a task closed in the UI leaves the open view with its done bucket
ok 34 - a task closed in the UI leaves the open view with its done bucket
---
duration_ms: 113.610013
type: 'test'
...
# Subtest: a task that leaves the board is recorded as deleted, moved or out of reach
ok 35 - a task that leaves the board is recorded as deleted, moved or out of reach
---
duration_ms: 65.693133
type: 'test'
...
# Subtest: a poll that read before a verb wrote does not overwrite the verb
ok 36 - a poll that read before a verb wrote does not overwrite the verb
---
duration_ms: 34.519446
type: 'test'
...
# Subtest: a tracker fault during a tick is reported and the next tick catches up
ok 37 - a tracker fault during a tick is reported and the next tick catches up
---
duration_ms: 35.540654
type: 'test'
...
# Subtest: a malformed answer refuses the tick with tracker-shape
ok 38 - a malformed answer refuses the tick with tracker-shape
---
duration_ms: 11.963452
type: 'test'
...
# Subtest: no token value reaches the database, the log or a refusal
ok 39 - no token value reaches the database, the log or a refusal
---
duration_ms: 46.592746
type: 'test'
...
# Subtest: the first look at a task counts only comments inside the window
ok 40 - the first look at a task counts only comments inside the window
---
duration_ms: 34.905182
type: 'test'
...
# Subtest: with descendants off the adapter reads no project list and no child, as in v0
ok 41 - with descendants off the adapter reads no project list and no child, as in v0
---
duration_ms: 45.272597
type: 'test'
...
# Subtest: a three-level tree is read per project, and a project outside it is not
ok 42 - a three-level tree is read per project, and a project outside it is not
---
duration_ms: 21.475483
type: 'test'
...
# Subtest: a watch-only child keeps the business ready, and a failed child read refuses as transient
ok 43 - a watch-only child keeps the business ready, and a failed child read refuses as transient
---
duration_ms: 26.92962
type: 'test'
...
# Subtest: a root without the installed buckets refuses with descendants on
ok 44 - a root without the installed buckets refuses with descendants on
---
duration_ms: 10.679158
type: 'test'
...
# Subtest: the project list refuses without read_all, and skips archived projects and saved filters
ok 45 - the project list refuses without read_all, and skips archived projects and saved filters
---
duration_ms: 23.327317
type: 'test'
...
# Subtest: descendants must be true or false
ok 46 - descendants must be true or false
---
duration_ms: 9.00679
type: 'test'
...
# Subtest: a move inside the tree is a moved tombstone plus a snapshot under the new ref
ok 47 - a move inside the tree is a moved tombstone plus a snapshot under the new ref
---
duration_ms: 63.81362
type: 'test'
...
# Subtest: a child made after startup joins the tree at the next reconcile
ok 48 - a child made after startup joins the tree at the next reconcile
---
duration_ms: 53.761186
type: 'test'
...
# Subtest: a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
ok 49 - a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
---
duration_ms: 58.663188
type: 'test'
...
# Subtest: a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
ok 50 - a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
---
duration_ms: 81.807043
type: 'test'
...
# Subtest: a reconcile that fails keeps the previous tree
ok 51 - a reconcile that fails keeps the previous tree
---
duration_ms: 32.544718
type: 'test'
...
# Subtest: a closed task the cursor missed takes its own project's done bucket
ok 52 - a closed task the cursor missed takes its own project's done bucket
---
duration_ms: 33.196306
type: 'test'
...
# Subtest: closed tasks read at startup take their own project's done bucket
ok 53 - closed tasks read at startup take their own project's done bucket
---
duration_ms: 9.152244
type: 'test'
...
# Subtest: a closed task the cursor returns takes its own project's done bucket
ok 54 - a closed task the cursor returns takes its own project's done bucket
---
duration_ms: 33.025508
type: 'test'
...
# Subtest: a task moved out of a child that leaves the tree at the same time is moved, not no-access
ok 55 - a task moved out of a child that leaves the tree at the same time is moved, not no-access
---
duration_ms: 31.314653
type: 'test'
...
# Subtest: a task in a bucket outside the five keeps its raw bucket id
ok 56 - a task in a bucket outside the five keeps its raw bucket id
---
duration_ms: 31.721671
type: 'test'
...
# Subtest: bucket 0 on a watch-only task never becomes a bucket or a state
ok 57 - bucket 0 on a watch-only task never becomes a bucket or a state
---
duration_ms: 76.658771
type: 'test'
...
# Subtest: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
not ok 58 - a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
---
duration_ms: 34.807865
type: 'test'
location: '/mnt/storage/src/mosaic-stack/.claude/worktrees/agent-a44468a48c485520e/packages/tasks/tests/tree.test.mjs:425:1'
failureType: 'testCodeFailure'
error: 'Missing expected rejection.'
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected:
code: 'tracker-not-found'
operator: 'rejects'
stack: |-
async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack/.claude/worktrees/agent-a44468a48c485520e/packages/tasks/tests/tree.test.mjs:472:3)
async Test.run (node:internal/test_runner/test:1409:7)
async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
...
# Subtest: a child dropped at a tick comes back at the next reconcile once the bot reads it again
ok 59 - a child dropped at a tick comes back at the next reconcile once the bot reads it again
---
duration_ms: 36.556206
type: 'test'
...
# Subtest: task.create needs a recorded human request and a requirement id
ok 60 - task.create needs a recorded human request and a requirement id
---
duration_ms: 37.477814
type: 'test'
...
# Subtest: task.create takes only an approved requirement id
ok 61 - task.create takes only an approved requirement id
---
duration_ms: 25.776035
type: 'test'
...
# Subtest: task.create cites the request a received message carries, not the message's id
ok 62 - task.create cites the request a received message carries, not the message's id
---
duration_ms: 21.428282
type: 'test'
...
# Subtest: only labels named in the business file can be written
ok 63 - only labels named in the business file can be written
---
duration_ms: 30.604156
type: 'test'
...
# Subtest: task.schedule sets and clears a due date and relations
ok 64 - task.schedule sets and clears a due date and relations
---
duration_ms: 35.696893
type: 'test'
...
# Subtest: assign and reassign move the role bots and record task.assigned
ok 65 - assign and reassign move the role bots and record task.assigned
---
duration_ms: 51.677173
type: 'test'
...
# Subtest: task.update.assigned is for the assignee and records task.state
ok 66 - task.update.assigned is for the assignee and records task.state
---
duration_ms: 44.590124
type: 'test'
...
# Subtest: a wrong expected digest records task.conflict and writes nothing
ok 67 - a wrong expected digest records task.conflict and writes nothing
---
duration_ms: 17.881052
type: 'test'
...
# Subtest: a cross-role verb needs a resolved decision, used once
ok 68 - a cross-role verb needs a resolved decision, used once
---
duration_ms: 20.322939
type: 'test'
...
# Subtest: task.close needs a verdict; after it every verb refuses with task-done
ok 69 - task.close needs a verdict; after it every verb refuses with task-done
---
duration_ms: 21.187137
type: 'test'
...
# Subtest: a lost answer is settled by a re-read and never retried
ok 70 - a lost answer is settled by a re-read and never retried
---
duration_ms: 25.142297
type: 'test'
...
# Subtest: a create whose answer is lost is reported uncertain, and the poll finds the task
ok 71 - a create whose answer is lost is reported uncertain, and the poll finds the task
---
duration_ms: 36.049367
type: 'test'
...
# Subtest: a task the sync bot cannot read refuses and records nothing
ok 72 - a task the sync bot cannot read refuses and records nothing
---
duration_ms: 15.744434
type: 'test'
...
# Subtest: verbs and polls for one business run one at a time
ok 73 - verbs and polls for one business run one at a time
---
duration_ms: 87.455266
type: 'test'
...
# Subtest: a due date with milliseconds is written to the second
ok 74 - a due date with milliseconds is written to the second
---
duration_ms: 63.926825
type: 'test'
...
# Subtest: every write landed and the final read failed: the verb succeeds and records what it wrote
ok 75 - every write landed and the final read failed: the verb succeeds and records what it wrote
---
duration_ms: 37.114019
type: 'test'
...
# Subtest: some writes landed and the final read failed: write-uncertain, and nothing is recorded
ok 76 - some writes landed and the final read failed: write-uncertain, and nothing is recorded
---
duration_ms: 14.619195
type: 'test'
...
# Subtest: a create whose final read fails succeeds and records task.created
ok 77 - a create whose final read fails succeeds and records task.created
---
duration_ms: 32.420325
type: 'test'
...
# Subtest: an edit between the last write and the final read shows as external on the next poll
ok 78 - an edit between the last write and the final read shows as external on the next poll
---
duration_ms: 34.851743
type: 'test'
...
# Subtest: task.created is recorded when a later label write fails
ok 79 - task.created is recorded when a later label write fails
---
duration_ms: 10.803743
type: 'test'
...
# Subtest: every verb acts in an installed child, on the child's own board
ok 80 - every verb acts in an installed child, on the child's own board
---
duration_ms: 41.977682
type: 'test'
...
# Subtest: task.create refuses a project outside the tree, a watch-only one and one that is not an id
ok 81 - task.create refuses a project outside the tree, a watch-only one and one that is not an id
---
duration_ms: 22.713698
type: 'test'
...
# Subtest: with descendants off, task.create takes only the root project
ok 82 - with descendants off, task.create takes only the root project
---
duration_ms: 11.216167
type: 'test'
...
# Subtest: a verb on a watch-only task, or a relation to one, refuses with project-not-installed
ok 83 - a verb on a watch-only task, or a relation to one, refuses with project-not-installed
---
duration_ms: 15.686458
type: 'test'
...
# Subtest: a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
ok 84 - a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
---
duration_ms: 21.530086
type: 'test'
...
# Subtest: a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
ok 85 - a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
---
duration_ms: 14.767496
type: 'test'
...
# Subtest: a verb and a create in the child record the final read of the child's board
ok 86 - a verb and a create in the child record the final read of the child's board
---
duration_ms: 14.054079
type: 'test'
...
# Subtest: a create in the child whose final read fails records the child's todo bucket
ok 87 - a create in the child whose final read fails records the child's todo bucket
---
duration_ms: 33.155996
type: 'test'
...
# Subtest: a lost answer in the child is settled by a re-read of the child's board
ok 88 - a lost answer in the child is settled by a re-read of the child's board
---
duration_ms: 18.780476
type: 'test'
...
# Subtest: every related task is read before authority, not only the first
ok 89 - every related task is read before authority, not only the first
---
duration_ms: 14.326976
type: 'test'
...
1..89
# tests 89
# suites 0
# pass 88
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 980.81047
@@ -0,0 +1,5 @@
r3-confirm-4xx killed rc=1 start=2026-10-13T14:48:04Z end=2026-10-13T14:48:05Z # tests 89 # pass 88 # fail 1
not ok: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
r3-confirm-error-on-throw killed rc=1 start=2026-10-13T14:48:05Z end=2026-10-13T14:48:06Z # tests 89 # pass 88 # fail 1
not ok: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
restored packages/tasks/src/sync.mjs sha256 35e79dc2ac56af8047bef11a5aaf5f1d37ce3e11513f9968454053068f59ebcf OK
@@ -0,0 +1,5 @@
r3-confirm-4xx killed rc=1 start=2026-10-13T14:48:04Z end=2026-10-13T14:48:05Z # tests 89 # pass 88 # fail 1
not ok: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
r3-confirm-error-on-throw killed rc=1 start=2026-10-13T14:48:05Z end=2026-10-13T14:48:06Z # tests 89 # pass 88 # fail 1
not ok: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
restored packages/tasks/src/sync.mjs sha256 35e79dc2ac56af8047bef11a5aaf5f1d37ce3e11513f9968454053068f59ebcf OK
@@ -0,0 +1,700 @@
TAP version 13
# Subtest: agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged
ok 1 - agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged
---
duration_ms: 29.404392
type: 'test'
...
# Subtest: agents: working counts what the holder received and has not read; routed alone is not working
ok 2 - agents: working counts what the holder received and has not read; routed alone is not working
---
duration_ms: 24.388082
type: 'test'
...
# Subtest: agents: input needed is the role's open decisions routed to the human, gated first, then oldest
ok 3 - agents: input needed is the role's open decisions routed to the human, gated first, then oldest
---
duration_ms: 41.095966
type: 'test'
...
# Subtest: agents: working wins over waiting, and Input needed still shows
ok 4 - agents: working wins over waiting, and Input needed still shows
---
duration_ms: 21.103277
type: 'test'
...
# Subtest: agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role
ok 5 - agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role
---
duration_ms: 29.086999
type: 'test'
...
# Subtest: agents: state reads only its own business, even for a run name both use
ok 6 - agents: state reads only its own business, even for a run name both use
---
duration_ms: 21.29204
type: 'test'
...
# Subtest: launch identity is stamped, payload identity is refused and stale holder cannot send
ok 7 - launch identity is stamped, payload identity is refused and stale holder cannot send
---
duration_ms: 28.153702
type: 'test'
...
# Subtest: decision classes route from policy; gated resolution is human-only, choice and target must match
ok 8 - decision classes route from policy; gated resolution is human-only, choice and target must match
---
duration_ms: 29.101524
type: 'test'
...
# Subtest: claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic
ok 9 - claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic
---
duration_ms: 33.031822
type: 'test'
...
# Subtest: launch events require a human CLI capability; generic emit cannot forge authority events
ok 10 - launch events require a human CLI capability; generic emit cannot forge authority events
---
duration_ms: 19.817481
type: 'test'
...
# Subtest: within-role decisions close atomically and invalid options or blocking omissions refuse
ok 11 - within-role decisions close atomically and invalid options or blocking omissions refuse
---
duration_ms: 25.074911
type: 'test'
...
# Subtest: observer capabilities read human inbox but cannot mutate or forge launch identity
ok 12 - observer capabilities read human inbox but cannot mutate or forge launch identity
---
duration_ms: 20.872654
type: 'test'
...
# Subtest: task action subjects and linked decision trail are complete and ordered
ok 13 - task action subjects and linked decision trail are complete and ordered
---
duration_ms: 30.519334
type: 'test'
...
# Subtest: launch binding is durable and reconnecting requires the identical trusted record
ok 14 - launch binding is durable and reconnecting requires the identical trusted record
---
duration_ms: 13.571008
type: 'test'
...
# Subtest: business isolation includes inherited object names and cross-business message references
ok 15 - business isolation includes inherited object names and cross-business message references
---
duration_ms: 23.959227
type: 'test'
...
# Subtest: authority never transfers between action, run, target, unresolved or replaced role holder
ok 16 - authority never transfers between action, run, target, unresolved or replaced role holder
---
duration_ms: 27.468671
type: 'test'
...
# Subtest: task projection uses schema current view, skipping earlier and equal-start polls
ok 17 - task projection uses schema current view, skipping earlier and equal-start polls
---
duration_ms: 14.469312
type: 'test'
...
# Subtest: revocation permanently bars the old run from reclaiming first, including after broker restart
ok 18 - revocation permanently bars the old run from reclaiming first, including after broker restart
---
duration_ms: 19.536403
type: 'test'
...
# Subtest: empty message references refuse before storage; refusal-evidence failure stays a typed error
ok 19 - empty message references refuse before storage; refusal-evidence failure stays a typed error
---
duration_ms: 11.665092
type: 'test'
...
# Subtest: both arbiters require human resolution when their cross-role route is themselves
ok 20 - both arbiters require human resolution when their cross-role route is themselves
---
duration_ms: 20.53905
type: 'test'
...
# Subtest: the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role
ok 21 - the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role
---
duration_ms: 17.56469
type: 'test'
...
# Subtest: S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input
ok 22 - S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input
---
duration_ms: 2.752409
type: 'test'
...
# Subtest: credentials gives human and reader sessions service, account, role, date and state, and nothing else
ok 23 - credentials gives human and reader sessions service, account, role, date and state, and nothing else
---
duration_ms: 20.969979
type: 'test'
...
# Subtest: credentials refuses a role session and any argument
ok 24 - credentials refuses a role session and any argument
---
duration_ms: 19.490276
type: 'test'
...
# Subtest: credentials reads the status on each request, and a broker without one lists none
ok 25 - credentials reads the status on each request, and a broker without one lists none
---
duration_ms: 24.262478
type: 'test'
...
# Subtest: the broker process answers credentials without a token, path or variable in its output, log or store
ok 26 - the broker process answers credentials without a token, path or variable in its output, log or store
---
duration_ms: 80.104856
type: 'test'
...
# Subtest: only validated broker references load; returned data and exceptions cannot expose a known token
ok 27 - only validated broker references load; returned data and exceptions cannot expose a known token
---
duration_ms: 4.733079
type: 'test'
...
# Subtest: bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse
ok 28 - bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse
---
duration_ms: 4.008375
type: 'test'
...
# Subtest: expiry refuses use and env references never become client data
ok 29 - expiry refuses use and env references never become client data
---
duration_ms: 0.900712
type: 'test'
...
# Subtest: S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state
ok 30 - S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state
---
duration_ms: 2.062545
type: 'test'
...
# Subtest: opaque tokens shorter than 16 characters refuse before use
ok 31 - opaque tokens shorter than 16 characters refuse before use
---
duration_ms: 0.43369
type: 'test'
...
# Subtest: roles lists open decisions routed to a role, and never the human inbox
ok 32 - roles lists open decisions routed to a role, and never the human inbox
---
duration_ms: 37.367827
type: 'test'
...
# Subtest: recent lists closed decisions of every route, newest close first, with how each closed
ok 33 - recent lists closed decisions of every route, newest close first, with how each closed
---
duration_ms: 33.698975
type: 'test'
...
# Subtest: recent gives the closing event as closed when the decision was seen first
ok 34 - recent gives the closing event as closed when the decision was seen first
---
duration_ms: 36.302512
type: 'test'
...
# Subtest: recent stops at RECENT rows
ok 35 - recent stops at RECENT rows
---
duration_ms: 112.381059
type: 'test'
...
# Subtest: every row is what trail already gives the same session for that id
ok 36 - every row is what trail already gives the same session for that id
---
duration_ms: 39.417836
type: 'test'
...
# Subtest: a role session can't list decisions, so it can't read another role's open decisions
ok 37 - a role session can't list decisions, so it can't read another role's open decisions
---
duration_ms: 38.923681
type: 'test'
...
# Subtest: decisions is a read: one business, strict arguments, nothing written
ok 38 - decisions is a read: one business, strict arguments, nothing written
---
duration_ms: 34.929545
type: 'test'
...
# Subtest: endLaunch writes session.ended, releases the run claim and kills its capabilities
ok 39 - endLaunch writes session.ended, releases the run claim and kills its capabilities
---
duration_ms: 24.898626
type: 'test'
...
# Subtest: endLaunch refuses an unknown run, a second end and a rebind of the ended run
ok 40 - endLaunch refuses an unknown run, a second end and a rebind of the ended run
---
duration_ms: 14.111017
type: 'test'
...
# Subtest: a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound
ok 41 - a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound
---
duration_ms: 18.644999
type: 'test'
...
# Subtest: endLaunch leaves a claim another run took alone
ok 42 - endLaunch leaves a claim another run took alone
---
duration_ms: 20.834805
type: 'test'
...
# Subtest: refuse records action.refused against the caller with the code only
ok 43 - refuse records action.refused against the caller with the code only
---
duration_ms: 16.75486
type: 'test'
...
# Subtest: launches off refuses role.launch with launch-revoked until launches on
ok 44 - launches off refuses role.launch with launch-revoked until launches on
---
duration_ms: 21.337677
type: 'test'
...
# Subtest: broker process: launch ops authorize role.launch, record refusals and end runs
ok 45 - broker process: launch ops authorize role.launch, record refusals and end runs
---
duration_ms: 98.224744
type: 'test'
...
# Subtest: human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse
ok 46 - human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse
---
duration_ms: 3.785214
type: 'test'
...
# Subtest: process reader gets own kernel identity without exposing environment values
ok 47 - process reader gets own kernel identity without exposing environment values
---
duration_ms: 0.708465
type: 'test'
...
# Subtest: EACCES ancestor environments skip only markers; commands and registered launches still refuse
ok 48 - EACCES ancestor environments skip only markers; commands and registered launches still refuse
---
duration_ms: 0.931919
type: 'test'
...
# Subtest: real pid 1 remains inspectable when its environment is protected
ok 49 - real pid 1 remains inspectable when its environment is protected
---
duration_ms: 0.378096
type: 'test'
...
# Subtest: within-role sends cite an open gated launch decision without spending it or naming it in grants
ok 50 - within-role sends cite an open gated launch decision without spending it or naming it in grants
---
duration_ms: 31.467452
type: 'test'
...
# Subtest: missing and foreign-business citations refuse and roll back message and grant
ok 51 - missing and foreign-business citations refuse and roll back message and grant
---
duration_ms: 21.397751
type: 'test'
...
# Subtest: cross-role sends still need a matching resolved decision and consume it once
ok 52 - cross-role sends still need a matching resolved decision and consume it once
---
duration_ms: 31.69782
type: 'test'
...
# Subtest: messages pages all human messages newest first without writes; read state is history
ok 53 - messages pages all human messages newest first without writes; read state is history
---
duration_ms: 347.390182
type: 'test'
...
# Subtest: messages refuses role callers, invalid paging and cursors outside this human feed
ok 54 - messages refuses role callers, invalid paging and cursors outside this human feed
---
duration_ms: 18.565262
type: 'test'
...
# Subtest: views messages passes only its paging arguments through
ok 55 - views messages passes only its paging arguments through
---
duration_ms: 0.230416
type: 'test'
...
# Subtest: messages isolates businesses even with a valid foreign cursor
ok 56 - messages isolates businesses even with a valid foreign cursor
---
duration_ms: 10.260464
type: 'test'
...
# Subtest: broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly
ok 57 - broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly
---
duration_ms: 88.499191
type: 'test'
...
# Subtest: startup token refusal returns safe code without value or partial listening broker
ok 58 - startup token refusal returns safe code without value or partial listening broker
---
duration_ms: 55.806194
type: 'test'
...
# Subtest: loaded fixture token is absent from socket replies and SQLite, including refusal evidence
ok 59 - loaded fixture token is absent from socket replies and SQLite, including refusal evidence
---
duration_ms: 73.825352
type: 'test'
...
# Subtest: killed broker leaves an explicit stale lock; another process cannot silently reclaim it
ok 60 - killed broker leaves an explicit stale lock; another process cannot silently reclaim it
---
duration_ms: 93.548139
type: 'test'
...
# Subtest: trusted host registers later launches; socket clients never have a registration verb
ok 61 - trusted host registers later launches; socket clients never have a registration verb
---
duration_ms: 56.121313
type: 'test'
...
# Subtest: runtime excludes declared project roots even when host supplies no repoRoots
ok 62 - runtime excludes declared project roots even when host supplies no repoRoots
---
duration_ms: 37.978129
type: 'test'
...
# Subtest: a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it
ok 63 - a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it
---
duration_ms: 55.354582
type: 'test'
...
# Subtest: a reply is listed for human and reader sessions, and its delivery rows are unchanged
ok 64 - a reply is listed for human and reader sessions, and its delivery rows are unchanged
---
duration_ms: 43.544135
type: 'test'
...
# Subtest: the reply still reaches the human message.receive (mosaic talk) after the Console showed it
ok 65 - the reply still reaches the human message.receive (mosaic talk) after the Console showed it
---
duration_ms: 22.976264
type: 'test'
...
# Subtest: a message with no reply gives an empty list
ok 66 - a message with no reply gives an empty list
---
duration_ms: 19.763755
type: 'test'
...
# Subtest: replies come oldest first and stop at REPLIES
ok 67 - replies come oldest first and stop at REPLIES
---
duration_ms: 93.997141
type: 'test'
...
# Subtest: an id that names no message in the business refuses message-not-found, and the refusal is recorded
ok 68 - an id that names no message in the business refuses message-not-found, and the refusal is recorded
---
duration_ms: 33.267248
type: 'test'
...
# Subtest: strict arguments; a role session gets human-required
ok 69 - strict arguments; a role session gets human-required
---
duration_ms: 33.780563
type: 'test'
...
# Subtest: views passes replies through as one call with the id
ok 70 - views passes replies through as one call with the id
---
duration_ms: 0.239359
type: 'test'
...
# Subtest: requirements returns the committed list to a holding role session, and no one else
ok 71 - requirements returns the committed list to a holding role session, and no one else
---
duration_ms: 29.706814
type: 'test'
...
# Subtest: the PM's prd.approve with no task, when no id fits, reaches the human's Inbox
ok 72 - the PM's prd.approve with no task, when no id fits, reaches the human's Inbox
---
duration_ms: 18.864349
type: 'test'
...
# Subtest: the PM's non-blocking role.revoke with no task reaches the human's Inbox
ok 73 - the PM's non-blocking role.revoke with no task reaches the human's Inbox
---
duration_ms: 21.736755
type: 'test'
...
# Subtest: v3b prototype refusals, views and append-only mutations
ok 74 - v3b prototype refusals, views and append-only mutations
---
duration_ms: 94.540081
type: 'test'
...
# Subtest: gated approval authorizes once, survives store reopen, and fresh approval works
ok 75 - gated approval authorizes once, survives store reopen, and fresh approval works
---
duration_ms: 35.29223
type: 'test'
...
# Subtest: another run cannot consume an approval; a failed check leaves it usable
ok 76 - another run cannot consume an approval; a failed check leaves it usable
---
duration_ms: 27.487187
type: 'test'
...
# Subtest: two scheduled callers have exactly one grant and one consumed refusal
ok 77 - two scheduled callers have exactly one grant and one consumed refusal
---
duration_ms: 18.592453
type: 'test'
...
# Subtest: failed commit rolls consumption back; cross-role consumes and within-role stays reusable
ok 78 - failed commit rolls consumption back; cross-role consumes and within-role stays reusable
---
duration_ms: 42.955639
type: 'test'
...
# Subtest: class drift gated to cross-role refuses before consumption
ok 79 - class drift gated to cross-role refuses before consumption
---
duration_ms: 26.871433
type: 'test'
...
# Subtest: class drift cross-role to gated refuses before consumption
ok 80 - class drift cross-role to gated refuses before consumption
---
duration_ms: 27.161389
type: 'test'
...
# Subtest: class drift gated to within-role refuses before consumption
ok 81 - class drift gated to within-role refuses before consumption
---
duration_ms: 22.625194
type: 'test'
...
# Subtest: class drift cross-role to within-role refuses before consumption
ok 82 - class drift cross-role to within-role refuses before consumption
---
duration_ms: 25.887318
type: 'test'
...
# Subtest: class drift within-role to gated refuses before consumption
ok 83 - class drift within-role to gated refuses before consumption
---
duration_ms: 20.414737
type: 'test'
...
# Subtest: class drift within-role to cross-role refuses before consumption
ok 84 - class drift within-role to cross-role refuses before consumption
---
duration_ms: 19.083114
type: 'test'
...
# Subtest: message.send consumes approval and prevents a later send or authorize
ok 85 - message.send consumes approval and prevents a later send or authorize
---
duration_ms: 19.984908
type: 'test'
...
# Subtest: role.revoke consumes approval and prevents a later revoke or authorize
ok 86 - role.revoke consumes approval and prevents a later revoke or authorize
---
duration_ms: 20.262932
type: 'test'
...
# Subtest: creates private WAL store and excludes a second writer until explicit close
ok 87 - creates private WAL store and excludes a second writer until explicit close
---
duration_ms: 18.586235
type: 'test'
...
# Subtest: rollback is atomic and schema metadata is checked against trusted DDL, not just itself
ok 88 - rollback is atomic and schema metadata is checked against trusted DDL, not just itself
---
duration_ms: 19.823934
type: 'test'
...
# Subtest: existing empty database and symlink runtime directory refuse, never initialize over damage
ok 89 - existing empty database and symlink runtime directory refuse, never initialize over damage
---
duration_ms: 20.148158
type: 'test'
...
# Subtest: crash during a transaction recovers no partial event after explicit fixture-only lock removal
ok 90 - crash during a transaction recovers no partial event after explicit fixture-only lock removal
---
duration_ms: 62.573919
type: 'test'
...
# Subtest: writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers
ok 91 - writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers
---
duration_ms: 13.713291
type: 'test'
...
# Subtest: async transactions refuse before invoking their function
ok 92 - async transactions refuse before invoking their function
---
duration_ms: 10.245812
type: 'test'
...
# Subtest: the session default fits under the reply cap and pages to the end with next
ok 93 - the session default fits under the reply cap and pages to the end with next
---
duration_ms: 182.297793
type: 'test'
...
# Subtest: the short form: no description, assignees by role, every listed key
ok 94 - the short form: no description, assignees by role, every listed key
---
duration_ms: 80.842934
type: 'test'
...
# Subtest: each filter, alone and together, and total counts every match
ok 95 - each filter, alone and together, and total counts every match
---
duration_ms: 148.772203
type: 'test'
...
# Subtest: task_ref reads one task in full, as the whole board has it
ok 96 - task_ref reads one task in full, as the whole board has it
---
duration_ms: 86.059366
type: 'test'
...
# Subtest: no arguments is the read the Console and mosaic make, unchanged
ok 97 - no arguments is the read the Console and mosaic make, unchanged
---
duration_ms: 68.410868
type: 'test'
...
# Subtest: an unknown argument or a bad value refuses invalid-request
ok 98 - an unknown argument or a bad value refuses invalid-request
---
duration_ms: 287.824699
type: 'test'
...
# Subtest: tasks rows carry priority and requirement for every session that reads tasks
ok 99 - tasks rows carry priority and requirement for every session that reads tasks
---
duration_ms: 46.590704
type: 'test'
...
# Subtest: the read model rebuilds from the ledger: a reopened bus and each trail give the same values
ok 100 - the read model rebuilds from the ledger: a reopened bus and each trail give the same values
---
duration_ms: 51.526953
type: 'test'
...
# Subtest: an empty business and one with snapshots but no task.created read cleanly
ok 101 - an empty business and one with snapshots but no task.created read cleanly
---
duration_ms: 12.286622
type: 'test'
...
# Subtest: recordTask keeps sync reads and a role write apart
ok 102 - recordTask keeps sync reads and a role write apart
---
duration_ms: 24.793842
type: 'test'
...
# Subtest: read_at must be one canonical UTC format, so the projection compares strings safely
ok 103 - read_at must be one canonical UTC format, so the projection compares strings safely
---
duration_ms: 11.673334
type: 'test'
...
# Subtest: a bad entry refuses the whole record
ok 104 - a bad entry refuses the whole record
---
duration_ms: 11.412186
type: 'test'
...
# Subtest: taskView reads the projection for one business
ok 105 - taskView reads the projection for one business
---
duration_ms: 13.571013
type: 'test'
...
# Subtest: requestTask hands only a holder and a task verb to the handler, and records refusals
ok 106 - requestTask hands only a holder and a task verb to the handler, and records refusals
---
duration_ms: 23.931202
type: 'test'
...
# Subtest: the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous
ok 107 - the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous
---
duration_ms: 275.781364
type: 'test'
...
# Subtest: without an adapter the server refuses every task verb
ok 108 - without an adapter the server refuses every task verb
---
duration_ms: 15.732511
type: 'test'
...
# Subtest: the runtime refuses an invalid adapter and closes a valid one
ok 109 - the runtime refuses an invalid adapter and closes a valid one
---
duration_ms: 16.680061
type: 'test'
...
# Subtest: the process loads the S3 adapter from plain-data trackers
ok 110 - the process loads the S3 adapter from plain-data trackers
---
duration_ms: 98.450111
type: 'test'
...
# Subtest: socket capability stamps launch identity; shared views use wire, no SQL client
ok 111 - socket capability stamps launch identity; shared views use wire, no SQL client
---
duration_ms: 31.177984
type: 'test'
...
# Subtest: two wire claims serialize; a lost reply never automatically retries
ok 112 - two wire claims serialize; a lost reply never automatically retries
---
duration_ms: 23.843443
type: 'test'
...
# Subtest: malformed, oversized and identity-forging envelopes refuse without echoing input
ok 113 - malformed, oversized and identity-forging envelopes refuse without echoing input
---
duration_ms: 12.08672
type: 'test'
...
# Subtest: client preserves UTF-8 when a response divides a multibyte character
ok 114 - client preserves UTF-8 when a response divides a multibyte character
---
duration_ms: 12.689802
type: 'test'
...
# Subtest: committed mutation followed by dropped reply reports unknown and is never retried
ok 115 - committed mutation followed by dropped reply reports unknown and is never retried
---
duration_ms: 15.867775
type: 'test'
...
1..115
# tests 115
# suites 0
# pass 115
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 1009.541259
@@ -0,0 +1,544 @@
TAP version 13
# Subtest: the boot config is checked before anything starts
ok 1 - the boot config is checked before anything starts
---
duration_ms: 15.373002
type: 'test'
...
# Subtest: a business with no tracker entry refuses task verbs
ok 2 - a business with no tracker entry refuses task verbs
---
duration_ms: 16.54793
type: 'test'
...
# Subtest: credential.expiring and .expired are recorded once per instance
ok 3 - credential.expiring and .expired are recorded once per instance
---
duration_ms: 32.903372
type: 'test'
...
# Subtest: a token file that changes on disk records credential.changed
ok 4 - a token file that changes on disk records credential.changed
---
duration_ms: 13.718499
type: 'test'
...
# Subtest: autostart polls, reconciles and retries a startup the tracker was down for
ok 5 - autostart polls, reconciles and retries a startup the tracker was down for
---
duration_ms: 36.388706
type: 'test'
...
# Subtest: a refusal a restart must clear is not retried by the poll
ok 6 - a refusal a restart must clear is not retried by the poll
---
duration_ms: 11.731165
type: 'test'
...
# Subtest: a poll that fires while two are queued is dropped
ok 7 - a poll that fires while two are queued is dropped
---
duration_ms: 14.792592
type: 'test'
...
# Subtest: close waits for a running verb and refuses one that has not started
ok 8 - close waits for a running verb and refuses one that has not started
---
duration_ms: 43.160938
type: 'test'
...
# Subtest: the bundled Vikunja is the pinned upstream image the runbook names
ok 9 - the bundled Vikunja is the pinned upstream image the runbook names
---
duration_ms: 1.122644
type: 'test'
...
# Subtest: every published port is on 127.0.0.1, and no secret is in the file
ok 10 - every published port is on 127.0.0.1, and no secret is in the file
---
duration_ms: 0.422977
type: 'test'
...
# Subtest: the committed table loads frozen; its verbs are the broker task verbs
ok 11 - the committed table loads frozen; its verbs are the broker task verbs
---
duration_ms: 1.401375
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 12 - the schema refuses any other shape
---
duration_ms: 3.119555
type: 'test'
...
# Subtest: each verb refuses, asks for a decision and writes as the table and the role files say
ok 13 - each verb refuses, asks for a decision and writes as the table and the role files say
---
duration_ms: 161.876618
type: 'test'
...
# Subtest: the list holds the PRD's requirement ids, in its order, at its version
ok 14 - the list holds the PRD's requirement ids, in its order, at its version
---
duration_ms: 5.015825
type: 'test'
...
# Subtest: the committed list loads frozen
ok 15 - the committed list loads frozen
---
duration_ms: 0.503693
type: 'test'
...
# Subtest: the schema refuses any other shape
ok 16 - the schema refuses any other shape
---
duration_ms: 2.487269
type: 'test'
...
# Subtest: the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
ok 17 - the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent
---
duration_ms: 98.430176
type: 'test'
...
# Subtest: the project list holds recorded project objects in the recorded list envelope
ok 18 - the project list holds recorded project objects in the recorded list envelope
---
duration_ms: 10.372561
type: 'test'
...
# Subtest: the recorded task bodies pass the checks S3 applies to every read
ok 19 - the recorded task bodies pass the checks S3 applies to every read
---
duration_ms: 0.447974
type: 'test'
...
# Subtest: the client works against the fake over real HTTP with the platform fetch
ok 20 - the client works against the fake over real HTTP with the platform fetch
---
duration_ms: 100.522814
type: 'test'
...
# Subtest: a correct install starts, and the first reconcile records tasks that already exist
ok 21 - a correct install starts, and the first reconcile records tasks that already exist
---
duration_ms: 25.186592
type: 'test'
...
# Subtest: verbs refuse while a business is starting and after startup refused it
ok 22 - verbs refuse while a business is starting and after startup refused it
---
duration_ms: 16.584152
type: 'test'
...
# Subtest: startup refuses a token that can do more than its role needs
ok 23 - startup refuses a token that can do more than its role needs
---
duration_ms: 43.957423
type: 'test'
...
# Subtest: startup refuses an unsupported version and flags an untested one
ok 24 - startup refuses an unsupported version and flags an untested one
---
duration_ms: 30.417189
type: 'test'
...
# Subtest: startup refuses a board that the runbook did not install
ok 25 - startup refuses a board that the runbook did not install
---
duration_ms: 39.769969
type: 'test'
...
# Subtest: startup refuses a project the sync bot cannot read
ok 26 - startup refuses a project the sync bot cannot read
---
duration_ms: 10.619813
type: 'test'
...
# Subtest: startup refuses a configured label the pm bot cannot see
ok 27 - startup refuses a configured label the pm bot cannot see
---
duration_ms: 9.55423
type: 'test'
...
# Subtest: startup refuses an expired credential and a missing sync credential
ok 28 - startup refuses an expired credential and a missing sync credential
---
duration_ms: 15.33053
type: 'test'
...
# Subtest: an unreachable tracker refuses with tracker-unavailable
ok 29 - an unreachable tracker refuses with tracker-unavailable
---
duration_ms: 6.047777
type: 'test'
...
# Subtest: an edit in the UI is recorded once, with the fields that changed
ok 30 - an edit in the UI is recorded once, with the fields that changed
---
duration_ms: 81.651407
type: 'test'
...
# Subtest: a move between open buckets is seen on the board, though updated does not change
ok 31 - a move between open buckets is seen on the board, though updated does not change
---
duration_ms: 40.65521
type: 'test'
...
# Subtest: a person's comment is counted and a bot's is not
ok 32 - a person's comment is counted and a bot's is not
---
duration_ms: 72.160882
type: 'test'
...
# Subtest: the hourly reconcile catches a comment through comment_count
ok 33 - the hourly reconcile catches a comment through comment_count
---
duration_ms: 75.571973
type: 'test'
...
# Subtest: a task closed in the UI leaves the open view with its done bucket
ok 34 - a task closed in the UI leaves the open view with its done bucket
---
duration_ms: 114.050267
type: 'test'
...
# Subtest: a task that leaves the board is recorded as deleted, moved or out of reach
ok 35 - a task that leaves the board is recorded as deleted, moved or out of reach
---
duration_ms: 62.861146
type: 'test'
...
# Subtest: a poll that read before a verb wrote does not overwrite the verb
ok 36 - a poll that read before a verb wrote does not overwrite the verb
---
duration_ms: 33.650755
type: 'test'
...
# Subtest: a tracker fault during a tick is reported and the next tick catches up
ok 37 - a tracker fault during a tick is reported and the next tick catches up
---
duration_ms: 36.726265
type: 'test'
...
# Subtest: a malformed answer refuses the tick with tracker-shape
ok 38 - a malformed answer refuses the tick with tracker-shape
---
duration_ms: 13.16272
type: 'test'
...
# Subtest: no token value reaches the database, the log or a refusal
ok 39 - no token value reaches the database, the log or a refusal
---
duration_ms: 45.451924
type: 'test'
...
# Subtest: the first look at a task counts only comments inside the window
ok 40 - the first look at a task counts only comments inside the window
---
duration_ms: 34.839318
type: 'test'
...
# Subtest: with descendants off the adapter reads no project list and no child, as in v0
ok 41 - with descendants off the adapter reads no project list and no child, as in v0
---
duration_ms: 48.293931
type: 'test'
...
# Subtest: a three-level tree is read per project, and a project outside it is not
ok 42 - a three-level tree is read per project, and a project outside it is not
---
duration_ms: 22.741197
type: 'test'
...
# Subtest: a watch-only child keeps the business ready, and a failed child read refuses as transient
ok 43 - a watch-only child keeps the business ready, and a failed child read refuses as transient
---
duration_ms: 25.584269
type: 'test'
...
# Subtest: a root without the installed buckets refuses with descendants on
ok 44 - a root without the installed buckets refuses with descendants on
---
duration_ms: 10.829984
type: 'test'
...
# Subtest: the project list refuses without read_all, and skips archived projects and saved filters
ok 45 - the project list refuses without read_all, and skips archived projects and saved filters
---
duration_ms: 25.614391
type: 'test'
...
# Subtest: descendants must be true or false
ok 46 - descendants must be true or false
---
duration_ms: 10.090398
type: 'test'
...
# Subtest: a move inside the tree is a moved tombstone plus a snapshot under the new ref
ok 47 - a move inside the tree is a moved tombstone plus a snapshot under the new ref
---
duration_ms: 63.257475
type: 'test'
...
# Subtest: a child made after startup joins the tree at the next reconcile
ok 48 - a child made after startup joins the tree at the next reconcile
---
duration_ms: 53.464339
type: 'test'
...
# Subtest: a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
ok 49 - a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history
---
duration_ms: 59.379728
type: 'test'
...
# Subtest: a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
ok 50 - a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses
---
duration_ms: 80.722644
type: 'test'
...
# Subtest: a reconcile that fails keeps the previous tree
ok 51 - a reconcile that fails keeps the previous tree
---
duration_ms: 30.274693
type: 'test'
...
# Subtest: a closed task the cursor missed takes its own project's done bucket
ok 52 - a closed task the cursor missed takes its own project's done bucket
---
duration_ms: 33.556879
type: 'test'
...
# Subtest: closed tasks read at startup take their own project's done bucket
ok 53 - closed tasks read at startup take their own project's done bucket
---
duration_ms: 11.304826
type: 'test'
...
# Subtest: a closed task the cursor returns takes its own project's done bucket
ok 54 - a closed task the cursor returns takes its own project's done bucket
---
duration_ms: 34.47553
type: 'test'
...
# Subtest: a task moved out of a child that leaves the tree at the same time is moved, not no-access
ok 55 - a task moved out of a child that leaves the tree at the same time is moved, not no-access
---
duration_ms: 33.855457
type: 'test'
...
# Subtest: a task in a bucket outside the five keeps its raw bucket id
ok 56 - a task in a bucket outside the five keeps its raw bucket id
---
duration_ms: 29.916939
type: 'test'
...
# Subtest: bucket 0 on a watch-only task never becomes a bucket or a state
ok 57 - bucket 0 on a watch-only task never becomes a bucket or a state
---
duration_ms: 78.180511
type: 'test'
...
# Subtest: a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
ok 58 - a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only
---
duration_ms: 55.83525
type: 'test'
...
# Subtest: a child dropped at a tick comes back at the next reconcile once the bot reads it again
ok 59 - a child dropped at a tick comes back at the next reconcile once the bot reads it again
---
duration_ms: 35.039514
type: 'test'
...
# Subtest: task.create needs a recorded human request and a requirement id
ok 60 - task.create needs a recorded human request and a requirement id
---
duration_ms: 40.038164
type: 'test'
...
# Subtest: task.create takes only an approved requirement id
ok 61 - task.create takes only an approved requirement id
---
duration_ms: 26.188455
type: 'test'
...
# Subtest: task.create cites the request a received message carries, not the message's id
ok 62 - task.create cites the request a received message carries, not the message's id
---
duration_ms: 20.204034
type: 'test'
...
# Subtest: only labels named in the business file can be written
ok 63 - only labels named in the business file can be written
---
duration_ms: 28.889903
type: 'test'
...
# Subtest: task.schedule sets and clears a due date and relations
ok 64 - task.schedule sets and clears a due date and relations
---
duration_ms: 35.511892
type: 'test'
...
# Subtest: assign and reassign move the role bots and record task.assigned
ok 65 - assign and reassign move the role bots and record task.assigned
---
duration_ms: 52.985464
type: 'test'
...
# Subtest: task.update.assigned is for the assignee and records task.state
ok 66 - task.update.assigned is for the assignee and records task.state
---
duration_ms: 45.462286
type: 'test'
...
# Subtest: a wrong expected digest records task.conflict and writes nothing
ok 67 - a wrong expected digest records task.conflict and writes nothing
---
duration_ms: 18.246971
type: 'test'
...
# Subtest: a cross-role verb needs a resolved decision, used once
ok 68 - a cross-role verb needs a resolved decision, used once
---
duration_ms: 20.824764
type: 'test'
...
# Subtest: task.close needs a verdict; after it every verb refuses with task-done
ok 69 - task.close needs a verdict; after it every verb refuses with task-done
---
duration_ms: 18.669837
type: 'test'
...
# Subtest: a lost answer is settled by a re-read and never retried
ok 70 - a lost answer is settled by a re-read and never retried
---
duration_ms: 22.962907
type: 'test'
...
# Subtest: a create whose answer is lost is reported uncertain, and the poll finds the task
ok 71 - a create whose answer is lost is reported uncertain, and the poll finds the task
---
duration_ms: 34.833368
type: 'test'
...
# Subtest: a task the sync bot cannot read refuses and records nothing
ok 72 - a task the sync bot cannot read refuses and records nothing
---
duration_ms: 14.189432
type: 'test'
...
# Subtest: verbs and polls for one business run one at a time
ok 73 - verbs and polls for one business run one at a time
---
duration_ms: 87.217517
type: 'test'
...
# Subtest: a due date with milliseconds is written to the second
ok 74 - a due date with milliseconds is written to the second
---
duration_ms: 63.3084
type: 'test'
...
# Subtest: every write landed and the final read failed: the verb succeeds and records what it wrote
ok 75 - every write landed and the final read failed: the verb succeeds and records what it wrote
---
duration_ms: 36.767011
type: 'test'
...
# Subtest: some writes landed and the final read failed: write-uncertain, and nothing is recorded
ok 76 - some writes landed and the final read failed: write-uncertain, and nothing is recorded
---
duration_ms: 14.892048
type: 'test'
...
# Subtest: a create whose final read fails succeeds and records task.created
ok 77 - a create whose final read fails succeeds and records task.created
---
duration_ms: 33.229455
type: 'test'
...
# Subtest: an edit between the last write and the final read shows as external on the next poll
ok 78 - an edit between the last write and the final read shows as external on the next poll
---
duration_ms: 34.927009
type: 'test'
...
# Subtest: task.created is recorded when a later label write fails
ok 79 - task.created is recorded when a later label write fails
---
duration_ms: 12.685295
type: 'test'
...
# Subtest: every verb acts in an installed child, on the child's own board
ok 80 - every verb acts in an installed child, on the child's own board
---
duration_ms: 40.250043
type: 'test'
...
# Subtest: task.create refuses a project outside the tree, a watch-only one and one that is not an id
ok 81 - task.create refuses a project outside the tree, a watch-only one and one that is not an id
---
duration_ms: 23.879872
type: 'test'
...
# Subtest: with descendants off, task.create takes only the root project
ok 82 - with descendants off, task.create takes only the root project
---
duration_ms: 11.825594
type: 'test'
...
# Subtest: a verb on a watch-only task, or a relation to one, refuses with project-not-installed
ok 83 - a verb on a watch-only task, or a relation to one, refuses with project-not-installed
---
duration_ms: 17.946104
type: 'test'
...
# Subtest: a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
ok 84 - a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found
---
duration_ms: 23.395865
type: 'test'
...
# Subtest: a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
ok 85 - a task moved to another project of the tree refuses its old ref with task-moved and takes its new one
---
duration_ms: 14.305279
type: 'test'
...
# Subtest: a verb and a create in the child record the final read of the child's board
ok 86 - a verb and a create in the child record the final read of the child's board
---
duration_ms: 12.940352
type: 'test'
...
# Subtest: a create in the child whose final read fails records the child's todo bucket
ok 87 - a create in the child whose final read fails records the child's todo bucket
---
duration_ms: 33.588967
type: 'test'
...
# Subtest: a lost answer in the child is settled by a re-read of the child's board
ok 88 - a lost answer in the child is settled by a re-read of the child's board
---
duration_ms: 21.070278
type: 'test'
...
# Subtest: every related task is read before authority, not only the first
ok 89 - every related task is read before authority, not only the first
---
duration_ms: 15.963255
type: 'test'
...
1..89
# tests 89
# suites 0
# pass 89
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 983.468677
@@ -0,0 +1,17 @@
OK status with missing harness credential exits 3 and still lists accounts
OK status reports harness credential (read-only) + mosaic accounts
OK api key material never reaches output
OK oauth token material never reaches output
OK unparseable credential file exits 2
OK symlinked credential file exits 4
OK env-side credential names reported
OK env var values never reach output
OK accounts without an accounts dir reports none and creates nothing
OK accounts lists files and marks the active one
OK loose account perms flagged in listing
OK agent --auth with missing account file refuses (exit 4)
OK agent --auth with non-0600 account file refuses
OK agent --auth with invalid account name refuses
OK auth.sh without valid config refuses
selftest: 15 passed, 0 failed
@@ -0,0 +1,23 @@
On branch refactor
Your branch is up to date with 'origin/refactor'.
nothing to commit, working tree clean
OK dry-run: allowed change, exit 0, nothing committed (exit 0)
OK dry-run committed nothing
OK apply: allowed change exits 0 (exit 0)
OK apply: attribution in commit subject
OK apply: target tree clean after commit
OK disallowed path refused (exit 1)
OK disallowed path: target untouched
OK syntax gate refused broken .mjs (exit 1)
OK syntax gate: target untouched
OK suite failure refused (exit 1)
OK suite failure: target reverted to clean
OK disabled policy refused (exit 2)
OK disabled policy: target untouched
OK failed run refused (exit 1)
OK failed run: target untouched
OK missing run exits 4 (exit 4)
OK invalid policy exits 2 (exit 2)
selftest: 17 passed, 0 failed
@@ -0,0 +1,26 @@
OK absent adapter defaults to pi
OK adapter mock validates (exit 0)
OK unsupported adapter exits 2 (exit 2)
OK env exports adapter
OK bootstrap creates default when absent (exit 0)
OK bootstrap wrote config file
OK bootstrap is idempotent on existing config (exit 0)
OK bootstrap did not rewrite existing config
OK validate missing config exits 3 (exit 3)
OK malformed JSON exits 2 (exit 2)
OK unsupported configVersion exits 2 (exit 2)
OK unknown top-level key exits 2 (exit 2)
OK unknown execution key exits 2 (exit 2)
OK unsupported backend exits 2 (exit 2)
OK unsupported environment exits 2 (exit 2)
OK relative dataRoot exits 2 (exit 2)
OK non-canonical dataRoot exits 2 (exit 2)
OK filesystem root dataRoot exits 2 (exit 2)
OK home directory dataRoot exits 2 (exit 2)
OK dataRoot containing config dir exits 2 (exit 2)
OK control character in provider exits 2 (exit 2)
OK symlinked config file exits 2 (exit 2)
OK env exports resolve correctly
OK failed validation modified nothing
selftest: 24 passed, 0 failed
@@ -0,0 +1,70 @@
toolchain: node v26.8.1
OK syntax: packages/discord/src/approvals.mjs
OK syntax: packages/discord/src/authorize.mjs
OK syntax: packages/discord/src/binding.mjs
OK syntax: packages/discord/src/cli.mjs
OK syntax: packages/discord/src/connector.mjs
OK syntax: packages/discord/src/context.mjs
OK syntax: packages/discord/src/engine-pi.mjs
OK syntax: packages/discord/src/errors.mjs
OK syntax: packages/discord/src/gateway.mjs
OK syntax: packages/discord/src/git.mjs
OK syntax: packages/discord/src/journal.mjs
OK syntax: packages/discord/src/notify.mjs
OK syntax: packages/discord/src/rest.mjs
OK syntax: packages/discord/src/setspark.mjs
OK syntax: packages/discord/src/tools.mjs
OK syntax: packages/discord/src/web.mjs
OK syntax: packages/discord/bin/git-credential.mjs
OK syntax: packages/discord/extension/tools.mjs
OK syntax: packages/discord/tests/approvals.test.mjs
OK syntax: packages/discord/tests/authorize.test.mjs
OK syntax: packages/discord/tests/binding.test.mjs
OK syntax: packages/discord/tests/connector.test.mjs
OK syntax: packages/discord/tests/context.test.mjs
OK syntax: packages/discord/tests/engine.test.mjs
OK syntax: packages/discord/tests/fake-pi.mjs
OK syntax: packages/discord/tests/gateway.test.mjs
OK syntax: packages/discord/tests/git.test.mjs
OK syntax: packages/discord/tests/helpers.mjs
OK syntax: packages/discord/tests/journal.test.mjs
OK syntax: packages/discord/tests/notify.test.mjs
OK syntax: packages/discord/tests/recover.test.mjs
OK syntax: packages/discord/tests/rest.test.mjs
OK syntax: packages/discord/tests/setspark.test.mjs
OK syntax: packages/discord/tests/tools.test.mjs
OK syntax: packages/discord/tests/web.test.mjs
OK syntax: packages/discord/fixtures/claim-worker.mjs
OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs
OK syntax: scripts/discord.sh
OK syntax: scripts/discord-service.sh
OK packages/discord declares no dependencies
OK no bot-token-shaped string in packages/discord
OK fixture binding uses placeholder ids only
OK fixture binding validates
OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool
OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start
OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root
OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token
OK real pi with protocol vault adds reserve_id to the git verbs
OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key
OK real pi refuses a git key on a read-only root (fail closed)
OK real pi with the pilot flags (--no-tools) exposes no tool at all
OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed)
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
OK node --test packages/discord/tests/ (ℹ pass 178)
OK scripts/discord.sh --help exits 0
OK scripts/discord.sh check without a binding exits 4
OK scripts/discord.sh recover without a binding exits 4
OK scripts/discord.sh reload without a binding exits 4
OK scripts/discord-service.sh without a command exits 4
OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP
OK service install writes the rendered unit (0644) and leaves no temp file
OK service install a second time reports unchanged
OK systemd-analyze verify accepts the rendered unit
OK service uninstall removes the unit file
OK service install with an unknown flag exits 4
OK service install with USER unset finishes and names the account for lingering
discord suite: 66 passed, 0 failed
@@ -0,0 +1,21 @@
OK initial ordinary-file install
OK installed tree matches canonical source
OK installed tree has no symlinks
OK check detects installation drift
OK sync refuses to overwrite installation drift
OK check detects an extra destination file
OK check detects an extra destination directory
OK check rejects a destination symlink
OK sync accepts a canonical source update
OK updated installation matches canonical source
scripts/test-extension-package.sh: line 14: 955374 Killed "$@" > /dev/null 2>&1
OK forced interruption kills the replacing process
OK next invocation recovers old consistent installation
OK interrupted replacement rolled back
OK sync succeeds after interruption recovery
OK unlocked stale lock file does not block
OK active lock refuses a concurrent sync
OK source symlink fails closed
OK nested second entrypoint fails closed
extension package selftest: 18 passed, 0 failed
@@ -0,0 +1,53 @@
toolchain: node v26.8.1, python 3.12.8, jsonschema 4.26.0
OK syntax: scripts/foundation-inspect.mjs
OK syntax: scripts/foundation/strict-json.mjs
OK syntax: scripts/foundation/canonical.mjs
OK syntax: scripts/foundation/resolve.mjs
OK syntax: scripts/foundation/validate-record.mjs
OK syntax: scripts/foundation/fixtures/build-fixtures.mjs
OK syntax: scripts/foundation/canonical.test.mjs
OK syntax: scripts/foundation/cli.test.mjs
OK syntax: scripts/foundation/fixtures.test.mjs
OK syntax: scripts/foundation/resolve.test.mjs
OK syntax: scripts/foundation/strict-json.test.mjs
OK syntax: scripts/foundation/verify-schema.py (ast only; no bytecode written)
OK fixture generator runs
OK checked-in fixtures/bundles equal a fresh generation
OK checked-in fixtures/raw equal a fresh generation
OK checked-in fixtures/index.json equal a fresh generation
OK checked-in demo bundles equal a fresh generation
OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT
OK node --test scripts/foundation/ (ℹ pass 80)
OK differential schema oracle: PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof)
platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999)
node v26.8.1; corpus 1568 records (38 pinned fixtures, 478 unique bundle records, 1052 typeCase/mutation/lexical cases)
schema column: agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10
profile column (schema-valid records only): profile-valid 510, profile-invalid 30
profile refusals asserted: 30 schema-agreed-valid records refused only by the strict typed-string profile (rule profile-pattern-mismatch), 12 declared by name; 73 named probes verified against declared schema/profile columns
OK oracle: zero schema-column disagreements with the pinned checker
OK oracle: strict-only profile refusals are counted and asserted
OK demo: permitted read preview exits 0 (exit 0)
OK demo: permitted file.change preview exits 0 (exit 0)
OK demo: assignment.change proposal is unresolved (exit 3) (exit 3)
OK demo: revoked registration is refused (exit 3) (exit 3)
OK demo: message is not authority (exit 3) (exit 3)
OK usage: no arguments exits 2 (exit 2)
OK io: missing file exits 4 (exit 4)
OK io: directory exits 4 (exit 4)
OK io: symlink exits 4 (O_NOFOLLOW) (exit 4)
OK bound: oversize fixture exits 2 (exit 2)
OK profile: one final LF in a typed selection id is refused before admission (exit 2) (exit 2)
OK profile: two final LFs fail the schema pattern itself (exit 2) (exit 2)
OK profile: escaped newlines in free-form text stay allowed (exit 0) (exit 0)
OK profile refusal is invalid-request/profile-pattern-mismatch with selection and operation withheld, value not echoed
OK text output starts with the disclaimer
OK json output is valid JSON with result allowed and exactly the charter §7 fields
OK json golden matches byte-for-byte
OK sandboxed bundle run (env -i, PATH=/nonexistent) produced the unresolved proposal
OK sandbox inventory (path/type/size/mode/uid/gid/inode/mtime/sha256) unchanged by runs
OK canary never printed (bundle run and credential-file run)
OK a non-bundle JSON file is refused at the shape gate, not read into output
OK no field of the non-bundle file is echoed
selftest: 44 passed, 0 failed
@@ -0,0 +1,35 @@
toolchain: node v26.8.1, git version 2.55.0
OK syntax: packages/queue/src/cli.mjs
OK syntax: packages/queue/src/errors.mjs
OK syntax: packages/queue/src/io.mjs
OK syntax: packages/queue/src/lock.mjs
OK syntax: packages/queue/src/queue.mjs
OK syntax: packages/queue/src/review.mjs
OK syntax: packages/queue/src/store.mjs
OK syntax: packages/queue/tests/commit.test.mjs
OK syntax: packages/queue/tests/data.test.mjs
OK syntax: packages/queue/tests/dispatch.test.mjs
OK syntax: packages/queue/tests/helpers.mjs
OK syntax: packages/queue/tests/lock.test.mjs
OK syntax: packages/queue/tests/migration.test.mjs
OK syntax: packages/queue/tests/review.test.mjs
OK syntax: packages/queue/tests/store.test.mjs
OK syntax: packages/queue/tests/write.test.mjs
OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs
OK syntax: packages/queue/tests/fixtures/kill-at.mjs
OK syntax: packages/queue/tests/fixtures/lock-child.mjs
OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh
OK syntax: scripts/queue-commit.sh
OK syntax: scripts/git-hooks/pre-commit
OK syntax: scripts/mosaic
OK queue-commit.sh, the guard and scripts/mosaic are executable
OK packages/queue declares no dependencies
ℹ tests 150
ℹ pass 150
ℹ fail 0
OK node --test packages/queue/tests/
OK scripts/mosaic queue help
skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack/.claude/worktrees/agent-a44468a48c485520e) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
queue suite: 27 passed, 0 failed
@@ -0,0 +1,16 @@
OK valid RELEASE resolves (exit 0)
OK invalid RELEASE exits 1 (exit 1)
OK missing RELEASE exits 1 (exit 1)
OK valid RELEASE leaves image tag consistent with version
OK status safe on empty state (exit 0)
OK status created no pointer
OK fault-injected activation refuses (exit 1)
OK refused activation wrote no pointer
OK refusal logged exactly once with valid fields
OK healthy activation succeeds (exit 0)
OK pointer written with valid fields
OK repeat activation succeeds (log grows) (exit 0)
OK log is append-only across activations
OK rollback without previous refuses (exit 1)
selftest: 14 passed, 0 failed
@@ -0,0 +1,32 @@
OK valid task validates (exit 0)
OK unknown task key exits 2 (exit 2)
OK unsupported taskVersion exits 2 (exit 2)
OK invalid task id exits 2 (exit 2)
OK empty prompt exits 2 (exit 2)
OK NUL in expectExact exits 2 (exit 2)
OK out-of-range timeout exits 2 (exit 2)
OK missing mission file exits 4 (exit 4)
OK task with valid mission validates (exit 0)
OK invalid mission exits 2 (exit 2)
OK validate missing task exits 4 (exit 4)
OK validation does not modify the task file
OK prune dry-run exits 0 (exit 0)
OK dry-run deleted nothing
OK prune --keep=2 --yes removes oldest (exit 0)
OK kept exactly 2 newest runs
OK newest run kept, oldest pruned
OK append-only receipt written (3 entries)
OK sessions/workspaces untouched by prune
OK prune with invalid keep exits 4 (exit 4)
skip adapter seam cases (docker daemon unavailable)
skip workspace/capability cases (docker daemon unavailable)
skip live task cases (docker unavailable)
OK onboard without name exits 4 (non-interactive) (exit 4)
OK onboard --name renders profile (exit 0)
OK profile written
OK canon structure: required filled, optional placeholdered
OK canon sections present
skip live recall pair: user recall run, recalled user name (docker daemon unavailable)
OK no agent identity on headless run
selftest: 26 passed, 0 failed
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""Run one command in its own session and process group, with a timeout.
usage: run_group.py TIMEOUT_S LOGFILE CWD -- CMD [ARGS...]
Child stdout and stderr go to LOGFILE. On timeout the whole process group gets
SIGTERM, then SIGKILL after 5 s. After the child exits, anything still left in
its group is killed too, so nothing from one step outlives it.
Exit status: the child's, or 124 on timeout.
"""
import os
import signal
import subprocess
import sys
def group_kill(pgid, sig):
try:
os.killpg(pgid, sig)
except ProcessLookupError:
pass
def main():
timeout = float(sys.argv[1])
log = sys.argv[2]
cwd = sys.argv[3]
cmd = sys.argv[sys.argv.index('--') + 1:]
with open(log, 'w') as out:
p = subprocess.Popen(
cmd,
cwd=cwd,
stdout=out,
stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL,
start_new_session=True,
)
try:
rc = p.wait(timeout=timeout)
except subprocess.TimeoutExpired:
group_kill(p.pid, signal.SIGTERM)
try:
p.wait(timeout=5)
except subprocess.TimeoutExpired:
pass
group_kill(p.pid, signal.SIGKILL)
p.wait()
out.write(f"\nTIMEOUT after {timeout:.0f}s: process group {p.pid} killed\n")
rc = 124
group_kill(p.pid, signal.SIGKILL)
sys.exit(rc)
if __name__ == '__main__':
main()