Prune interval created inside hook was not exposed for disposal,
preventing cleanup on plugin unload.
- Add dispose() method that clears the prune interval
- Export dispose in hook return type
Tests: 2 pass, 6 expects
setInterval for model availability monitoring was never cleared,
keeping the hook alive indefinitely with no dispose mechanism.
- Add dispose() method to RuntimeFallbackHook that clears interval
- Track intervalId in hook state for cleanup
- Export dispose in hook return type
Tests: 3 pass, 10 expects
Sync call_omo_agent leaked entries in global activeSessionMessages
and activeSessionToolResults Sets when execution threw errors,
since cleanup only ran on success path.
- Wrap session Set operations in try/finally blocks
- Ensure Set.delete() runs regardless of success/failure
- Add guard against double-cleanup
Tests: 2 pass, 14 expects
processedCommands and recentResults Sets grew infinitely because
Date.now() in dedup keys made deduplication impossible and no
session.deleted cleanup existed.
- Extract ProcessedCommandStore with maxSize cap and TTL-based eviction
- Add session cleanup on session.deleted event
- Remove Date.now() from dedup keys for effective deduplication
- Add dispose() for interval cleanup
Tests: 3 pass, 9 expects
- Replace overly broad .includes('anthropic') with exact provider ID
matching against known Anthropic providers (anthropic, google-vertex-
anthropic, aws-bedrock-anthropic) in context-limit-resolver
- Add afterEach cleanup for vision-capable-models cache in look-at
tool tests to prevent cross-test state leakage
When users switch from pinned version to tag in opencode.json (e.g.,
3.10.0 -> @latest), the cache package.json still contains the resolved
version. This causes bun install to reinstall the old version instead
of resolving the new tag.
This adds syncCachePackageJsonToIntent() which updates the cache
package.json to match user intent before running bun install. Uses
atomic writes (temp file + rename) with UUID-based temp names for
concurrent safety.
Critical changes:
- Treat all sync errors as abort conditions (file_not_found,
plugin_not_in_deps, parse_error, write_error) to prevent corrupting
a bad cache state further
- Remove dead code (unreachable revert branch for pinned versions)
- Add tests for all error paths and atomic write cleanup
- New context-limit-resolver.ts with resolveActualContextLimit() shared helper
- Anthropic provider detection now uses .includes('anthropic') instead of hard-coded IDs
- Both context-window-monitor and dynamic-truncator use the shared resolver
- Added missing test cases: Anthropic+1M disabled+cached limit, non-Anthropic without cache
- Check response.error and !response.data after session.get() to fail closed
- Prevents unlimited spawning when SDK returns non-throwing error responses
- Added regression tests for SDK error and missing data scenarios
- Import and inject buildAntiDuplicationSection() in all 3 Prometheus variants (interview-mode, gpt, gemini) and Metis
- Added tests verifying anti-dup section presence in all prompt variants
- Completes anti-duplication coverage for all delegating agents
- parseInteger() now rejects malformed input like '120oops' using /^\d+$/ regex
- New parseActiveValue() validates active flag is exactly '0' or '1'
- Added regression tests for malformed integers, negative values, empty fields, non-binary active flags
Resume GPT sessions when the last assistant reply ends in a permission-seeking tail, while honoring stop-continuation and avoiding duplicate continuation across todo and atlas flows.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>