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:
@@ -160,6 +160,19 @@ export interface Suggestion {
|
||||
created_at: string
|
||||
}
|
||||
|
||||
// The growth journal (GET /api/suggestions/growth). `kept`/`kept_before` are
|
||||
// the last thirty days and the thirty before them — the only comparison Petal
|
||||
// draws is with her own past self. `stuck` is phrasing she was given that now
|
||||
// turns up across her own documents; `faded` is what she used to be corrected
|
||||
// on and hasn't been lately. Both lists are empty when the data isn't there:
|
||||
// nothing here is padded to fill a page.
|
||||
export interface GrowthJournal {
|
||||
kept: number
|
||||
kept_before: number
|
||||
stuck: { phrase: string; docs: number }[]
|
||||
faded: { pattern: string; times: number }[]
|
||||
}
|
||||
|
||||
// A deterministic, rule-based fix detected client-side (see Companion/prose.ts).
|
||||
// The frontend owns mechanics detection; the backend only persists these as the
|
||||
// 'mechanics' suggestion family. Spans are exact plaintext offsets.
|
||||
@@ -267,6 +280,10 @@ export const api = {
|
||||
// opening bubble (the explanation itself stays English in the card body).
|
||||
translateSuggestion: (id: string) =>
|
||||
req<{ translation: string }>(`/suggestions/${id}/translate`, { method: 'POST' }),
|
||||
// The growth journal: her own accepted edits read back as patterns. Purely a
|
||||
// read-side view of a table Petal already keeps, computed locally with no
|
||||
// model call, so it costs nothing and leaves nothing.
|
||||
growth: () => req<GrowthJournal>('/suggestions/growth'),
|
||||
|
||||
// Version history. listVersions returns metadata only (no bodies); getVersion
|
||||
// loads one full snapshot for preview; snapshotDoc takes an explicit restore
|
||||
|
||||
Reference in New Issue
Block a user