Prevent cross-file mock.module leakage by restoring Bun mocks after recovery-hook test, so executor tests always run against the real module implementation.
Stop patching global timers in every lock-management test. Use scoped fake timers only in continuation tests so lock/notification assertions remain deterministic in CI.
- getSdkMessages now handles both response.data and direct array
responses from SDK
- Consolidated getMessageDir: storage.ts now re-exports from shared
opencode-message-dir.ts (with path traversal guards)
- Replace all response.data ?? [] with (response.data ?? response)
pattern across 14 files to handle SDK array-shaped responses
- Normalize SDK parts in parts-reader.ts by injecting sessionID/
messageID before validation (P1: SDK parts lack these fields)
- Treat unknown part types as having content in
recover-empty-content-message-sdk.ts to prevent false placeholder
injection on image/file parts
- Replace local isRecord with shared import in parts-reader.ts
- P1: Use compacted timestamp check instead of nonexistent truncated
field in target-token-truncation.ts
- P1: Use defensive (response.data ?? response) pattern in
hook-message-injector/injector.ts to match codebase convention
- P2: Filter by tool type in countTruncatedResultsFromSDK to avoid
counting non-tool compacted parts
- P2: Treat thinking/meta-only messages as empty in both
empty-content-recovery-sdk.ts and message-builder.ts to align
SDK path with file-based logic
- P2: treat unknown part types as non-content in message-builder messageHasContentFromSDK
- P3: reuse shared isRecord from record-type-guard.ts in opencode-http-api
Unknown part types should be treated as content (return true)
to match parity with the existing message-builder implementation.
Using continue would incorrectly mark messages with unknown part
types as empty, triggering false recovery.
- isTodo: allow optional id to match Todo interface, preventing
todos without ids from being silently dropped
- messageHasContentFromSDK: treat unknown part types as empty
(continue) instead of content (return true) for parity with
existing storage logic
- readMessagesFromSDK in recover-empty-content-message-sdk: wrap
SDK call in try/catch to prevent recovery from throwing
- target-token-truncation: eliminate redundant SDK messages fetch by
extracting tool results from already-fetched toolPartsByKey map
- recover-thinking-block-order: wrap SDK message fetches in try/catch
so recovery continues gracefully on API errors
- thinking-strip: guard against missing part.id before calling
deletePart to prevent invalid HTTP requests
- executeDeduplication: now async, reads messages from SDK on SQLite via
client.session.messages() instead of JSON file reads
- truncateToolOutputsByCallId: now async, uses truncateToolResultAsync()
HTTP PATCH on SQLite instead of file-based truncateToolResult()
- deduplication-recovery: passes client through to both functions
- recovery-hook: passes ctx.client to attemptDeduplicationRecovery
Removes the last intentional feature gap on SQLite backend — dynamic
context pruning (dedup + tool-output truncation) now works on both
JSON and SQLite storage backends.
- Use shared OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE constants
- Make isCallerOrchestrator async with SDK fallback for beta
- Fix cache implementation using Symbol sentinel
- Update atlas hooks and sisyphus-junior-notepad to use async isCallerOrchestrator
- Make id field optional in all Todo interfaces (TodoInfo, Todo, TodoItem)
- Fix null-unsafe comparisons in todo-sync.ts to handle missing ids
- Add test case for todos without id field preservation
- All tests pass and typecheck clean
* fix: exclude prompt/permission from plan agent config
plan agent should only inherit model settings from prometheus,
not the prompt or permission. This ensures plan agent uses
OpenCode's default behavior while only overriding the model.
* test(todo-continuation-enforcer): use FakeTimers for 15x faster tests
- Add custom FakeTimers implementation (~100 lines)
- Replace all real setTimeout waits with fakeTimers.advanceBy()
- Test time: 104.6s → 7.01s
* test(callback-server): fix race conditions with Promise.all and Bun.fetch
- Use Bun.fetch.bind(Bun) to avoid globalThis.fetch mock interference
- Use Promise.all pattern for concurrent fetch/waitForCallback
- Add Bun.sleep(10) in afterEach for port release
* test(concurrency): replace placeholder assertions with getCount checks
Replace 6 meaningless expect(true).toBe(true) assertions with
actual getCount() verifications for test quality improvement
* refactor(config-handler): simplify planDemoteConfig creation
Remove unnecessary IIFE and destructuring, use direct spread instead
* test(executor): use FakeTimeouts for faster tests
- Add custom FakeTimeouts implementation
- Replace setTimeout waits with fakeTimeouts.advanceBy()
- Test time reduced from ~26s to ~6.8s
* test: fix gemini model mock for artistry unstable mode
* test: fix model list mock payload shape
* test: mock provider models for artistry category
---------
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
- Delete src/hooks/preemptive-compaction/ entirely
- Remove dcp_for_compaction from schema and executor
- Clean up related imports, options, and test code
- Update READMEs to remove experimental options docs