Let the garden keep what she was given, not only what she sought
Two halves of the same idea, both read out of work Petal already records. Planting: an accepted collocation is a learnable chunk, so it becomes a phrase card. The scheduler didn't need to know — a three-word chunk climbs the ladder exactly like a looked-up word. What needed care was deciding what *isn't* a chunk (single words are word choice; a six-word-plus "collocation" is a rewritten sentence, and sentences make miserable flashcards), and that the example must be the *corrected* sentence — the stored draft still holds the phrasing she just left behind. Re-accepting the same chunk leaves the existing card alone rather than resetting a schedule it has been climbing. The whole thing is best-effort: accepting an edit must never fail because a flashcard couldn't be made. The growth journal: kept this month beside kept the month before, the phrasing that stuck, the patterns that faded. The queries were the easy part; the honesty is the feature. "Stuck" needs the phrase in a *second* document, because one document is just the edit where she left it. "Faded" says nothing at all unless she has been writing lately — otherwise a month away from Petal comes back to her as progress, which is the one way this could lie. And a suggestion had to start recording when she *decided* it, not when the model proposed it, so 0012 adds resolved_at and backfills the old rows to their created_at. It lives as a second tab in the garden, and it feeds the kitten: after an accept she now sometimes hears something true of her alone, once per line, half the time, never waited for. Claude-Session: https://claude.ai/code/session_016y6gyuHkQXPiEuW8RGQyua
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
type Line,
|
||||
} from './tips'
|
||||
import { analyzeProse } from './prose'
|
||||
import { personalCheer, warmPersonalCheers } from './journalCheers'
|
||||
import { playPop, playSound, type SoundName } from '../../audio/sounds'
|
||||
import { isBedtime } from '../../lib/night'
|
||||
|
||||
@@ -197,7 +198,13 @@ export function useCompanion({ wordCount, saveStatus, llmDown, editTick, acceptT
|
||||
firstAccept.current = false
|
||||
return
|
||||
}
|
||||
say({ ...pick(encouragements()), tone: 'cheer' }, { celebrate: true })
|
||||
// Prefer something true of her own writing over a line that would fit
|
||||
// anybody — but only sometimes, so the personal ones stay a small surprise
|
||||
// rather than the new default. The journal is fetched on this first accept
|
||||
// and never awaited: the cheer goes out now, personal or not.
|
||||
warmPersonalCheers()
|
||||
const personal = Math.random() < 0.5 ? personalCheer() : null
|
||||
say({ ...(personal ?? pick(encouragements())), tone: 'cheer' }, { celebrate: true })
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [acceptTick])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user