Skip to content

feat(routing): let a refusal outlive the session, and fade - #81

Merged
tanglearncode merged 1 commit into
mainfrom
routing-decline-decay
Aug 8, 2026
Merged

tanglearncode merged 1 commit into
mainfrom
routing-decline-decay

Conversation

@tanglearncode

Copy link
Copy Markdown
Contributor

A refusal was forgotten the moment the window closed. It is the clearest signal a user ever gives about routing, and it was being thrown away.

What changes

A refusal now survives the session — as evidence, not as a rule.

when what happens
rest of the session unchanged: that context is not raised again, full stop
after that a discount on its score, halving every two weeks
about six weeks gone, and the record is dropped
refused again the clock restarts and the penalty deepens

The escalation on repeats is the one a browser uses for a permission prompt dismissed several times over: once is noise, three times is an answer.

Two deliberate limits

A refused context drops down the shortlist, never off it. The same request should reach it again eventually — just not today, and not without better evidence. Hiding it would turn a guess about the user into a fact about the store.

The multiplier never reaches zero, however many refusals there have been, and records are pruned once too old to matter. The only permanent "no" in this plugin is manual mode, because that one is a decision the user made on purpose. A guess the system made about someone should not harden into a rule.

Where it is applied

After ranking, not folded into the index. Refusals change on their own schedule, and rebuilding the index every time someone says no would throw away the cache for a multiplier. The results are re-sorted afterwards, since a discount can change the order and the shortlist's whole meaning is that it is in order.

Tests

14 new. The decay curve is pinned at each point that matters — the day it happens, two weeks (half the strength), six weeks (nothing), repeats deepening, and the floor above zero. Plus the recording path: kept beyond its session, repeats counted, works with no session to attribute it to, old records pruned from the file, and a hand-broken file still yields a usable state rather than failing the session.

The two that matter most are on a shortlist of two identically-described contexts, where nothing but the refusal can separate them: the refused one is demoted and still present, and once expired the two score equal again.

Diff coverage: 105 changed lines, 0 uncovered. Full suite 423 passing.

Scope

This is decision 6 from the design. The remaining priors — workspace binding, frecency, and switch hysteresis — are the last piece and are their own change.

A refusal was forgotten the moment the window closed. It is the clearest
signal a user ever gives about routing, and it was being thrown away.

It now survives, as evidence rather than as a rule. Strength halves every
two weeks and is negligible by six; refusing the same context again
restarts the clock and deepens the penalty, which is the escalation a
browser uses for a permission prompt dismissed several times over. Once
is noise, three times is an answer.

Inside the session that produced it a refusal still means exactly what it
meant before: that context is not raised again, full stop. Outside it,
the effect is a discount on the score, so a refused context drops down
the shortlist rather than off it — the same request should reach it
again eventually, just not today and not without better evidence.

The discount is applied after ranking rather than folded into the index,
because refusals change on their own schedule and rebuilding the index
for a multiplier would throw away the cache for nothing.

Nothing here becomes permanent: the multiplier never reaches zero however
many refusals there have been, and records are dropped once they are too
old to change an outcome. The only permanent no in this plugin is manual
mode, which is a decision the user made on purpose.
@tanglearncode
tanglearncode merged commit 2de9820 into main Aug 8, 2026
11 checks passed
@tanglearncode tanglearncode mentioned this pull request Aug 9, 2026
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