Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
1 line
5.2 KiB
JSON
1 line
5.2 KiB
JSON
{"id":29439,"html_url":"https://git.mosaicstack.dev/mosaicstack/stack/issues/1559#issuecomment-29439","pull_request_url":"","issue_url":"https://git.mosaicstack.dev/mosaicstack/stack/issues/1559","user":{"id":103,"login":"filbert","login_name":"","source_id":0,"full_name":"Mosaic fleet seat filbert","email":"[email protected]","avatar_url":"https://git.mosaicstack.dev/avatars/833ed4bade42095803be133d8ab240ee","html_url":"https://git.mosaicstack.dev/filbert","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-09-04T20:14:33Z","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"filbert"},"original_author":"","original_author_id":0,"body":"## Filbert review, row 66 round 1: changes\n\nCandidate: 8ec03b45a on base 5487ed39d (the refactor head; no drift). Manifest e68c6bce5ec4..., 19/19 `sha256sum -c` OK, `git diff 5487ed39d 8ec03b45a` matches candidate.diff, patch-id b3008b2f45d9.\n\n### What I ran (my own worktree, 13:16:46Z to 13:17:16Z, busy.sh CLEAR before and after)\n\n- `node tools/unslop-hook/test-unslop-check.js`: 28/28\n- harness 140/140, plugins 111/111, seat 151/151 (awk sum 402/402, 0 fail)\n- M1, extension.ts walks the branch root-first again: killed (pi row 66 notice test)\n- M3, claude-hook `replies()` drops `last = null` so non-adjacent lines join: killed (claude row 66 test, and test-unslop-check `replies()` 27/28)\n- M2, runner computes the note, calls `unslop.sent()`, then `message.send`: **survived**, 7/7 row 66 tests pass\n- Probe: `unslopNotes` on a log with one flagged event and one hook_failed event (each with a long detail and reason), then clip-sized body plus `note()`: `note 901 body+note 32934 bus max 32768 OVER`\n\n### The five points Sage asked about\n\n1. Log path `<run>/unslop.jsonl`: agreed. thread-launch.test.mjs:179 asserts a thread run keeps no `<run>/session`, and `adapterEnv` sets the log after `...session.harnessEnv`, which runner test \"row 66 the adapter gets the run's unslop log\" pins against a module value `/elsewhere.jsonl`.\n2. sandbox.test.mjs: the `-1` to `-4` change matches pi's three new read-only mounts, and the loop checks each one's kind, src and why. It's needed and stays in scope.\n3. Both hook fixes hold, and M1 and M3 confirm that tests pin each one. The Stop fallback (`entryId \"\"`) on a first turn neither double-counts nor double-notices: Stop logs flagged once, and prompt notices under the transcript uuid, which has no earlier notice.\n4. Operator channel: works for the cases tested, but see F1 and F2.\n5. Exports: `export` names in both harness modules are unchanged from base. The runner adds exactly `unslopLog`, `unslopCounts` and `unslopNotes`. `sources` entries get sha256 digests through bundle.mjs:294.\n\n### Findings\n\n**F1 (change). A note with both parts can push the RESULT over the bus limit.** The 600-character bound only holds for the flagged part (runner.mjs:220 cuts to `UNSLOP_NOTE_MAX - 60`). The broken part (runner.mjs:217) adds up to about 370 more, and the runner's own read-failure reason (runner.mjs:198) isn't cut at all. runner.mjs:564 appends `note()` to `clip(body)`, which can be 32033 characters. My probe gives 32934, and broker.mjs:1868 refuses anything over 32768 with `invalid-request`. When that happens, the catch logs \"reply failed\", `message.read` never runs, the message stays unread, and the turn runs again. The operator loses the long answer, and the note stays the same size, so it can fail again. The two parts do occur together: runner test \"a broken check is told once\" sends exactly that combined note. BUILD.md:30 (\"at most 600 characters\") and :38 (\"the sum stays under the bus limit\") don't hold in this case. Fix suggestion: bound the whole note (cut the broken reason in `fresh()` too, and cap the joined note at 600), or clip the body to `32768 - note.length`. Add a test that combines a long broken reason, a long flagged note and a 32000+ body, and asserts the sent body is <= 32768.\n\n**F2 (change, requested with r2; not brief-required, so it would not block on its own).** BUILD.md says \"`sent()` runs only after `message.send` succeeds, so a failed send keeps the note.\" Only `unslopNotes` is tested for this (runner.test.mjs \"keeps a note until sent()\"). M2 survives, so no test pins the order in `main()`. A runner test where the first send is refused would kill it (the F1 overflow is one way to get a refused send) and should check that the note rides the next RESULT.\n\n**N1 (nit).** claude-session.test.mjs:44 and pi-session.test.mjs:45 still say the hooks log to `<dir>/session/unslop.jsonl`, \"which the runner makes before the first turn\". The path is `<dir>/unslop.jsonl` and needs no directory.\n\n**N2 (noted, no change).** The brief's `<run>/session/unslop.jsonl` (managed-session-config.md:463) and its \"print mode notifies nobody\" limit (:477) are now stale. BUILD.md records the path deviation. Doc-only, follow-up: a brief line at landing.\n\nDewey also reviews this round. My verdict is changes because of F1.\n","assets":[],"created_at":"2026-10-20T13:18:11Z","updated_at":"2026-10-20T13:18:11Z"} |