memory: count habits over self facts only, and skip retracted ones

The behaviour profile read the newest 2000 rows of the shared facts table and
then discarded everything that was not kind=self, so the length of the window
was set by the noisiest writer. mavpoll writes a wg_handshake row every time a
peer rehandshakes, about every two minutes per peer, which is enough to reduce
2000 rows to under three days. A weekday habit needs two distinct Tuesdays, so
that window can never hold one, and she answered that she knows no habits on a
store holding a year of taps.

RecentActiveFactsByKind filters kind in SQL, and also drops rows a later row
voids along with the void marker itself. The old read counted both a retracted
tap and its retraction, so a fact he explicitly took back still shaped what she
said he usually does. A correction still counts, because a correction is a value
he stands behind.

Found in review of #59.
This commit is contained in:
kami
2026-08-01 14:00:46 +04:00
parent 88c841cb0e
commit 012bdcc1ae
9 changed files with 166 additions and 5 deletions
+5
View File
@@ -439,6 +439,10 @@ type outcomesReq struct {
type nReq struct {
N int `json:"n"`
}
type kindNReq struct {
Kind string `json:"kind"`
N int `json:"n"`
}
type calendarEventsReq struct {
From time.Time `json:"from"`
To time.Time `json:"to"`
@@ -586,6 +590,7 @@ type CoreAPI interface {
ResolveNudge(ctx context.Context, id int64, outcome string, ts time.Time) error
RecentOutcomes(ctx context.Context, rule string, n int) ([]string, error)
RecentFacts(ctx context.Context, n int) ([]Fact, error)
RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error)
CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error)
RecentNudges(ctx context.Context, n int) ([]Nudge, error)
WriteNote(ctx context.Context, ts time.Time, text string, embedding []float32, source string) (int64, error)
+9
View File
@@ -62,6 +62,7 @@ var readOnlyMethods = map[Method]bool{
MethodListReminders: true,
MethodRecentOutcomes: true,
MethodRecentFacts: true,
MethodRecentActiveFacts: true,
MethodCalendarEvents: true,
MethodRecentNudges: true,
MethodQueryNotes: true,
@@ -334,6 +335,14 @@ func (c *Client) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
return out, nil
}
func (c *Client) RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error) {
var out []Fact
if err := c.call(ctx, MethodRecentActiveFacts, kindNReq{Kind: kind, N: n}, &out); err != nil {
return nil, err
}
return out, nil
}
func (c *Client) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
var out []Fact
if err := c.call(ctx, MethodCalendarEvents, calendarEventsReq{From: from, To: to}, &out); err != nil {
+22
View File
@@ -120,6 +120,18 @@ func (a *storeAPI) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
return out, nil
}
func (a *storeAPI) RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error) {
fs, err := a.s.RecentActiveFactsByKind(ctx, store.FactKind(kind), n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Fact, len(fs))
for i, f := range fs {
out[i] = toFact(f)
}
return out, nil
}
func (a *storeAPI) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
fs, err := a.s.CalendarEvents(ctx, from, to)
if err != nil {
@@ -764,6 +776,16 @@ var methodTable = map[Method]handlerFunc{
}
return out, nil
}),
MethodRecentActiveFacts: withParams(func(ctx context.Context, api CoreAPI, p kindNReq) ([]Fact, error) {
out, err := api.RecentActiveFactsByKind(ctx, p.Kind, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Fact{}
}
return out, nil
}),
MethodCalendarEvents: withParams(func(ctx context.Context, api CoreAPI, p calendarEventsReq) ([]Fact, error) {
out, err := api.CalendarEvents(ctx, p.From, p.To)
if err != nil {
+3
View File
@@ -62,6 +62,9 @@ func (UnimplementedCoreAPI) RecentOutcomes(ctx context.Context, rule string, n i
func (UnimplementedCoreAPI) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
return nil, ErrNotImplemented
}
func (UnimplementedCoreAPI) RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error) {
return nil, ErrNotImplemented
}
func (UnimplementedCoreAPI) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
return nil, ErrNotImplemented
}
+1
View File
@@ -25,6 +25,7 @@ const (
MethodResolveNudge Method = "resolve_nudge"
MethodRecentOutcomes Method = "recent_outcomes"
MethodRecentFacts Method = "recent_facts"
MethodRecentActiveFacts Method = "recent_active_facts_by_kind"
MethodCalendarEvents Method = "calendar_events"
MethodRecentNudges Method = "recent_nudges"
MethodWriteNote Method = "write_note"