agents: Dewey row 151 round 1 packet, launch-notice routing and talk waiting/reply tests (#1645)
Candidate on 686fc1cb6: candidate-manifest.sha256 cb831847...78ed, 2 test files, +44.
Mutants 4/4 killed; owner's gate rc 0 (bus 265, cli 213, every scripts/test-*.sh).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
dfe7df1cac
commit
20c0ee1c6f
26 files changed
+1505
No files matched your search
@@ -0,0 +1,111 @@
|
||||
# Row 151 (#1645): tests pin where a launch notice is routed and how talk prints it with a reply
|
||||
|
||||
Builder: Dewey. Reviewer: Filbert. Gate owner: Sage.
|
||||
Brief: docs/plans/2026-10-15_landing-followups.md, the first `##` section (blob 4e620d79, commit
|
||||
c66c7fb71). Assignment: sage-0454. Sources: Filbert's row 146 round 1 review, note 1 and mutant M1
|
||||
(comment 28641), and the row 142 round 3 hand probe the brief describes.
|
||||
|
||||
Base: 686fc1cb6 (base.txt, origin/refactor after rows 136 and 147). The candidate is build.patch on that
|
||||
base, and candidate-manifest.sha256 lists both changed paths with their sha256. repro.sh applies the
|
||||
patch to a fresh detached worktree and checks the digests; it printed DIGESTS_OK.
|
||||
|
||||
Built on 02ee7f640 (after row 142). Row 136 landed as d8487b3af and changed packages/bus/src/broker.mjs
|
||||
under the launch-notice test, and none of this row's paths. Per sage-0463 the worktree moved to
|
||||
d8487b3af: the patch applied with no change to either file, the manifest digests are the same, and
|
||||
repro.sh on the new base printed DIGESTS_OK.
|
||||
Row 147 then landed as 686fc1cb6. Sage's check (`git diff --name-only 02ee7f640 686fc1cb6` on the two
|
||||
test files, sage-0467) printed nothing, so the base could have stayed. But row 147 changed
|
||||
packages/cli/src/cli.mjs, the file C1 to C3 mutate and verbs runs, so I moved to 686fc1cb6 so that
|
||||
the mutants and the gate run on the cli.mjs that lands. The patch and the digests are unchanged
|
||||
again, each mutant target still occurs once, and repro.sh printed DIGESTS_OK.
|
||||
|
||||
## The change
|
||||
|
||||
Test-only: no product code changes. The two files the brief names, +44 lines, nothing removed.
|
||||
|
||||
- **packages/bus/tests/launch-notice.test.mjs**, test 1. After the second send (human to coder) with
|
||||
chief, launch.by, running, the latest notice's `routed` delivery has `holder_run` equal to
|
||||
`chief-run`. The test already asserted a null holder for the first notice, sent while chief was
|
||||
stopped. message.receive selects on `to_role`, so chief still receives a notice routed elsewhere.
|
||||
This row's `routed` delivery is the only place the routing shows, and it's the row the Console's
|
||||
waiting lists read.
|
||||
- **packages/cli/tests/verbs.test.mjs**, a new test, "talk to a stopped role prints the waiting line
|
||||
once, skips a non-reply and prints the reply". The business's launch block names pm as launch.by,
|
||||
and pm runs. `talk cto` with `--wait 5` goes to cto, which has no session. A transport wrapper
|
||||
injects the other side. On poll 1, pm sends the human an INFO note, "launching cto". On poll 2, cto
|
||||
is launched and claims, receives the waiting message and replies with RESULT in_reply_to it.
|
||||
Assertions:
|
||||
- exit 0;
|
||||
- the whole stdout equals `sent <id> to cto`, then `cto isn't running, pm has been told`, then the
|
||||
reply, so the waiting line prints once, the note doesn't print, and nothing else prints;
|
||||
- polls is 2, so the note did arrive before the reply;
|
||||
- message.read was called once, for the reply's id;
|
||||
- `mosaic inbox` then shows 1 unread, pm's note.
|
||||
|
||||
This is the case Filbert probed by hand on the row 142 candidate. Row 146's talk test uses
|
||||
`--wait 0`, which never polls. Row 142's tests talk to coder, which runs, so they never print a
|
||||
waiting line.
|
||||
|
||||
### Choices
|
||||
|
||||
- **The non-reply comes from launch.by (pm), not from the target.** That is the message a human
|
||||
is likely to get first when a stopped role is launched. Row 142's test already covers an
|
||||
unsolicited note from the target role itself.
|
||||
- **Exact stdout instead of separate matches.** One equality pins the order (sent, waiting line,
|
||||
reply), says the waiting line prints once, and says the note never prints. Separate matches would
|
||||
each need a count.
|
||||
- **C3, a mutant beyond the brief's two.** The brief says the waiting line prints once. C3 prints it
|
||||
again on every receive poll, so the "once" has a mutant of its own.
|
||||
|
||||
## Mutants
|
||||
|
||||
mutants.py applies one fault at a time, runs the owning test file with the spec reporter, and
|
||||
restores the source after each one. Run 2026-10-16T00:13:46Z to 00:13:59Z on 686fc1cb6 plus the
|
||||
candidate, in the sage-0470 slot: 4 of 4 killed, `restored True` (mutants-run.log, logs in mutants/).
|
||||
|
||||
| Mutant | Fault | Runs | Result | Failing tests |
|
||||
|---|---|---|---|---|
|
||||
| B1-notice-routed-to-target | Filbert's row 146 M1: `#notice` routes to `to`, not `by` | bus launch-notice | KILLED | test 1, at the new assertion (line 97: actual null, expected `chief-run`). Nothing else fails, so this assertion is the only thing holding it, as Filbert found. |
|
||||
| C1-no-reply-filter | talk drops row 142's `m.in_reply_to !== sent.id` skip | cli verbs | KILLED | the new test; row 142's two talk tests |
|
||||
| C2-no-waiting-lines | talk drops row 146's `waitingLines` write | cli verbs | KILLED | the new test; row 146's talk test |
|
||||
| C3-waiting-every-poll | talk writes the waiting line on every receive poll | cli verbs | KILLED | the new test only |
|
||||
|
||||
C1 and C2 were already killed by the row 142 and row 146 tests. The new test adds what neither
|
||||
had: both paths in one talk, plus the "once" that only C3 checks.
|
||||
|
||||
## Receipts
|
||||
|
||||
Single files on the candidate, without the slot, TMPDIR in my scratch, 0 fail and 0 skipped:
|
||||
|
||||
- on 02ee7f640: bus launch-notice 7/7, cli verbs 8/8;
|
||||
- on d8487b3af, 2026-10-16T00:05:44Z to 00:05:48Z: bus launch-notice 7/7, cli verbs 8/8. B1's target
|
||||
string still occurs once in broker.mjs.
|
||||
- on 686fc1cb6, 2026-10-16T00:12:33Z to 00:12:38Z: bus launch-notice 7/7, cli verbs 8/8.
|
||||
|
||||
Slot granted by Sage in sage-0470 (00:13:38Z).
|
||||
|
||||
- **Mutants**, 00:13:46Z to 00:13:59Z: 4 of 4 killed, source restored. See the kill table above.
|
||||
- **Gate**, gate.sh from ~/dewey-scratch/r151 on 686fc1cb6, 2026-10-16T00:14:06Z to 00:16:58Z,
|
||||
exit 0 (gate-run.log, logs under gate/). It covers the bus and cli suites and every
|
||||
scripts/test-*.sh, as the brief's gate names them:
|
||||
|
||||
| Step | Result |
|
||||
|---|---|
|
||||
| bus | 265 pass, 0 fail |
|
||||
| cli | 213 pass, 0 fail |
|
||||
| test-auth | 15 passed, 0 failed |
|
||||
| test-conductor | 17 passed, 0 failed |
|
||||
| test-config | 24 passed, 0 failed |
|
||||
| test-discord | 78 passed, 0 failed |
|
||||
| test-extension-package | 18 passed, 0 failed |
|
||||
| test-foundation | 44 passed, 0 failed |
|
||||
| test-land-work | 84 passed, 0 failed |
|
||||
| test-queue | 28 passed, 0 failed |
|
||||
| test-release | 14 passed, 0 failed |
|
||||
| test-task | 98 passed, 0 failed |
|
||||
|
||||
No recurrence of flakes #258, #261, #262 or #263. gate.sh exports
|
||||
`COMPOSE_PROJECT_NAME=dewey-r151`, and its EXIT trap printed `removed network
|
||||
dewey-r151_default`. Afterwards no network named dewey* or wt* exists.
|
||||
- **Candidate:** candidate-manifest.sha256, sha256
|
||||
cb831847239e9ea60bd77ed8c765dafbf607a03cadeed3d0fc8d8284846878ed, 2 files.
|
||||
@@ -0,0 +1 @@
|
||||
686fc1cb6d4ce77a441b2953aa09dfc441ce9a39
|
||||
@@ -0,0 +1,66 @@
|
||||
diff --git a/packages/bus/tests/launch-notice.test.mjs b/packages/bus/tests/launch-notice.test.mjs
|
||||
index 3ac83e702..0bf1703a2 100644
|
||||
--- a/packages/bus/tests/launch-notice.test.mjs
|
||||
+++ b/packages/bus/tests/launch-notice.test.mjs
|
||||
@@ -92,6 +92,12 @@ test('a message to a stopped role sends launch.by one notice, and the result say
|
||||
launcherRunning: true,
|
||||
});
|
||||
assert.equal(ctx.notices().length, 2);
|
||||
+ // Row 151 (#1645): the notice is routed to launch.by's holder, which the Console's waiting lists read.
|
||||
+ // message.receive selects on to_role, so only this row shows a notice routed anywhere else.
|
||||
+ assert.equal(
|
||||
+ ctx.store().get("SELECT holder_run FROM deliveries WHERE message=? AND op='routed'", ctx.notices().at(-1).id).holder_run,
|
||||
+ 'chief-run',
|
||||
+ );
|
||||
// A role's message to a stopped role tells launch.by too.
|
||||
ctx.launch('coder', 'coder');
|
||||
ctx.claim('coder');
|
||||
diff --git a/packages/cli/tests/verbs.test.mjs b/packages/cli/tests/verbs.test.mjs
|
||||
index f29922e0e..c9d0b9d17 100644
|
||||
--- a/packages/cli/tests/verbs.test.mjs
|
||||
+++ b/packages/cli/tests/verbs.test.mjs
|
||||
@@ -118,6 +118,44 @@ test("talk says when the role isn't running, whether launch.by was told, and how
|
||||
assert.equal(await text(s, "coder"), "");
|
||||
});
|
||||
|
||||
+// Row 151 (#1645): rows 146 and 142 in one talk. The waiting line prints once after "sent", a
|
||||
+// message that isn't the reply arrives first and stays unread, then the reply prints and talk exits 0.
|
||||
+test("talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply", async (t) => {
|
||||
+ const s = setup(t, {}, { demo: { ...BUSINESSES.demo, launch: { by: "pm", instances: ["cto", "coder"], models: {}, limits: {} } } });
|
||||
+ const pm = s.b.bindLaunch({ business: "demo", role: "pm", run: "pm-run", harness: "pi" });
|
||||
+ call(s.b, pm, "role.claim");
|
||||
+ // pm's note arrives on the first poll; cto comes up and answers on the second.
|
||||
+ let polls = 0;
|
||||
+ let note;
|
||||
+ let reply;
|
||||
+ const transport = (business) => {
|
||||
+ const inner = s.transport(business);
|
||||
+ return async (verb, args) => {
|
||||
+ if (verb === "message.receive" && ++polls === 1) note = call(s.b, pm, "message.send", { to: "human", body: "launching cto", class: "INFO" });
|
||||
+ if (verb === "message.receive" && polls === 2) {
|
||||
+ const cto = s.b.bindLaunch({ business: "demo", role: "cto", run: "cto-run", harness: "pi" });
|
||||
+ call(s.b, cto, "role.claim");
|
||||
+ const [m] = call(s.b, cto, "message.receive");
|
||||
+ reply = call(s.b, cto, "message.send", { to: m.from_role, body: "on it", class: "RESULT", in_reply_to: m.id });
|
||||
+ }
|
||||
+ return inner(verb, args);
|
||||
+ };
|
||||
+ };
|
||||
+ const r = await s.run(["talk", "cto", "review the plan", "--wait", "5", "--business", "demo"], io(), { transport });
|
||||
+ assert.equal(r.code, 0, r.error);
|
||||
+ const sent = s.store.get("SELECT id FROM messages WHERE from_role='human' ORDER BY seq DESC LIMIT 1");
|
||||
+ assert.equal(
|
||||
+ r.io.out.text,
|
||||
+ `sent ${sent.id.slice(0, 8)} to cto\ncto isn't running, pm has been told\ncto (RESULT, re ${sent.id.slice(0, 8)}) ${reply.id.slice(0, 8)}:\non it\n`,
|
||||
+ );
|
||||
+ assert.equal(polls, 2, "the note came first");
|
||||
+ assert.deepEqual(s.calls.filter((c) => c.verb === "message.read").map((c) => c.args.id), [reply.id], "only the reply was marked read");
|
||||
+ const inbox = io();
|
||||
+ await main(["inbox", "--business", "demo"], inbox, { system: { dataRoot: s.dataRoot }, transport: s.transport });
|
||||
+ assert.match(inbox.out.text, /messages: 1 unread\n/);
|
||||
+ assert.match(inbox.out.text, new RegExp(`pm \\(INFO\\) ${note.id.slice(0, 8)}:\nlaunching cto\n`));
|
||||
+});
|
||||
+
|
||||
test("talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors", async (t) => {
|
||||
const s = setup(t);
|
||||
const agent = () => io({ ...io().env, CLAUDECODE: "1" });
|
||||
@@ -0,0 +1,2 @@
|
||||
eb496122a8aa58ca8c3b63ec0c77ebe28654828f090add98ea723cdcf0ca29ca packages/bus/tests/launch-notice.test.mjs
|
||||
756e2e733a96aed0d9050ae6096f1176ee84de7b0bdf73765842110ecc60c4ad packages/cli/tests/verbs.test.mjs
|
||||
@@ -0,0 +1,15 @@
|
||||
gate start 2026-10-16T00:14:06Z
|
||||
pkg-bus start=2026-10-16T00:14:06Z end=2026-10-16T00:14:18Z rc=0 tests=265 pass=265 fail=0 skipped=0
|
||||
pkg-cli start=2026-10-16T00:14:18Z end=2026-10-16T00:14:38Z rc=0 tests=213 pass=213 fail=0 skipped=0
|
||||
test-auth start=2026-10-16T00:14:38Z end=2026-10-16T00:14:38Z rc=0
|
||||
test-conductor start=2026-10-16T00:14:38Z end=2026-10-16T00:14:44Z rc=0
|
||||
test-config start=2026-10-16T00:14:44Z end=2026-10-16T00:14:46Z rc=0
|
||||
test-discord start=2026-10-16T00:14:46Z end=2026-10-16T00:14:52Z rc=0
|
||||
test-extension-package start=2026-10-16T00:14:52Z end=2026-10-16T00:14:54Z rc=0
|
||||
test-foundation start=2026-10-16T00:14:54Z end=2026-10-16T00:15:32Z rc=0
|
||||
test-land-work start=2026-10-16T00:15:32Z end=2026-10-16T00:15:44Z rc=0
|
||||
test-queue start=2026-10-16T00:15:44Z end=2026-10-16T00:16:15Z rc=0
|
||||
test-release start=2026-10-16T00:16:15Z end=2026-10-16T00:16:24Z rc=0
|
||||
test-task start=2026-10-16T00:16:24Z end=2026-10-16T00:16:58Z rc=0
|
||||
removed network dewey-r151_default
|
||||
gate end 2026-10-16T00:16:58Z rc=0
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Row 151 owner's gate (sage-0454): the bus and cli suites and every scripts/test-*.sh, on base.txt plus
|
||||
# build.patch. One log per step under gate/.
|
||||
set -uo pipefail
|
||||
WT=${1:-$HOME/dewey-scratch/r151/wt}
|
||||
OUT=$(cd "$(dirname "$0")" && pwd)/gate
|
||||
mkdir -p "$OUT"
|
||||
export TMPDIR=$HOME/dewey-scratch/tmp
|
||||
# test-task.sh's live cases run `docker compose run` from $WT (mosaic-task.mjs passes its env through).
|
||||
# An explicit project name keeps them off the dir-named `wt` project; its network goes at exit (Mos, sage-0447).
|
||||
export COMPOSE_PROJECT_NAME=dewey-r151
|
||||
trap 'docker network rm "${COMPOSE_PROJECT_NAME}_default" >/dev/null 2>&1 && echo "removed network ${COMPOSE_PROJECT_NAME}_default"' EXIT
|
||||
status=0
|
||||
for p in bus cli; do
|
||||
start=$(date -u +%FT%TZ)
|
||||
(cd "$WT/packages/$p" && node --test tests/*.test.mjs) >"$OUT/pkg-$p.log" 2>&1
|
||||
rc=$?
|
||||
counts=$(grep -E '^ℹ (tests|pass|fail|skipped) ' "$OUT/pkg-$p.log" | awk '{printf "%s=%s ", $2, $3}')
|
||||
echo "pkg-$p start=$start end=$(date -u +%FT%TZ) rc=$rc $counts"
|
||||
[ "$rc" -eq 0 ] || status=1
|
||||
done
|
||||
for s in "$WT"/scripts/test-*.sh; do
|
||||
n=$(basename "$s" .sh)
|
||||
start=$(date -u +%FT%TZ)
|
||||
(cd "$WT" && bash "scripts/$n.sh") >"$OUT/$n.log" 2>&1
|
||||
rc=$?
|
||||
echo "$n start=$start end=$(date -u +%FT%TZ) rc=$rc"
|
||||
[ "$rc" -eq 0 ] || status=1
|
||||
done
|
||||
exit $status
|
||||
@@ -0,0 +1,273 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (120.337424ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (236.10335ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (342.028896ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (180.930349ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (223.304101ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (205.720718ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (209.298105ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (241.989695ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (1122.622583ms)
|
||||
✔ agents: stranded is per role and per business (396.325154ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (164.490172ms)
|
||||
✔ REQ-DEC an approval outlives its run and a broker restart; a new run of the instance consumes it once (296.676593ms)
|
||||
✔ REQ-DEC another instance of the same definition cannot consume an approval, and its refusal consumes nothing (190.537558ms)
|
||||
✔ REQ-DEC REQ-THREAD-1 a thread approval is consumed only by a run holding the same thread (290.461762ms)
|
||||
✔ REQ-DEC a later run of the same instance supersedes an open decision; another instance cannot (253.973049ms)
|
||||
✔ REQ-DEC REQ-THREAD-1 a thread decision is superseded only from the same thread (294.597641ms)
|
||||
✔ REQ-DEC REQ-THREAD-1 a thread instance decision raised before row 121 is not consumed or superseded by any thread run (366.320044ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (182.76576ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (298.785483ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (300.483364ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (175.652242ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (203.826509ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (280.006595ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (191.264372ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (203.618744ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (120.583386ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (313.709529ms)
|
||||
✔ authority never transfers between action, target, unresolved or replaced role holder; a later run of the instance keeps it (368.749769ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (177.383849ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (246.164487ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (192.003233ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (296.80443ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (222.040456ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (2.274531ms)
|
||||
✔ REQ-COS-1, REQ-ROLE-2: the chief of staff ends a run with a reason and no decision, and the reason is logged (286.982142ms)
|
||||
✔ REQ-ROLE-2: a role without role.end still needs a resolved decision to revoke (338.032958ms)
|
||||
✔ REQ-ROLE-2: storage accepts a revoke with a reason or a decision and aborts one with neither (256.453408ms)
|
||||
✔ REQ-ROLE-2: the chief of staff may still cite a decision, and a decision alone is the old path (256.035535ms)
|
||||
✔ REQ-ROLE-2: a role without role.end still ends a run through a resolved decision, which is recorded and has no reason (271.429837ms)
|
||||
✔ REQ-ROLE-2: a reason is required, bounded, and never sent with a decision (328.095175ms)
|
||||
✔ REQ-COS-1: the chief of staff cannot end its own run or the assistant's through role.end (269.925519ms)
|
||||
✔ REQ-LIMIT-1, REQ-COS-1: organization.set from the chief of staff reaches the shared writer, named as the actor (411.936337ms)
|
||||
✔ REQ-LIMIT-1, REQ-COS-1: a refused organization.set logs action.refused and no action.allowed, like a refused limits.set (373.954576ms)
|
||||
✔ REQ-LIMIT-1: organization.set is refused for every caller whose role file lacks organization.change (338.94336ms)
|
||||
✔ REQ-LIMIT-1: the chief of staff is logged as allowed, and organization.set takes only the human's keys (472.604423ms)
|
||||
✔ REQ-ROLE-3, REQ-LIMIT-1: a chief-of-staff change is validated, written and logged like a human's; an invalid one is refused (657.472064ms)
|
||||
✔ REQ-ROLE-2, REQ-COS-1: the 3c→3d migration lets the chief of staff end a held role with a reason; neither is still refused (1007.735632ms)
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (136.063226ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (137.232948ms)
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3e; normal startup never migrates (894.789636ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (1782.994497ms)
|
||||
✔ named migration registry chains 3b through 3e to a fixture-only future version in order (925.447555ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (1008.069346ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (930.053437ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (105.730174ms)
|
||||
✔ credentials refuses a role session and any argument (192.643933ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (235.190218ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (220.079688ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (4.916867ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (2.662913ms)
|
||||
✔ expiry refuses use and env references never become client data (0.840564ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (1.948585ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.604049ms)
|
||||
✔ each C-suite role file carries the same two lists: human, chief-of-staff, pm, cto (2.51994ms)
|
||||
✔ chief-executive-officer: messages to and from the user, chief of staff, pm and cto pass (516.83888ms)
|
||||
✔ chief-executive-officer: a message to or from the coder, reviewer or assistant is refused and logged, and nothing is stored (483.993628ms)
|
||||
✔ chief-executive-officer: another C-suite role isn't on the lists either (425.952182ms)
|
||||
✔ chief-financial-officer: messages to and from the user, chief of staff, pm and cto pass (499.059434ms)
|
||||
✔ chief-financial-officer: a message to or from the coder, reviewer or assistant is refused and logged, and nothing is stored (645.148748ms)
|
||||
✔ chief-financial-officer: another C-suite role isn't on the lists either (458.600784ms)
|
||||
✔ chief-information-officer: messages to and from the user, chief of staff, pm and cto pass (569.870542ms)
|
||||
✔ chief-information-officer: a message to or from the coder, reviewer or assistant is refused and logged, and nothing is stored (557.729033ms)
|
||||
✔ chief-information-officer: another C-suite role isn't on the lists either (523.990355ms)
|
||||
✔ chief-information-security-officer: messages to and from the user, chief of staff, pm and cto pass (528.301878ms)
|
||||
✔ chief-information-security-officer: a message to or from the coder, reviewer or assistant is refused and logged, and nothing is stored (474.362384ms)
|
||||
✔ chief-information-security-officer: another C-suite role isn't on the lists either (386.660934ms)
|
||||
✔ chief-marketing-officer: messages to and from the user, chief of staff, pm and cto pass (439.922413ms)
|
||||
✔ chief-marketing-officer: a message to or from the coder, reviewer or assistant is refused and logged, and nothing is stored (433.00763ms)
|
||||
✔ chief-marketing-officer: another C-suite role isn't on the lists either (448.849809ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (275.202245ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (239.138701ms)
|
||||
✔ a human withdraw sends one message with the note (254.274775ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (307.309098ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (301.815534ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (316.760762ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (269.887201ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (370.36077ms)
|
||||
✔ a cross-role raise whose arbiter the raiser does not hear from is refused and stores nothing (331.483097ms)
|
||||
✔ a gated raise by a role that does not hear from the human is refused and stores nothing (297.997392ms)
|
||||
✔ a route the raiser hears from is allowed, checked from the route to the raiser (376.700152ms)
|
||||
✔ a refused supersede withdraws nothing (327.237208ms)
|
||||
✔ the assistant's within-role and gated raises still work (319.708622ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (254.514555ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (300.145587ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (319.232461ms)
|
||||
✔ recent stops at RECENT rows (878.606728ms)
|
||||
✔ every row is what trail already gives the same session for that id (279.88558ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (617.925294ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (453.330153ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (152.535099ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (167.064819ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (153.524761ms)
|
||||
✔ endLaunch leaves a claim another run took alone (188.146227ms)
|
||||
✔ refuse records action.refused against the caller with the code only (143.165399ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (199.023043ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (340.400628ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (1.602623ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.489221ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.635023ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.257571ms)
|
||||
✔ a message to a stopped role sends launch.by one notice, and the result says so (238.034723ms)
|
||||
✔ a message to a running role sends no notice and its result is unchanged (148.150794ms)
|
||||
✔ a re-route at a claim, a release and claim, and a broker restart send no second notice (253.269261ms)
|
||||
✔ a run launched but not yet claimed counts as no holder (153.33514ms)
|
||||
✔ no notice for a message to launch.by, from it, from a tester, to the human, or in a thread to a thread instance (280.313936ms)
|
||||
✔ a business with no launch block tells nobody and says there is no launcher (137.558758ms)
|
||||
✔ the notice sender stays internal: no role is named _bus and no caller can send as it or to it (388.938786ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (243.910901ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (286.135801ms)
|
||||
✔ uncertain organization receipts leave bus startup and reads alone but refuse writes until reconciled (436.848255ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (238.332908ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (187.159ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (267.719117ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (2952.676963ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (299.045227ms)
|
||||
✔ views messages passes only its paging arguments through (0.270901ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (203.491166ms)
|
||||
✔ the assistant sends to the user and to the chief of staff only (334.867872ms)
|
||||
✔ an assistant send to any other role, or to the tester, is refused and logged (390.930871ms)
|
||||
✔ only the user and the chief of staff may send to the assistant; the tester is refused by default (381.659241ms)
|
||||
✔ REQ-ASSIST-2 REQ-THREAD-1 thread.send to an instance that does not hear from the user is refused and stores nothing (445.456355ms)
|
||||
✔ a sender-side list alone refuses a send to a role that has no list (438.419302ms)
|
||||
✔ a target-side list alone refuses a send from a role that has no list (388.876484ms)
|
||||
✔ the sender list is checked before the target list (361.902135ms)
|
||||
✔ roles without the field behave exactly as before (529.37908ms)
|
||||
✔ a business with no role definitions at all is unlimited (453.833005ms)
|
||||
✔ a malformed messaging field refuses at boot (121.869077ms)
|
||||
✔ the assistant's review.request to a reviewer is refused and logged, even with an approved decision (378.981644ms)
|
||||
✔ a review.verdict to the assistant from a role outside its receiveFrom is refused and logged (425.972925ms)
|
||||
✔ review requests and verdicts between roles without the field are unchanged (343.142962ms)
|
||||
✔ plugins and plugins.set refuse every non-human session and a forged actor, and pass only the patch with the verified actor (211.476438ms)
|
||||
✔ runtime: the switch changes the organization file, the receipt carries the actor, and a bad shape, an unknown module and a stale revision are refused with nothing written (511.682538ms)
|
||||
✔ vikunja:19/309 through the broker, a patch switches the kinds it names and keeps the rest; null removes one kind and is trailed (438.708873ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (233.721972ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (63.614037ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (220.861017ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (242.677472ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (263.582196ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (60.064915ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (246.238924ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (259.627384ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (199.460571ms)
|
||||
✔ a message with no reply gives an empty list (219.836853ms)
|
||||
✔ replies come oldest first and stop at REPLIES (978.858185ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (356.703793ms)
|
||||
✔ strict arguments; a role session gets human-required (459.820447ms)
|
||||
✔ views passes replies through as one call with the id (0.239939ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (216.079867ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (205.348646ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (267.883134ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (241.624182ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (369.673343ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (390.924564ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (418.497977ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (271.586155ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (381.240433ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (492.527486ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (347.461728ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (1818.734793ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (427.878971ms)
|
||||
✔ another run of the same instance consumes an approval once; a failed check leaves it usable (252.424739ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (186.454692ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (379.024988ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (268.98431ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (309.009736ms)
|
||||
✔ class drift gated to within-role refuses before consumption (288.833621ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (360.25217ms)
|
||||
✔ class drift within-role to gated refuses before consumption (255.711236ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (237.629154ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (256.929027ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (274.916425ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (183.938801ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (187.34609ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (163.713081ms)
|
||||
✔ a tombstone is not open (157.647915ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (179.260281ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (164.606129ms)
|
||||
✔ a human session reads the same state, with the same cap (203.412287ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (185.493496ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (156.845554ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (210.599099ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (198.188117ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (189.916588ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (122.783855ms)
|
||||
✔ async transactions refuse before invoking their function (100.583117ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (349.0754ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (268.084897ms)
|
||||
✔ each filter, alone and together, and total counts every match (367.669581ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (343.789627ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (318.772374ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (1067.819115ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (365.230926ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (403.313319ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (177.887673ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (229.065081ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (127.751567ms)
|
||||
✔ a bad entry refuses the whole record (123.958861ms)
|
||||
✔ taskView reads the projection for one business (162.579452ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (355.111458ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (435.370416ms)
|
||||
✔ without an adapter the server refuses every task verb (235.424712ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (232.972038ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (335.109654ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (1046.358063ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (283.159515ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (603.8502ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (248.744456ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (264.45102ms)
|
||||
✔ the tester reads the human views a reader reads (169.204384ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.123755ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.327183ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.190133ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (112.53608ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (903.690894ms)
|
||||
✔ REQ-THREAD-1 REQ-ORG-2: the 3d→3e migration adds the thread tables and leaves messages from before threads as written (1216.625423ms)
|
||||
✔ REQ-THREAD-1: a 3d bus with a changed schema is refused and keeps its version and tables (872.609043ms)
|
||||
✔ REQ-THREAD-1: the offline command prints the kept-message counts before the ready line (849.912089ms)
|
||||
✔ REQ-ROLE-2 REQ-THREAD-1: one holder per thread, through the broker and the trigger (401.551652ms)
|
||||
✔ REQ-ROLE-2 REQ-THREAD-1: the 3e triggers refuse writes that skip the broker (1341.154433ms)
|
||||
✔ REQ-MSG-1: a message to or from the assistant names its thread, or is refused (352.38586ms)
|
||||
✔ REQ-MSG-1: the chief of staff's reply comes back to the thread that sent the work (3958.521652ms)
|
||||
✔ REQ-MSG-1: a reply can't carry one thread instance's thread to another thread instance (106.105684ms)
|
||||
✔ REQ-THREAD-1 REQ-USER-2: one thread's messages never reach another thread's holder (155.408372ms)
|
||||
✔ REQ-LAUNCH-1: a message to a thread with no holder waits, and the next holder gets it (174.541422ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1: threadIdle releases only a thread with nothing waiting, and only for its holder (181.78263ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1: a message delivered to a run that ended unread doesn't hold up the next holder (173.949515ms)
|
||||
✔ REQ-ROLE-2 REQ-THREAD-1: an approved role.revoke never reaches a thread run, and the thread stays held (302.747585ms)
|
||||
✔ REQ-USER-2: the human verbs refuse another owner's thread (156.068023ms)
|
||||
✔ REQ-THREAD-1: thread.create refuses when the business has no thread instance or more than one (114.110125ms)
|
||||
✔ REQ-ORG-2: projects and threads are named once, and the repo names a business project (148.454449ms)
|
||||
✔ REQ-THREAD-2: thread.messages returns the thread's history in pages and writes nothing (463.777514ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (177.455282ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (259.058602ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (167.07144ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (10.820041ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (174.81851ms)
|
||||
✔ web.search: a granted role gets labelled results, and the call is trailed with role, run, verb and query (218.752174ms)
|
||||
✔ web.fetch: a granted role gets the page as labelled text, and the call is trailed with the url (200.729373ms)
|
||||
✔ a role without the grant is refused, the refusal is logged with the verb, and nothing is fetched (283.400395ms)
|
||||
✔ a broker with no web service refuses a granted role (154.063919ms)
|
||||
✔ bad requests are refused: unknown verb, extra or missing argument, not a string, a human or reader session (232.461615ms)
|
||||
✔ a session that is not the role holder is refused (126.999869ms)
|
||||
✔ web.mjs's fences hold on the broker side: refusals are normal results with the fixed reason (438.097711ms)
|
||||
✔ web.search with no search source configured is a refused result, not an error (149.946357ms)
|
||||
✔ a search source that fails with its own refusal, or that throws, is handled (180.076413ms)
|
||||
✔ a slow search source ends in a refusal at the deadline (187.188926ms)
|
||||
✔ a secret in the arguments is refused before anything is trailed or fetched (121.075396ms)
|
||||
✔ over the socket: the server routes web verbs to the service; other roles are refused; no service is web-not-configured (238.296211ms)
|
||||
✔ busBusiness: the web grant comes from "web" in the resolved tool limit (0.25467ms)
|
||||
✔ webServices: the business's search-source plug-in and web.searxng var make web.search work; without either it is refused as not configured (232.358448ms)
|
||||
✔ an ungranted call is refused at once: no admission, no wait, nothing touched (168.10247ms)
|
||||
✔ over the socket an ungranted caller is dropped by the server timeout and a granted one gets the longer wait (470.89933ms)
|
||||
✔ a search that never answers is aborted at the deadline, the module sees the signal, and the call is trailed as refused (timeout) (236.773852ms)
|
||||
✔ a fetch that stalls is cut off at the deadline: the request is destroyed, not left running (230.319161ms)
|
||||
✔ one query limit: over SEARCH_MAX_QUERY_CHARS or empty is refused with the same reason before any backend, and the tool schema carries the same number (170.899761ms)
|
||||
ℹ tests 265
|
||||
ℹ suites 0
|
||||
ℹ pass 265
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 11950.614617
|
||||
@@ -0,0 +1,223 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1392.94054ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (65.226836ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (144.899792ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (234.950305ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (241.603231ms)
|
||||
✔ the app shows the same decide text as mosaic decide (159.256084ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (3057.084473ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (789.037736ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (1920.329552ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (93.514219ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (91.282545ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (799.179184ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (174.363391ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (154.893943ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (116.478809ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (1063.518736ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8492.504374ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (149.956101ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (108.958373ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (55.629888ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (242.1676ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (95.121636ms)
|
||||
✔ no business: the app says so and :business picks one (49.227595ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.679998ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (167.59024ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.440173ms)
|
||||
✔ decide with --note still asks; a No sends nothing (60.406093ms)
|
||||
✔ the app's business comes from a live bus host only (0.940807ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (7.12598ms)
|
||||
✔ draw is pure: same state, same frame (0.787061ms)
|
||||
✔ recordBootRefused keeps the last good load across refusals; recordBootOk clears the refusal (4.658559ms)
|
||||
✔ an unknown key and a JSON syntax error each leave the bus down with the reason and path in the status (790.352828ms)
|
||||
✔ a missing file is recorded too, and a valid file clears the status on the next start (429.188557ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (245.883893ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (188.461524ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (183.011459ms)
|
||||
✔ decide prints a declining choice as declining (177.014866ms)
|
||||
✔ an unknown outcome is reported once and never resent (120.320351ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (130.554787ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (201.80951ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (144.798923ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (304.606361ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (210.235063ms)
|
||||
✔ agents and tasks print through the broker (121.435062ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.187012ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (69.054575ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (94.547776ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (48.172781ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (49.025591ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (29.987987ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (73.708115ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (314.369522ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (268.445895ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (4726.697749ms)
|
||||
✔ follow refuses agent context and bad arguments (118.473089ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (147.003549ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (148.483513ms)
|
||||
✔ empty views say so (0.988468ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (1.187932ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.195363ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (927.813386ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (948.043884ms)
|
||||
✔ the size cap refuses a push before any byte (405.621208ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (1137.685949ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (1465.057799ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (561.15317ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (655.659359ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (545.965099ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (529.561844ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (418.643691ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (823.77607ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (679.45238ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (643.122073ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (42.491165ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (640.928111ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (24.630106ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.065489ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (467.767121ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (1054.563808ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (284.466681ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (366.282613ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (621.564236ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (3.201968ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.72421ms)
|
||||
✔ a live host's lock stays, however old the file is (0.497506ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (1066.838911ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (197.082997ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (25.808777ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (101.889508ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (28.839161ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (42.588331ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (562.827472ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (480.130978ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (185.107972ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (186.455062ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (343.226185ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (27.326386ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (204.20097ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (504.081093ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (289.50521ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (492.283162ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1273.66017ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (378.274055ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (181.439564ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (234.659889ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (218.086301ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (148.519775ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (221.028947ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (168.978998ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (224.390891ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (20.183837ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (207.219312ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (309.16616ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (109.475353ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (751.713416ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (52.307392ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (62.38137ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (12.73607ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (8.157995ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (42.126085ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1518.570731ms)
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (986.900622ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3499.319054ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (385.912573ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (496.611983ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (302.022704ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (335.285531ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (451.293215ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (192.806205ms)
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1468.291273ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (1000.581475ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3759.58585ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (162.013829ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (165.490432ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (168.876957ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1297.168149ms)
|
||||
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.347185ms)
|
||||
✔ migration needs no bus/config, prints whole converted document, is idempotent and never writes (55.850343ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (2.050896ms)
|
||||
✔ post-119 example and Jason fixture migrate with checked inherited models; wrong or absent config refuses (215.863942ms)
|
||||
✔ plugins view/set use the human bus transport and pass only the explicit patch (vikunja:19/305) (2.743303ms)
|
||||
✔ zoned uses the IANA zone across DST (25.05817ms)
|
||||
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (257.129311ms)
|
||||
✔ two blocking decisions get two DMs with different nonces (194.321353ms)
|
||||
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.31809ms)
|
||||
✔ a failed DM is journaled, backs off, and is retried until it lands (134.380921ms)
|
||||
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (203.477636ms)
|
||||
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (122.090147ms)
|
||||
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (129.41985ms)
|
||||
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (279.877692ms)
|
||||
✔ a restart after the second refusal does not send before that refusal's 30 min are up (237.706663ms)
|
||||
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (353.538065ms)
|
||||
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (121.156114ms)
|
||||
✔ an inbox read failure is logged and the next poll retries (0.643421ms)
|
||||
✔ no Discord id reaches the journal or the log (124.116058ms)
|
||||
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (45.489613ms)
|
||||
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (55.878993ms)
|
||||
✔ the journal: a whole file that is one torn line truncates to empty (22.760038ms)
|
||||
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (2.053679ms)
|
||||
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (0.695123ms)
|
||||
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (4.179566ms)
|
||||
✔ the journal: a symlinked directory refuses and says it is a link (0.608345ms)
|
||||
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.538904ms)
|
||||
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.367424ms)
|
||||
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.424274ms)
|
||||
✔ digest content stays within Discord's 2000 characters (0.26115ms)
|
||||
✔ runLoop never overlaps ticks and stops after the one in flight (111.254108ms)
|
||||
✔ a human command refused with human-required prints the other-tree line and exits 3 (4.078583ms)
|
||||
✔ a --tester command refused with tester-required prints the other-tree line and exits 3 (1.27028ms)
|
||||
✔ other exit-3 refusals print no other-tree line (1.841352ms)
|
||||
✔ the line names no path (0.151386ms)
|
||||
✔ project init/check use declared business repo and never contact the bus (174.807814ms)
|
||||
✔ project commands validate args and refuse undeclared projects and agent init (35.120857ms)
|
||||
✔ project dispatcher reaches the human CLI (109.170593ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (602.470712ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (497.416017ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (474.083201ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (242.85511ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (4427.326853ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (485.646118ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (245.411102ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (260.938784ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (208.166502ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (208.42477ms)
|
||||
✔ inherited service.d override refuses without changing the unit (188.261193ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (181.245858ms)
|
||||
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (243.220357ms)
|
||||
✔ talk --tester refuses text without the [mos test] prefix before any call (146.169384ms)
|
||||
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (210.62822ms)
|
||||
✔ decide, stop and launches take no --tester (119.324579ms)
|
||||
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.335903ms)
|
||||
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.543418ms)
|
||||
✔ talk --tester to a stopped role says nobody is told to launch it (128.011642ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 REQ-MSG-1 a thread message starts the thread's session, which stops when idle; its history survives the stop and a restart and no other thread sees it (6570.100902ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 a running thread counts against its model's limit and an idle-stopped one doesn't (1797.660661ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 a turn longer than the idle time isn't stopped, and the thread idles out after it (4465.478219ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 a message sent after the idle snapshot keeps the session, which answers it (2898.899915ms)
|
||||
✔ REQ-ROLE-2 REQ-LAUNCH-1 a thread held by a run the launcher didn't start gets no second session (113.811563ms)
|
||||
✔ REQ-LAUNCH-1 a run that ends without taking its thread's message isn't started again for that message (209.209175ms)
|
||||
✔ REQ-THREAD-2 REQ-LAUNCH-1 a thread id that isn't a safe segment, or a thread of a non-thread instance, launches nothing (250.264362ms)
|
||||
✔ REQ-THREAD-1 REQ-LAUNCH-1 the chief can't launch the assistant outside a thread (86.949411ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (528.459841ms)
|
||||
✔ the transport writes {business, verb, args} to the child and reads its JSON (38.07345ms)
|
||||
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2157.315908ms)
|
||||
✔ busExit and refuseInsideAgent (0.456975ms)
|
||||
✔ talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread (329.68791ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1136.70871ms)
|
||||
✔ a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it (2438.797063ms)
|
||||
✔ talk says when the role isn't running, whether launch.by was told, and how to start launch.by (624.268703ms)
|
||||
✔ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (247.745199ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (117.451626ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (140.114369ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (148.514659ms)
|
||||
ℹ tests 213
|
||||
ℹ suites 0
|
||||
ℹ pass 213
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 20099.024308
|
||||
@@ -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,55 @@
|
||||
Note: switching to '686fc1cb6d4ce77a441b2953aa09dfc441ce9a39'.
|
||||
|
||||
You are in 'detached HEAD' state. You can look around, make experimental
|
||||
changes and commit them, and you can discard any commits you make in this
|
||||
state without impacting any branches by switching back to a branch.
|
||||
|
||||
If you want to create a new branch to retain commits you create, you may
|
||||
do so (now or later) by using -c with the switch command. Example:
|
||||
|
||||
git switch -c <new-branch-name>
|
||||
|
||||
Or undo this operation with:
|
||||
|
||||
git switch -
|
||||
|
||||
Turn off this advice by setting config variable advice.detachedHead to false
|
||||
|
||||
Not currently on any branch.
|
||||
nothing to commit, working tree clean
|
||||
Note: switching to '686fc1cb6d4ce77a441b2953aa09dfc441ce9a39'.
|
||||
|
||||
You are in 'detached HEAD' state. You can look around, make experimental
|
||||
changes and commit them, and you can discard any commits you make in this
|
||||
state without impacting any branches by switching back to a branch.
|
||||
|
||||
If you want to create a new branch to retain commits you create, you may
|
||||
do so (now or later) by using -c with the switch command. Example:
|
||||
|
||||
git switch -c <new-branch-name>
|
||||
|
||||
Or undo this operation with:
|
||||
|
||||
git switch -
|
||||
|
||||
Turn off this advice by setting config variable advice.detachedHead to false
|
||||
|
||||
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,82 @@
|
||||
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/copy-service.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/offline-check.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 183)
|
||||
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
|
||||
OK pinned render runs copy CLI with copy cwd/repo and no checkout executable
|
||||
OK pinned install writes the rendered unit in a temporary unit directory
|
||||
OK pinned install refuses short prerequisite and writes no unit
|
||||
OK pinned install refuses missing prerequisite and writes no unit
|
||||
OK pinned install refuses cli prerequisite and writes no unit
|
||||
OK pinned install refuses pi prerequisite and writes no unit
|
||||
OK status names the copy from fake systemctl effective cwd
|
||||
OK checkout install explicitly recommends --copy
|
||||
OK wrapper check --offline passes local fixture and makes no network call
|
||||
OK wrapper run --offline refuses usage
|
||||
|
||||
discord suite: 78 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: 2935078 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,86 @@
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK --base next refuses before the config is read (got 2)
|
||||
OK a missing system config exits 3 (got 3)
|
||||
OK nobus: exit 3
|
||||
OK schema-table: exit 2, bus-schema
|
||||
OK schema-meta: exit 2, bus-schema
|
||||
OK openBus opens the database read-only
|
||||
OK other-business: exit 2, decision-not-found
|
||||
OK no-raise: exit 2, decision-not-found
|
||||
OK not-a-merge: exit 2, not-a-merge
|
||||
OK open: exit 2, not-resolved
|
||||
OK withdrawn: exit 2, not-resolved
|
||||
OK by-agent: exit 2, not-human
|
||||
OK via-webui: exit 2, not-human
|
||||
OK no-answer: exit 2, not-human
|
||||
OK answer-role: exit 2, not-human
|
||||
OK answer-run: exit 2, not-human
|
||||
OK answer-choice: exit 2, not-human
|
||||
OK two-answers: exit 2, not-human
|
||||
OK chose-no: exit 2, not-merge-option
|
||||
OK two-refs: exit 2, work-ref
|
||||
OK bad-ref: exit 2, work-ref
|
||||
OK task-ref-disagrees: exit 2, work-ref
|
||||
OK raise-task-disagrees: exit 2, work-ref
|
||||
OK target-main: exit 2, target-branch
|
||||
OK superseded-question: exit 2, superseded
|
||||
OK superseded-task: exit 2, superseded
|
||||
OK superseded-by: exit 2, superseded
|
||||
OK no-verdict: exit 2, no-verdict
|
||||
OK changes-later: exit 2, not-approved
|
||||
OK short-commit: exit 2, not-approved
|
||||
OK wrong-task-body: exit 2, not-approved
|
||||
OK args: exit 2, decision-not-found
|
||||
OK earlier-merge: exit 0
|
||||
OK ref-moved: exit 2, ref-moved
|
||||
OK root-top: exit 2, root-file
|
||||
OK root-newdir: exit 2, root-file
|
||||
OK root-src: exit 2, root-file
|
||||
OK unrelated: exit 2, base-conflict
|
||||
OK empty: exit 2, base-conflict
|
||||
OK an empty reviewed diff says so
|
||||
OK dirty-changed: exit 2, checkout-dirty
|
||||
OK dirty-staged: exit 2, checkout-dirty
|
||||
OK dirty-untracked: exit 2, checkout-dirty
|
||||
OK conflict: exit 2, base-conflict
|
||||
OK a refusal after the worktree is added leaves no worktree or scratch
|
||||
OK cleanup looks for the worktree's Docker network
|
||||
OK dirty-during: exit 2, checkout-dirty
|
||||
OK a reviewed path dirtied during the gate moves no ref
|
||||
OK drift: exit 2, patch-drift
|
||||
OK patch-drift leaves no worktree or scratch
|
||||
OK gate-pkg: exit 2, gate-failed
|
||||
OK gate-failed names the failing step's log, and it exists
|
||||
OK gate-failed leaves no worktree or scratch
|
||||
OK gate-script: exit 2, gate-failed
|
||||
OK a failing scripts/test-*.sh fails the gate
|
||||
OK a failed gate moves no ref
|
||||
OK nomods: exit 4
|
||||
OK a target without node_modules leaves no worktree or scratch
|
||||
OK moved: exit 2, base-moved
|
||||
OK base-moved keeps the base where it moved to
|
||||
OK dry: exit 0
|
||||
OK --dry-run writes no ref
|
||||
OK --dry-run prints the commit with --subject and --attribution
|
||||
OK --dry-run runs the gate
|
||||
OK --dry-run leaves no worktree or scratch
|
||||
OK land: exit 0
|
||||
OK the landing is one commit on the old base
|
||||
OK its diff is the reviewed diff by patch-id
|
||||
OK its tree is the dry run's
|
||||
OK the message has the option's subject, the citations and the attribution last
|
||||
OK it prints the line for the PM
|
||||
OK the checked-out base has the reviewed paths and keeps the unrelated edit
|
||||
OK only refs/heads/refactor exists in the target
|
||||
OK the work ref is unchanged
|
||||
OK the bus database is unchanged
|
||||
OK the gate ran each package suite but queue, and each scripts/test-*.sh
|
||||
OK the landing leaves no worktree or scratch
|
||||
OK the target's node_modules is still there, with its contents
|
||||
OK the worktree's Docker network is removed
|
||||
---
|
||||
land-work selftests: 84 passed, 0 failed
|
||||
@@ -0,0 +1,36 @@
|
||||
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/gate-owner.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 156
|
||||
ℹ pass 156
|
||||
ℹ fail 0
|
||||
OK node --test packages/queue/tests/
|
||||
OK scripts/mosaic queue help
|
||||
skip queue verify and render --check: this checkout (/home/jwoltje/dewey-scratch/r151/wt) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)
|
||||
|
||||
queue suite: 28 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,101 @@
|
||||
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)
|
||||
OK mock adapter: gate passes on matching mock response (exit 0)
|
||||
OK mock adapter: expect-mismatch recorded (exit 1)
|
||||
OK mismatch reason recorded
|
||||
OK unknown adapter fails closed (exit 1)
|
||||
OK mission task runs via mock adapter (exit 0)
|
||||
OK mission section injected into generated prompt
|
||||
OK retry of mission run succeeds (exit 0)
|
||||
OK retriedFrom lineage recorded
|
||||
OK mission section present after retry (relative path resolved)
|
||||
OK retry of missing run exits 4 (exit 4)
|
||||
OK skill install bundled ms-tools (exit 0)
|
||||
OK installed to skills-available
|
||||
OK double install refuses (exit 1)
|
||||
OK activate enables skill (exit 0)
|
||||
OK enabled dir populated
|
||||
OK uninstall while enabled refuses (exit 1)
|
||||
OK deactivate moves back to available (exit 0)
|
||||
OK uninstall removes from available (exit 0)
|
||||
OK seat with enabled skill launches
|
||||
OK skill path delivered to adapter
|
||||
OK shipped researcher contract resolves (ceiling + network)
|
||||
OK resolve-role refuses a non-role document (conductor policy) (exit 2)
|
||||
OK resolve-role refuses name/filename mismatch (exit 2)
|
||||
OK resolve-role refuses unknown network declaration (exit 2)
|
||||
OK resolve-role refuses duplicate role tool (exit 2)
|
||||
OK resolve-role refuses unsupported tool (exit 2)
|
||||
OK resolve-role refuses missing contract file (exit 4)
|
||||
OK version 1 role prints no contract line
|
||||
OK shipped version 2 roles resolve with their contracts (pm, cto, coder, reviewer)
|
||||
OK resolve-role accepts a minimal version 2 role (exit 0)
|
||||
OK resolve-role refuses an action outside the vocabulary (exit 2)
|
||||
OK resolve-role refuses a gated-only action in a role file (exit 2)
|
||||
OK resolve-role refuses a Vikunja verb no role may hold (exit 2)
|
||||
OK resolve-role refuses a version 2 role whose contract is missing (exit 2)
|
||||
OK resolve-role refuses a contract that is a symbolic link (exit 2)
|
||||
OK seat launches under role ceiling
|
||||
OK role ceiling narrows seat tools (read,write,bash -> read,bash)
|
||||
OK narrowing recorded loudly
|
||||
OK missing role contract refuses launch (exit 2)
|
||||
OK missing-contract refusal names the role
|
||||
OK empty ceiling intersection -> tool-free seat
|
||||
OK tool-free outcome recorded loudly
|
||||
OK overridden agents dir without seat definition refuses (exit 4)
|
||||
OK seat-resolution refusal names the seat
|
||||
OK policy: mission only -> mission tools
|
||||
OK policy: task only -> task tools
|
||||
OK policy: both -> intersection (task narrowed)
|
||||
OK policy: empty intersection -> tool-free
|
||||
OK invalid mission capabilities rejected (exit 2)
|
||||
mosaic-task: unsupported mission tool: "sudo" (supported: read, write, edit, bash, grep, find, ls)
|
||||
OK task run with user layer present (exit 0)
|
||||
OK user context dispatched into generated prompt
|
||||
OK workspace+tools task runs via mock (exit 0)
|
||||
OK workspace path + tools delivered to adapter
|
||||
OK persistent workspace created on host
|
||||
OK plain task still runs (no workspace/tools) (exit 0)
|
||||
OK workspace var present but empty when absent
|
||||
OK tools empty when absent
|
||||
OK unknown tool exits 2 (exit 2)
|
||||
OK workspace traversal exits 2 (exit 2)
|
||||
OK live hello task succeeds with exact marker
|
||||
OK result.json written in run dir
|
||||
OK result.json contents are correct
|
||||
OK wrong expectExact fails with exit 1 (reason: expect-mismatch)
|
||||
OK each run gets a distinct run dir (no clobber)
|
||||
OK list shows both runs
|
||||
OK fork base: teach succeeds (exit 0)
|
||||
OK fork child recalls ancestor context (exit 0)
|
||||
OK forked child recalled ancestor code word
|
||||
OK ancestor session untouched by fork
|
||||
OK child session dir has its own branch file
|
||||
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
|
||||
OK user recall run succeeds
|
||||
OK recalled user name (response: Jason)
|
||||
OK no agent identity on headless run
|
||||
|
||||
selftest: 98 passed, 0 failed
|
||||
@@ -0,0 +1,7 @@
|
||||
start 2026-10-16T00:13:46Z
|
||||
B1-notice-routed-to-target KILLED rc=1 | a message to a stopped role sends launch.by one notice, and the result says so
|
||||
C1-no-reply-filter KILLED rc=1 | a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it | talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread | talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply
|
||||
C2-no-waiting-lines KILLED rc=1 | talk says when the role isn't running, whether launch.by was told, and how to start launch.by | talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply
|
||||
C3-waiting-every-poll KILLED rc=1 | talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply
|
||||
restored True
|
||||
end 2026-10-16T00:13:59Z rc=0
|
||||
@@ -0,0 +1,43 @@
|
||||
import subprocess, sys, os, signal
|
||||
# Row 151 (#1645): one mutant per pinned path. Each applies to its source in the worktree, runs the
|
||||
# owning test file, and the source is restored after every mutant.
|
||||
W=os.path.expanduser('~/dewey-scratch/r151/wt')
|
||||
OUT=os.path.expanduser('~/dewey-scratch/r151/mut')
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
BROKER='packages/bus/src/broker.mjs'
|
||||
CLI='packages/cli/src/cli.mjs'
|
||||
LOOP=' for (const m of await call("message.receive")) {\n'
|
||||
M={
|
||||
# Filbert's row 146 M1: the notice is routed to the target instead of launch.by.
|
||||
'B1-notice-routed-to-target': (BROKER, 'packages/bus', 'tests/launch-notice.test.mjs',
|
||||
'this.#route(business, nid, by, null);', 'this.#route(business, nid, to, null);'),
|
||||
# Row 142's reply filter is dropped: talk prints and reads every message.
|
||||
'C1-no-reply-filter': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
||||
' if (!follow && m.in_reply_to !== sent.id) continue;\n', ''),
|
||||
# Row 146's waitingLines write is dropped.
|
||||
'C2-no-waiting-lines': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
||||
' if (sent.waiting) io.stdout.write(', ' if (false) io.stdout.write('),
|
||||
# The waiting line is printed again on every receive poll instead of once.
|
||||
'C3-waiting-every-poll': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
||||
LOOP, ' if (sent?.waiting) io.stdout.write(waitingLines(sent.waiting, () => "demo"));\n' + LOOP),
|
||||
}
|
||||
env=dict(os.environ, TMPDIR=os.path.expanduser('~/dewey-scratch/tmp'))
|
||||
origs={p: open(os.path.join(W,p)).read() for p in (BROKER, CLI)}
|
||||
try:
|
||||
for name,(path,pkg,test,a,b) in M.items():
|
||||
orig=origs[path]
|
||||
assert orig.count(a)==1, name
|
||||
open(os.path.join(W,path),'w').write(orig.replace(a,b))
|
||||
p=subprocess.Popen(['node','--test','--test-reporter=spec',test],cwd=os.path.join(W,pkg),env=env,
|
||||
stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,start_new_session=True)
|
||||
try:
|
||||
out,_=p.communicate(timeout=300)
|
||||
except subprocess.TimeoutExpired:
|
||||
os.killpg(p.pid, signal.SIGKILL); out,_=p.communicate(); out+='\nTIMEOUT\n'
|
||||
fails=sorted({l.strip()[2:].split(' (')[0] for l in out.splitlines() if l.lstrip().startswith('✖') and 'failing tests' not in l})
|
||||
print(name, 'KILLED' if p.returncode!=0 else 'SURVIVED', 'rc=%d'%p.returncode, '| '+' | '.join(fails))
|
||||
open(os.path.join(OUT,f'{name}.log'),'w').write(out)
|
||||
open(os.path.join(W,path),'w').write(orig)
|
||||
finally:
|
||||
for path,orig in origs.items(): open(os.path.join(W,path),'w').write(orig)
|
||||
print('restored', all(open(os.path.join(W,p)).read()==o for p,o in origs.items()))
|
||||
@@ -0,0 +1,38 @@
|
||||
✖ a message to a stopped role sends launch.by one notice, and the result says so (71.619393ms)
|
||||
✔ a message to a running role sends no notice and its result is unchanged (54.574255ms)
|
||||
✔ a re-route at a claim, a release and claim, and a broker restart send no second notice (92.993429ms)
|
||||
✔ a run launched but not yet claimed counts as no holder (50.656281ms)
|
||||
✔ no notice for a message to launch.by, from it, from a tester, to the human, or in a thread to a thread instance (119.144025ms)
|
||||
✔ a business with no launch block tells nobody and says there is no launcher (45.072513ms)
|
||||
✔ the notice sender stays internal: no role is named _bus and no caller can send as it or to it (158.137067ms)
|
||||
ℹ tests 7
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 649.821244
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at tests/launch-notice.test.mjs:68:1
|
||||
✖ a message to a stopped role sends launch.by one notice, and the result says so (71.619393ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ null
|
||||
- 'chief-run'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/bus/tests/launch-notice.test.mjs:97:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: 'chief-run',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
✖ talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread (137.637526ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1062.429822ms)
|
||||
✖ a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it (2078.389494ms)
|
||||
✔ talk says when the role isn't running, whether launch.by was told, and how to start launch.by (131.77928ms)
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (128.132667ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (45.537858ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (56.013202ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (59.829141ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 5
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3787.405698
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at tests/verbs.test.mjs:32:1
|
||||
✖ talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread (137.637526ms)
|
||||
AssertionError [ERR_ASSERTION]: another role's note and the same role's unsolicited note are not printed
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:59:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'sent 7810611c to coder\ncto (INFO) 7f8d1144:\nfyi\ncoder (INFO) 2157a83c:\nside note\ncoder (RESULT, re 7810611c) bec1e61d:\ndone: 3 files\n',
|
||||
expected: /fyi|side note/,
|
||||
operator: 'doesNotMatch',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at tests/verbs.test.mjs:80:1
|
||||
✖ a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it (2078.389494ms)
|
||||
AssertionError [ERR_ASSERTION]: the late reply answers the first message, not this one
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:90:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'sent c04043bb to coder\ncoder (RESULT, re 5f5561b2) 7e17ed0e:\nlate answer\n',
|
||||
expected: /late answer/,
|
||||
operator: 'doesNotMatch',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at tests/verbs.test.mjs:123:1
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (128.132667ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
'sent f15cf912 to cto\n' +
|
||||
"cto isn't running, pm has been told\n" +
|
||||
+ 'pm (INFO) 9244dcf1:\n' +
|
||||
+ 'launching cto\n' +
|
||||
'cto (RESULT, re f15cf912) 5f56e30d:\n' +
|
||||
'on it\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:147:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: "sent f15cf912 to cto\ncto isn't running, pm has been told\npm (INFO) 9244dcf1:\nlaunching cto\ncto (RESULT, re f15cf912) 5f56e30d:\non it\n",
|
||||
expected: "sent f15cf912 to cto\ncto isn't running, pm has been told\ncto (RESULT, re f15cf912) 5f56e30d:\non it\n",
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
✔ talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread (140.435947ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1064.919362ms)
|
||||
✔ a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it (2089.02205ms)
|
||||
✖ talk says when the role isn't running, whether launch.by was told, and how to start launch.by (65.218102ms)
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (127.913466ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (47.996606ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (54.711986ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (45.47145ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3728.268613
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at tests/verbs.test.mjs:99:1
|
||||
✖ talk says when the role isn't running, whether launch.by was told, and how to start launch.by (65.218102ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ ''
|
||||
- "cto isn't running, and the business names no launch.by\n"
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:109:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '',
|
||||
expected: "cto isn't running, and the business names no launch.by\n",
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at tests/verbs.test.mjs:123:1
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (127.913466ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ 'sent dbd10b6c to cto\ncto (RESULT, re dbd10b6c) bf8a3623:\non it\n'
|
||||
- 'sent dbd10b6c to cto\n' +
|
||||
- "cto isn't running, pm has been told\n" +
|
||||
- 'cto (RESULT, re dbd10b6c) bf8a3623:\n' +
|
||||
- 'on it\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:147:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'sent dbd10b6c to cto\ncto (RESULT, re dbd10b6c) bf8a3623:\non it\n',
|
||||
expected: "sent dbd10b6c to cto\ncto isn't running, pm has been told\ncto (RESULT, re dbd10b6c) bf8a3623:\non it\n",
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
✔ talk sends a REQUEST, prints and reads only the reply to it, and leaves other messages unread (118.78593ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1057.049691ms)
|
||||
✔ a late reply the Console has listed stays unread for mosaic inbox, and the next talk skips it (2097.311374ms)
|
||||
✔ talk says when the role isn't running, whether launch.by was told, and how to start launch.by (210.456924ms)
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (131.942575ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (46.679533ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (55.369609ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (47.506821ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 7
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3854.040573
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at tests/verbs.test.mjs:123:1
|
||||
✖ talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply (131.942575ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
'sent 8da5c43f to cto\n' +
|
||||
"cto isn't running, pm has been told\n" +
|
||||
+ "cto isn't running, pm has been told\n" +
|
||||
+ "cto isn't running, pm has been told\n" +
|
||||
'cto (RESULT, re 8da5c43f) e0d0497e:\n' +
|
||||
'on it\n'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r151/wt/packages/cli/tests/verbs.test.mjs:147:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: "sent 8da5c43f to cto\ncto isn't running, pm has been told\ncto isn't running, pm has been told\ncto isn't running, pm has been told\ncto (RESULT, re 8da5c43f) e0d0497e:\non it\n",
|
||||
expected: "sent 8da5c43f to cto\ncto isn't running, pm has been told\ncto (RESULT, re 8da5c43f) e0d0497e:\non it\n",
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
05202775dd9fb4566e7d977467beb4bc02cdbeff19800a5800b61d2d8d362c6e ./BUILD.md
|
||||
f8e07a482fdf9ef493695ab6deffb296247f808e93510ea8de8618f770b4bde7 ./base.txt
|
||||
51065038dce8fdfb59745c82a1553d8db0376e79001941271e56ad52e082906f ./build.patch
|
||||
cb831847239e9ea60bd77ed8c765dafbf607a03cadeed3d0fc8d8284846878ed ./candidate-manifest.sha256
|
||||
8636de52c30c165c7ae3185ebda90db6031f04715d6626639208211b4ad51cea ./gate-run.log
|
||||
e403e2002984b207c1e95580aa9633b8d4f133d7654ca0c38ea4a577f2040064 ./gate.sh
|
||||
faf8ec1da03477575f9ff882724f2d5cf982face0edf3061ebbd4acf35138fec ./gate/pkg-bus.log
|
||||
0324a6d7cc4c19b9a1d1a33528a0f31a145940691d89363ec15ee44040e56192 ./gate/pkg-cli.log
|
||||
f91fc95a173339137f981e24fbf630acfde957e32c3cd71e28304532083c6a77 ./gate/test-auth.log
|
||||
bac0e22a2527e95c2e533937e5dd9c790f67efea53e37e2f0e96f5231e9a286c ./gate/test-conductor.log
|
||||
52d211444489ea729dafc3c9745d4474d9dfd50f41055cbad792424197f04073 ./gate/test-config.log
|
||||
87d2e24ce0be7586e31ea1f2c9ce5618b3127515b3c3cd3893f2a0ed899d5822 ./gate/test-discord.log
|
||||
827dfb83d0b2864e8705f317bab0c7082d863f522108a6dd86533c2317737f74 ./gate/test-extension-package.log
|
||||
83dfaa21c4e4ad941088efab3f69e87ebd2f6bd3cc72ede938e21dc06da8a34f ./gate/test-foundation.log
|
||||
8e2254aa3e1bb9b205ab72c68273d447c0328c9f156ccba2a46f3a0476468b58 ./gate/test-land-work.log
|
||||
400e651550c42a8580e572b31c4096aa779d34ee3c1eae185d77b854f926ea81 ./gate/test-queue.log
|
||||
fa832794ee35025fb4559d58d01a270f6bff2eb65e863e9075b797f47fa68545 ./gate/test-release.log
|
||||
ccea37f4ffde1f160dcd1a1864988083a645d974e892065c956b338d0f8c853a ./gate/test-task.log
|
||||
785da1cb9963a1bec9ee926b37d151df3c0681fe351fa7ae6fbcf9c40335292c ./mutants-run.log
|
||||
4cdf6bc76a9b2e7a19c83864a2d384c1605a6fe1830f9de9ad31268c3c73a0e1 ./mutants.py
|
||||
99a47ce7a736301380ac59b0fbc04185c1533f6a7eee9d7d34e29e86643bb953 ./mutants/B1-notice-routed-to-target.log
|
||||
36a4ab87bffc837a3bf1fdc3b8394c63068147e5af5fe0757c43a7ff194cbe08 ./mutants/C1-no-reply-filter.log
|
||||
824dd2f25605b7756a81961f68dac5d12eac125b4e223cd0b23c68706a902e1a ./mutants/C2-no-waiting-lines.log
|
||||
7eadad60aa4b8b4367df0452b0174101aa6f9a763f9c3ea7a0e7ed60b8ba28e9 ./mutants/C3-waiting-every-poll.log
|
||||
bae1a9f6c74fcb7461e0e0b5e277b86383ca1f25fea0b2ff1d57fb00c8c677ce ./repro.sh
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# Row 151: apply build.patch to a detached worktree at base.txt and check the candidate manifest.
|
||||
# Usage: repro.sh <canonical checkout> <new worktree path>
|
||||
set -euo pipefail
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
REPO=$1 WT=$2
|
||||
git -C "$REPO" worktree add -q --detach "$WT" "$(cat "$HERE/base.txt")"
|
||||
git -C "$WT" apply "$HERE/build.patch"
|
||||
(cd "$WT" && sha256sum -c --quiet "$HERE/candidate-manifest.sha256") && echo DIGESTS_OK
|
||||
Reference in new issue
Block a user