diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 06d11d2e8..87692d294 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -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 `### ` 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)). diff --git a/packages/coding-agent/src/goals/runtime.ts b/packages/coding-agent/src/goals/runtime.ts index 8e7dd43ff..000ae3bd8 100644 --- a/packages/coding-agent/src/goals/runtime.ts +++ b/packages/coding-agent/src/goals/runtime.ts @@ -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; diff --git a/packages/coding-agent/test/goals/goal-runtime.test.ts b/packages/coding-agent/test/goals/goal-runtime.test.ts index c4af4b8e2..73c31f541 100644 --- a/packages/coding-agent/test/goals/goal-runtime.test.ts +++ b/packages/coding-agent/test/goals/goal-runtime.test.ts @@ -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: {