4.4 KiB
v3.13.3 Release Notes
Release Date: 2026-07-29
Highlights
Two fixes about evidence you can trust. Learning capture could stop recording
for days without saying so on any project that sets AQE_DISABLE_WAL, and
QE-Court shipped a default review panel that broke the court's own
anti-collusion rule the moment it was created.
Fixed
Learning capture no longer stops silently under AQE_DISABLE_WAL
AQE_DISABLE_WAL=1 exists for filesystems where SQLite's WAL journal is unsafe
— notably macOS Docker bind mounts, where it has corrupted the learning database
before. With the flag set, AQE attempted to switch the journal mode on every
writable connection.
Changing a database's journal mode requires exclusive access. Any other process holding the database open makes that attempt fail, and the failure took the whole persistence layer down with it: the memory manager could not initialize, so nothing was recorded. The hooks kept returning success, so from the outside everything looked healthy while no learning was being captured at all. The condition could not clear on its own, because the switch can never succeed while any reader exists.
What changed:
- AQE reads the current journal mode first and only attempts a change when it is actually wrong. Normal operation no longer needs the exclusive lock at all, so the one-time migration is out of the everyday path.
- Only genuine lock contention is treated as such. Other faults — I/O errors, corruption, permissions — now surface as themselves instead of being misreported as "something else is using the database".
- If the journal mode cannot be changed, AQE refuses to write rather than continuing in a mode you have declared unsafe. Availability is not worth risking the database you enabled the flag to protect.
- The change is verified after it is applied, so a silently ignored switch cannot leave AQE writing in the unsafe mode believing it is safe.
- The diagnostic now prints the exact command that lists whatever is holding the database, instead of naming processes it guessed at. The previous guidance pointed at the wrong ones, which is most of why this went unnoticed for days.
The bundled statusline also now refreshes every 60 seconds rather than every 5. It reopened the learning database on every tick, adding constant pressure to the same lock.
QE-Court's shipped panel violated its own writerIsNeverJuror rule (#576)
The bundled config.json — the template copied into every project on first run
— seated the defense on cognitum-low and the jury on cognitum-high. Those
are different tiers of the same vendor, and QE-Court measures collusion by
vendor, not tier. A brand-new project therefore got a panel that failed the
court's central rule before anyone had touched it.
The deeper problem was that the rule could not have caught it. Nothing converted
the configured routing into a seated panel, so validatePanel was never reached
outside its own unit test, and the options block in the config was not wired to
the validator at all — a rule with no caller is not enforced.
What changed:
- The default panel is genuinely cross-vendor. We moved the defense rather
than the jury: the deeper reviewer already runs on
codex, so re-seating the jury there would have put the jury and the escalation round on one vendor and weakened the overturn mechanic the court depends on. panelFromRouting()andvalidateCourtConfig()connect the config to the validator, and running the validation is now a required step before a court convenes — an invalid panel stops the run instead of quietly seating.- The
optionsblock takes effect:minDistinctVendorsandwriterIsNeverJurorare read rather than decorative. - A routing map with no jury is now reported as invalid instead of passing.
- CI validates the shipped config files themselves, so a future routing edit fails the build rather than a user's court.
Reported by @pacphi.
Upgrade notes
No action required. If you set AQE_DISABLE_WAL=1 and another process is
holding your learning database open, AQE will now refuse that connection with a
message naming the command that finds the holder — previously it failed silently.
If you have already customized .claude/skills/qe-court/config.json, your file
is untouched; check that your defense and jury providers are on different
vendors, as the court now enforces.