📝 Gremlins run log: block 3.4a note

This commit is contained in:
2026-10-16 21:57:49 +02:00
parent 2257e89537
commit d6daf7a6c5
@@ -649,3 +649,29 @@ Intake 2026-10-16 18:23 +0200, a fresh (successor) Athanor, `claude-opus-5-5[1m]
- Left for later: SKILL.md text for N3 (re-run re-resolves unless pinned), N4 (`parent_inactive`) and the `warnings` key on `init` (block 3.5, digest §7.1 items 3 and 7 already name them); the full suite (3.8). - Left for later: SKILL.md text for N3 (re-run re-resolves unless pinned), N4 (`parent_inactive`) and the `warnings` key on `init` (block 3.5, digest §7.1 items 3 and 7 already name them); the full suite (3.8).
- Expected broken: nothing known. The full suite was not run (it runs once in 3.8); `CliTests`, `GateTests`, `TickTests`, `UsageTests` and the rest of `LaunchTests` were not run in this block (a grep of the tests' key-set assertions, `assertEqual(set(…), …)`, finds none on `init` output, so the new `warnings` key breaks no exact-shape check; the new job-entry key `rebase_inactive_parent` is not in `LIST_JOB_KEYS` or the result). - Expected broken: nothing known. The full suite was not run (it runs once in 3.8); `CliTests`, `GateTests`, `TickTests`, `UsageTests` and the rest of `LaunchTests` were not run in this block (a grep of the tests' key-set assertions, `assertEqual(set(…), …)`, finds none on `init` output, so the new `warnings` key breaks no exact-shape check; the new job-entry key `rebase_inactive_parent` is not in `LIST_JOB_KEYS` or the result).
- Commits: `62eef3b` (code and tests), then this note's commit. - Commits: `62eef3b` (code and tests), then this note's commit.
### Block 3.4a — Portable test fixes from the WSL check
- Model: `claude-opus-5-5[1m]` (fresh block owner, own tools, no agents dispatched)
- Start / end: Fri Oct 16 21:54:58 WEDT 2026 / Fri Oct 16 21:57:20 WEDT 2026 (`date`; the end is after the test commit, this note followed)
- Done (tests only, `gremlins.py` unchanged):
- **`GateTests.test_closed_gate_on_existing_registry`** (WSL cause: the "gate open" `init` was refused on Linux, since `GateTests.setUp` pops `SPIRE_GREMLIN_UNSUPPORTED_OK` and the host is unsupported). The setup `init` now runs inside `mock.patch.dict(os.environ, {UNSUPPORTED_OK_ENV: "1"})`, so the gate is open on any host (on Windows the env is ignored, A12); a new assertion inside checks `platform_gate()` is `None` there, and one after it checks the env is gone again. Then `close_gate()` and every closed-gate assertion exactly as before (each of `spawn`, `train`, `continue`, `rebase`, `tick`: exit 2, one JSON line, `error == "platform not supported"`, the A7 reason, `platform.supported` false; registry `jobs == {}` and unchanged; `tick_pass` reads no registry; `list` and `wait` still work).
- **`LaunchTests.test_delta_tokens_counts_only_what_the_base_does_not_know`** (WSL cause: `trained_at` has whole seconds, so B2's rebase ending in the same second the note was written gave `trained_at < mtime`). Right after the large note is written, its mtime is set with `os.utime` to now − 30 s and B1's `trained_at` (via `set_registry`) to now − 60 s, with a new precondition assertion `B1.trained_at < note mtime`. So B1 predates the note (the note counts for B1), `Bk` (cloned at `mtime + 60`) still postdates it, and B2's rebase, which ends at now or later, postdates it by at least 29 s on any host speed. `trained_at` is read by the helper only in `new_to_base` (and `list`'s copy of the field), so moving B1's is invisible to every other check in the test. Every assertion of the test is unchanged, including `assertGreater(_ts(B2.trained_at), mtime)` (now deterministic, not removed).
- Changed assertion lines (old → new; `git diff 4d8af02..2257e89 -- …/tests/ | grep -c '^-.*assert'` = 1):
- `GateTests.test_closed_gate_on_existing_registry`: `self.assertEqual(code, 0, out)` → the same line, indented into the `with` block (the setup `init` runs under the override env).
- Added: `self.assertIsNone(gremlins.platform_gate())` (gate open during setup), `self.assertNotIn(gremlins.UNSUPPORTED_OK_ENV, os.environ)` (env gone before the gate closes), and in the delta test `self.assertLess(gremlins._ts(self.reg()["bases"]["B1"]["trained_at"]), os.path.getmtime(note))`.
- None dropped or loosened.
- Gates:
1. `uv run python -m py_compile plugins/spire/skills/gremlins/tests/test_gremlins.py`: exit 0.
2. Windows: `uv run plugins/spire/skills/gremlins/tests/test_gremlins.py GateTests LaunchTests.test_delta_tokens_counts_only_what_the_base_does_not_know`: exit 0, `Ran 9 tests in 4.643s`, `OK`.
3. WSL (`MSYS_NO_PATHCONV=1 wsl -d Ubuntu-20.04 -e bash -lc '… cp -r …/skills/gremlins ~/g34a && cd ~ && uv run ~/g34a/tests/test_gremlins.py GateTests LaunchTests.test_delta_tokens_counts_only_what_the_base_does_not_know; echo exit=$?; rm -rf ~/g34a'`): `Ran 9 tests in 1.485s`, `OK`, `exit=0` (before this block both tests failed there, `suite.txt` lines 234–251).
4. Leftover processes (21:56; Windows `Get-CimInstance Win32_Process` by command line `gremlins-test-`, `_supervise`; WSL `pgrep -af "gremlins-test-|_supervise|g34a"`): none (only the query itself). No `wsl --shutdown`/`--terminate`.
- No live `claude` calls (stub only).
- Deviations from plan:
- The WSL findings file named in the brief (`…\scratchpad\gremlins-wsl\findings.md`) does not exist; the folder holds `suite.txt`, `matrix-gate.txt`, the `where-*` probes and `zombie_probe.py`. The two causes were taken from the brief and confirmed from `suite.txt`'s tracebacks.
- Fix 1 uses the override env (the brief's first option), not a fake supported platform: it keeps the host's own platform class and path handling for the `init`, as the WSL run of `test_override` already showed works.
- Flagged for review:
- Product (not changed, per the brief): `trained_at` is written with `timespec="seconds"` (truncated), and `new_to_base` counts a note when `mtime > trained_at`. A note written in the same whole second as, but before, a training's or rebase's end therefore still counts as new to that base: a spurious `delta_tokens` reason right after a rebase that absorbed it. It errs towards rebasing, never towards missing a note, and needs sub-second timing to happen in real use, so I left it; a fix would be a fractional `trained_at` or comparing against `trained_at + 1`.
- Left for later: the POSIX-only failures from the WSL suite (`test_kill_tree`, `test_refusals`, `test_expire_kills_running_jobs`, `test_rebase_counts_toward_cap`: zombie root counted alive; `test_lost`, `test_orphan_watchdog`: supervisor liveness; `test_timeout_and_stalled`: tree size 2 < 3) go into the platform handoff, untouched here.
- Expected broken: nothing known. Only the two classes/tests above ran; the full suite runs once in 3.8.
- Commits: `2257e89` (tests), then this note's commit.