Merge PR #2586: fix(goals): avoid deactivating goal mode on wall-clock-only updates

Closes #2586
This commit is contained in:
can1357
2026-06-15 02:39:39 +02:00
3 changed files with 22 additions and 1 deletions
+1
View File
@@ -164,6 +164,7 @@
- Replaced the `omp bench` default prompt with a concrete query-planning trace that requires deriving selectivities, cardinalities, and I/O/CPU costs from given schema and data. The old prompt was open-ended prose recall, which rewarded not-thinking: adaptive-thinking models (Opus 4.6+/Sonnet 4.6+) minimized reasoning on the trivial task and streamed faster, skewing throughput comparisons. The new task forces multi-step reasoning so adaptive thinking engages and the benchmark measures generation under real cognitive load. The prompt also demands explicit upfront deliberation and exhaustive enumeration/costing of every join order, so adaptive-thinking models cannot short-circuit to a quick answer and each model is measured over a sustained generation up to the token cap.
### Fixed
- Fixed a bug where goal mode was incorrectly deactivated/set to 'none' on every wall-clock-only update (when tokenDelta <= 0) during tool execution flushes, preventing OMP from writing a mode change to 'none' in the session history database while keeping in-memory/UI state fresh.
- Fixed Kokoro TTS setup loading the workspace/global `@huggingface/transformers` runtime before the side-installed Kokoro runtime, which could leave `onnxruntime-node@1.26.0` bound to an older `libonnxruntime.so.1` and fail with `VERS_1.26.0` missing ([#2591](https://github.com/can1357/oh-my-pi/issues/2591)).
- Fixed `scripts/ci-release-notes.ts` stranding curated changelog entries from intervening *silent* tags (a `vX.Y.Z` tag pushed without a GitHub Release, e.g. the `v15.12.5`/`v15.12.6` casualties of the pre-#2564 release-cancellation bug). The generator now walks `(latest-published-release, target]` — resolved via `gh release list` from the `release_github` CI job — and merges every in-range `## [X.Y.Z]` section per package, grouped by `### <category>` with bullet-level dedupe so post-release changelog flattening cannot duplicate entries. Falls back to the legacy single-version extraction when no prior published release resolves, and `OMP_RELEASE_NOTES_FLOOR=v15.12.4` overrides the lookup for manual rebuilds ([#2596](https://github.com/can1357/oh-my-pi/issues/2596)).
+4 -1
View File
@@ -356,7 +356,10 @@ export class GoalRuntime {
this.#wallClock.lastAccountedAt += wallSeconds * 1000;
}
await this.#commitState(state, { persist: "goal" });
// Persisting wall-clock-only accounting on every tool event bloats /goal sessions with full
// objective snapshots. Keep the in-memory/UI state fresh, but persist only token/budget changes.
const shouldPersistUsage = tokenDelta > 0 || flippedToBudgetLimited;
await this.#commitState(state, { persist: shouldPersistUsage ? "goal" : undefined });
if (state.goal.status !== "budget-limited") {
this.#budgetReportedFor = undefined;
@@ -118,6 +118,7 @@ describe("goal runtime", () => {
harness.runtime.onTurnStart("turn-1", createUsage());
harness.advance(2_500);
harness.setUsage(createUsage({ input: 1 }));
await harness.runtime.flushUsage("suppressed");
expect(harness.getState()?.goal.timeUsedSeconds).toBe(2);
expect(harness.runtime.snapshot.wallClock.lastAccountedAt).toBe(2_000);
@@ -130,12 +131,28 @@ describe("goal runtime", () => {
expect(harness.persists).toHaveLength(1);
harness.advance(700);
harness.setUsage(createUsage({ input: 2 }));
await harness.runtime.flushUsage("suppressed");
expect(harness.getState()?.goal.timeUsedSeconds).toBe(3);
expect(harness.runtime.snapshot.wallClock.lastAccountedAt).toBe(3_000);
expect(harness.persists).toHaveLength(2);
});
it("does not persist snapshots on wall-clock-only flushes", async () => {
const harness = createHarness({
state: { enabled: true, mode: "active", goal: createGoal() },
});
harness.runtime.onTurnStart("turn-1", createUsage());
harness.advance(2_500);
// Flush wall-clock time without any token usage changes.
await harness.runtime.flushUsage("suppressed");
// The in-memory state should still be updated.
expect(harness.getState()?.goal.timeUsedSeconds).toBe(2);
// But it should not write/persist to the session log.
expect(harness.persists).toHaveLength(0);
});
it("steers only once until a budget mutation resets the cycle", async () => {
const harness = createHarness({
state: {