Skip to content

feat: smart nudge gating — soft-block + recommendation filtering - #142

Merged
ranxianglei merged 13 commits into
masterfrom
2026-07-15_smart-nudge-gating
Jul 15, 2026
Merged

ranxianglei merged 13 commits into
masterfrom
2026-07-15_smart-nudge-gating

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Summary

Three improvements to compression recommendation behavior:

  1. Soft-block on last segment (Req 1) — First compress attempt covering the most recent message is rejected with a confirmation prompt. The lastMessageId is persisted in Nudges.lastSegmentConfirmAttempts. Retry (same lastMessageId) succeeds. Configurable via compress.lastSegmentSoftBlock (default: true).

  2. Single-message range filtering (Req 2) — Single-message ranges excluded from recommendation unless tokens > 5× growth threshold (25% of context at 5% config).

  3. Protected dominance filtering (Req 3) — Suppresses all recommendations when: besides last range all others protected, 70%+ protected, or remaining compressible < 5% of context. Huge single segment (> 25%) overrides.

Files Changed

  • State: lib/state/{types,state,persistence,utils}.tslastSegmentConfirmAttempts field
  • Config: lib/config.tslastSegmentSoftBlock?: boolean option
  • Compress: lib/compress/{pipeline,range,message}.ts — soft-block logic
  • Inject: lib/messages/inject/{utils,inject}.tsfilterRecommendedRanges()
  • Tests: 20 new tests + 6 existing test files updated

Test Results

  • TypeScript: 0 errors
  • Build: dist/index.js 397KB
  • Tests: 708/708 pass (688 existing + 20 new)

ranxianglei and others added 13 commits July 15, 2026 01:37
…racking

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…y succeeds

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…dominated recommendations

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…compat

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…parameter

Switches from two-attempt state tracking (lastSegmentConfirmAttempts) to
explicit opt-in via `dangerous: true` parameter. Removing all state
infrastructure for the soft-block — the check is now completely stateless.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…rous flag

Replaces old rules (5x huge threshold, single-msg filter, protected dominance checks) with a single coherent design:
- Last segment: excluded if < 2x growth threshold; included with dangerous flag if >= 2x
- Gate: effective compressible = non-last + max(0, last - 2x floor); suppress all if < growth threshold
- Protected ranges no longer affect filtering logic
- formatCompressibleRanges uses dangerous flag instead of position for annotation

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ve compressible gate)

smart-nudge-gating.test.ts: complete rewrite with 17 tests covering last-segment floor, effective compressible gate, dangerous flag propagation, and 200K proportional thresholds.
inject.test.ts: increase tool output data from 120K to 320K chars so ranges pass the new 100K last-segment floor.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
FiltersRecommendedRanges now logs input ranges, thresholds, last-segment analysis, effective compressible, and final suppression decision to the daily debug log.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…age when debug=true

Uses the existing sendIgnoredMessage mechanism (ignored: true, noReply: true) to display the filter decision in the conversation UI without sending it to the model. Shows input ranges, thresholds, last-segment analysis, effective compressible, and suppression decision.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…rwrite on restart

opencode resolves @latest against the npm registry on startup. If the local cache version is older than npm's latest, it re-downloads and silently overwrites local deploys. The deploy script now queries npm view and bumps the deployed package.json version to npm+1patch when local <= npm.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant