45b5e16eff
Things arrive at Maven from eight directions — a relayed Android notification on POST /api/ambient, mail candidates from mavmaild, RSS items, changed pages from the crawler, zenmoney and wg reads from mavpoll, CalDAV events, presence probes, meeting transcripts and image descriptions. Each grew its own shape and its own log line, and nothing could answer "what came in today, from where". internal/event is that answer: a flat source-agnostic envelope (Source, Kind, EntityIDs, Title, Body, Priority, OccurredAt, Payload) plus a bounded in-memory journal. Both are pure — Publish and Normalize take `now` as a parameter, so no clock read sits on a path a replay would drive. Adopting it did not touch eight callers, because every intake path already converges on three ipc.CoreAPI methods: WriteFact, WriteNote and CaptureTask. cmd/mavend/intake.go decorates that ONE interface, so mavweb, mavcaldav, mavpoll, mavmaild and the in-core feed/crawl/capture/ vision workers publish envelopes without knowing events exist. The lone exception is cmd/mavend/mail.go, which captures through the store directly and now publishes explicitly. Nothing dispatches on an event. It is a report that something arrived, never an instruction to speak — "a feed item appeared" becoming a notification is the nag this repo refuses. Digestion may read the journal later; it will still go through internal/loop's rules and the severity/presence routing table. Read surface: ipc.MethodRecentEvents (AuthRead, daemon-cached like TickTrace — a bare store cannot serve a ring) and a read-only /events page in mavweb. Production is unchanged when nobody is watching: a nil *event.Bus makes Publish a no-op and newIntakeAPI returns the wrapped API untouched, so config.intake_journal < 0 leaves no decorator on the call path at all. The default is 512 entries; the "off unless configured" rule is for capabilities that reach out, and a bounded in-memory log of writes core already performed reaches nowhere. Verified: make build, make test (go test -race) both clean. New tests cover the envelope and ring (internal/event, 95.7%), the decorator's invariants — a failed write publishes nothing, a deduped capture publishes nothing, OccurredAt is the fact's Ts and not notice time — and the /events page including escaping of feed-supplied titles.
137 lines
5.8 KiB
Go
137 lines
5.8 KiB
Go
package ipc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
// ErrNotImplemented is returned by every UnimplementedCoreAPI method. It is
|
|
// deliberately distinct from ErrUnknownMethod (a wire-level "no such
|
|
// method exists" verdict) and from any daemon-level "locked" error: this one
|
|
// means "this method exists on CoreAPI, but the fake/adapter embedding
|
|
// UnimplementedCoreAPI never got a real implementation for it." A test that
|
|
// exercises an undeclared method fails loudly on this text instead of
|
|
// silently nil-panicking or being mistaken for a legitimate failure.
|
|
var ErrNotImplemented = errors.New("ipc: not implemented (unimplemented CoreAPI stub)")
|
|
|
|
// UnimplementedCoreAPI is the gRPC Unimplemented*Server pattern applied to
|
|
// CoreAPI: embed it in a test double or adapter and override only the
|
|
// methods you actually exercise. Every method returns ErrNotImplemented, so
|
|
// a call that reaches an undeclared method fails loudly and specifically,
|
|
// rather than compiling to a silent no-op or nil-pointer panic. This
|
|
// replaces the old pattern of hand-writing all 30 no-op stubs per double —
|
|
// those were compiler-satisfying padding, not tests of anything.
|
|
type UnimplementedCoreAPI struct{}
|
|
|
|
var _ CoreAPI = UnimplementedCoreAPI{}
|
|
|
|
func (UnimplementedCoreAPI) WriteFact(ctx context.Context, req WriteFactReq) (int64, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) LatestFact(ctx context.Context, key string) (Fact, error) {
|
|
return Fact{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) LatestFactBySource(ctx context.Context, key, source string) (Fact, error) {
|
|
return Fact{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) Since(ctx context.Context, key string, now time.Time) (time.Duration, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) Presence(ctx context.Context) (Presence, error) {
|
|
return Presence{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) CreateReminder(ctx context.Context, fire time.Time, payload, cron string) (int64, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) MarkReminder(ctx context.Context, id int64, status string) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecordNudge(ctx context.Context, rule, channel, message string, ts time.Time) (int64, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ResolveNudge(ctx context.Context, id int64, outcome string, ts time.Time) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecentOutcomes(ctx context.Context, rule string, n int) ([]string, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecentNudges(ctx context.Context, n int) ([]Nudge, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) WriteNote(ctx context.Context, ts time.Time, text string, embedding []float32, source string) (int64, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) QueryNotes(ctx context.Context, embedding []float32, k int) ([]Note, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecentNotes(ctx context.Context, n int) ([]Note, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ProposeTool(ctx context.Context, name, utterance, scope string, ts time.Time) (bool, error) {
|
|
return false, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) EnableTool(ctx context.Context, name string, cmd []string, destructive bool, scope string, ts time.Time) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) DisableTool(ctx context.Context, name string) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) DeleteTool(ctx context.Context, name string) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) CaptureTask(ctx context.Context, req CaptureTaskReq) (CaptureTaskResp, error) {
|
|
return CaptureTaskResp{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ListTasks(ctx context.Context, status string) ([]Task, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) SetTaskStatus(ctx context.Context, id int64, status string, ts time.Time) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ListProposedRoutines(ctx context.Context) ([]ProposedRoutine, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) DismissProposedRoutine(ctx context.Context, id int64) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) AcceptProposedRoutine(ctx context.Context, id int64) error {
|
|
return ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) LookupTool(ctx context.Context, name string) (Tool, error) {
|
|
return Tool{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) ListTools(ctx context.Context, status string) ([]Tool, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RevertFact(ctx context.Context, key string) (int64, error) {
|
|
return 0, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) TickTrace(ctx context.Context) (TickTrace, error) {
|
|
return TickTrace{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) MorningStatus(ctx context.Context) ([]MorningRoutineStatus, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) RecentEvents(ctx context.Context, n int) ([]IntakeEvent, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) MCPServers(ctx context.Context) ([]MCPServerStatus, error) {
|
|
return nil, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) DayPlan(ctx context.Context) (DayPlan, error) {
|
|
return DayPlan{}, ErrNotImplemented
|
|
}
|
|
func (UnimplementedCoreAPI) Chat(ctx context.Context, text string) (string, error) {
|
|
return "", ErrNotImplemented
|
|
}
|