mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
b2e6090c6d
* feat(hooks): post-route Stop hook closes route sentinels 1:1 (#451) The `route` hook fires on UserPromptSubmit and writes a sentinel row to routing_outcomes with quality_score=-1, expecting `post-task` to close it. But `post-task` only fires on PostToolUse ^(Task|Agent)$, which is rare in direct-work sessions (Bash/Edit/Read without spawning sub- agents). Sentinels accumulated indefinitely — Jordi reported 123+ unresolved rows per session. Stream D never converged. Changes: 1. New `aqe hooks post-route` subcommand (src/cli/commands/hooks-handlers/routing-hooks.ts) Closes the most-recent unresolved route sentinel using a `task_json NOT LIKE '%"taskId"%'` discriminator that isolates route entries from pre-task entries. Quality formula collapses the 6-dim outcome formula for unknown duration: 0.325 + 0.25·success + 0.10·1.0 = 0.675 (success) / 0.425 (failure) 2. Inverse discriminator on updateRoutingOutcomeQuality (src/cli/commands/hooks-handlers/hooks-dream-learning.ts) Added `task_json LIKE '%"taskId"%'` to the WHERE clause so post-task only ever closes pre-task sentinels. Without this, post-task could grab a stale route sentinel by accident and miscredit duration to a row that wasn't about a Task() call. Symmetric counterpart to the post-route filter. 3. Stop-hook wiring in both init template paths (src/init/phases/07-hooks.ts + src/init/init-wizard-hooks.ts) Added `npx agentic-qe hooks post-route --success true --json` to the Stop block. Timeout 5000ms, continueOnError: true, so a failed post-route cannot block session teardown. 4. CLI help text (src/cli/commands/hooks.ts) Added example for the new subcommand. 5. Regression test (tests/unit/cli/commands/post-route.test.ts) 4 tests using in-memory better-sqlite3: - Closes most-recent route sentinel; leaves pre-task sentinels and resolved rows untouched - quality_score = 0.425 when --success false - No-op when only pre-task sentinels exist (discriminator works) - No-op on second invocation when only one sentinel was outstanding Bug-introduce verification: stashed routing-hooks.ts, ran new test — all 4 cases failed (Commander rejects unknown subcommand). Restored fix, all 4 pass. Test distinguishes pre-fix and post-fix states. Co-authored-by: Jordi Izquierdo <noreply@github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(release): bump version to v3.9.25 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.4 KiB
3.4 KiB
v3.9.25 Release Notes
Release Date: 2026-05-12
Highlights
Closes the routing_outcomes sentinel that route hooks (UserPromptSubmit) wrote but nothing reliably closed. In direct-work sessions (Bash/Edit/Read, no Task/Agent sub-agents) the sentinel sat at quality_score=-1 indefinitely — Jordi observed 123+ unresolved rows per session. New post-route subcommand wired into the Stop hook closes them 1:1 with each turn. Stream D can finally converge.
Added
aqe hooks post-route(#451) — Stop-hook counterpart to UserPromptSubmit/route. Closes the most-recent unresolved route sentinel using atask_json NOT LIKE '%"taskId"%'discriminator that isolates route entries from pre-task entries. Quality formula collapses the 6-dim outcome formula for an unknown duration:0.325 + 0.25·success + 0.10 = 0.675on success /0.425on failure.- Wired into both init template paths —
src/init/phases/07-hooks.ts(the auto/main init flow) andsrc/init/init-wizard-hooks.ts(the wizard flow) both gain a newStopblock entry:npx agentic-qe hooks post-route --success true --json. Timeout 5000ms,continueOnError: true, so a failedpost-routecannot block session teardown.
Fixed
- Route sentinels accumulated at
quality_score=-1forever (#451). Theroutehook fired on UserPromptSubmit and wrote a sentinel row, expectingpost-taskto fill it in. Butpost-taskonly fires onPostToolUse ^(Task|Agent)$, which is rare in direct-work sessions. Sentinels stayed open and any consumer readingrouting_outcomeswithout aquality_score >= 0filter sawsuccess=0(sentinel value) as if every turn had failed. updateRoutingOutcomeQualitycould close the wrong sentinel (#451). Prior to this release, the post-task UPDATE picked the most-recent unresolved row within 30 minutes biased onused_agent, with no discriminator separating route sentinels from pre-task sentinels. When dozens of route sentinels were sitting around, post-task could close one of those instead of the actual pre-task sentinel it had just written. Added the inverse discriminatortask_json LIKE '%"taskId"%'— post-task now only closes pre-task sentinels, symmetric with the newpost-routefilter.
Verification
npm run build— clean.npm run typecheck— clean.npx vitest run tests/unit/cli/ tests/unit/learning/qe-hooks.test.ts tests/hooks/task-completed-hook.test.ts tests/unit/init/phases— 833 / 833 passing across 30 files, including the newpost-route.test.ts(4 tests).- Bug-introduce verification: stashed
routing-hooks.ts, re-ran new test — all 4 cases failed (Commander rejects the unknown subcommand). Restored the fix, all 4 pass. The test correctly distinguishes pre-fix and post-fix states.
Upgrade Notes
- No breaking changes. After upgrading and re-running
aqe init, theStophook gains apost-routeinvocation that closes the route sentinel 1:1 with each turn. - Existing installs continue working but won't close route sentinels until
aqe initis re-run. The chronic-flake symptom (123+ unresolved sentinels per session) will continue until the Stop hook is wired. - Resolved sentinels on disk from prior versions are not retroactively adjusted — they stay at
quality_score=-1until cleanup or natural expiry. New turns get the correct quality_score on session end.
Thanks to @Jordi-Izquierdo-DDS for the diagnosis, evidence, and patch shape.