Skip to content

taste profile: rejected preferences always have confidence 0 (broken show ranking + dead drift warning) #1776

@jbetala7

Description

@jbetala7

Observed problem

In bin/gstack-taste-update, every preference in a rejected bucket is permanently stored with confidence: 0. This makes the show output useless for rejections and silently disables the taste-drift conflict warning.

Root cause

bumpPref() computes confidence as approval rate for both buckets:

const total = entry.approved_count + entry.rejected_count;
entry.confidence = entry.approved_count / (total + 1);

A rejected-bucket entry only ever gets rejected_count incremented (the approved and rejected lists are disjoint — a value approved goes in approved, rejected goes in rejected). So approved_count stays 0 and confidence = 0 / (rejected_count + 1) = 0 no matter how many times the value is rejected.

Downstream effects:

  1. show display prints conf 0.00 for every rejected preference (bin/gstack-taste-update cmdShow).
  2. show ranking sorts rejections by confidence * rejected_count, which is 0 for all of them, so .slice(0, 3) returns insertion order instead of the strongest rejections.
  3. Taste-drift warning at if (opp && opp.approved_count + opp.rejected_count >= 3 && opp.confidence >= 0.6) is unreachable through real CLI use, because a rejected entry's confidence can never exceed 0. (The existing test test/taste-engine.test.ts only passes it by hand-seeding confidence: 0.8 via writeProfile, with a comment acknowledging the natural value is 0/5.)

Current behavior on upstream main (19770ea)

Reproduced with a temp state dir + git repo:

$ gstack-taste-update rejected v1 --reason "colors: crimson"   # x3
$ gstack-taste-update rejected vx --reason "colors: beige"     # x1
$ gstack-taste-update show
[colors]
  rejected:
    crimson — conf 0.00 (+0/-3)
    beige — conf 0.00 (+0/-1)

Both confidences are 0, and the profile JSON stores "confidence": 0 for both. A value rejected 3 times ranks no differently from one rejected once.

Expected behavior

A rejected preference's confidence should reflect rejection strength (symmetric with the approved bucket): rejected_count / (total + 1). After the fix, crimson (3 rejections) → conf 0.75, beige (1 rejection) → conf 0.50, the show ranking orders by strength, and the drift warning fires naturally after enough real rejections.

Duplicate searches performed

Candidate fix shape

In bumpPref(), compute confidence from this bucket's own count:

const total = entry.approved_count + entry.rejected_count;
const ownCount = action === 'approved' ? entry.approved_count : entry.rejected_count;
entry.confidence = ownCount / (total + 1);

This leaves approved-bucket confidence identical (for approved entries total === approved_count) and only fixes the rejected case. Add regression coverage for rejected confidence, the show ranking, and the drift warning firing from real CLI rejections.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions