capture

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package capture is the episodic tier: sampling, coalescing, storage and retention.

The event record itself lives in internal/event so that this package and the sources it drives can share it without an import cycle. These aliases keep capture.Event working as the natural spelling at call sites.

Index

Constants

View Source
const (
	Focus     = event.Focus
	URL       = event.URL
	File      = event.File
	Commit    = event.Commit
	Calendar  = event.Calendar
	Clipboard = event.Clipboard
	Screen    = event.Screen
)
View Source
const IncidentalSecs = event.IncidentalSecs
View Source
const Schema = `` /* 570-byte string literal not displayed */

Schema lives in the same SQLite file as the vault index but is conceptually separate: the index is a cache derived from markdown, this is primary data that exists nowhere else. That is why retention is a deliberate setting rather than a cleanup detail.

Variables

View Source
var DefaultBlocklist = []string{
	"1Password", "Bitwarden", "KeePassXC", "Keychain Access",
	"Messages", "Signal", "WhatsApp", "Telegram",
	"Mail", "FaceTime", "System Settings",
}

DefaultBlocklist is seeded with the categories never worth recording. The user's own additions are appended from config.

View Source
var Now = event.Now

Functions

func Count

func Count(db *sql.DB) (int, error)

func Cursor

func Cursor(db *sql.DB, source string) int64

func Dur

func Dur(secs int64) string

func Footprint

func Footprint(db *sql.DB) (events int, bytes int64, days float64, err error)

Footprint is what raw capture currently costs, measured rather than guessed.

A user deciding whether to leave the daemon running deserves a number, and the only honest number is one taken from their own data: how much text their own apps and URLs actually produce. Bytes is the stored text plus a fixed allowance for the integer columns and row overhead — close enough to size a disk budget, and never presented as exact.

Days is how long the existing events span. It is the reason this returns a span at all: with less than a day of data there is nothing to extrapolate from, and saying so is better than projecting a week from ten minutes.

func HHMM

func HHMM(ts int64) string

func InitStore

func InitStore(db *sql.DB) error

func Insert

func Insert(db *sql.DB, e Event) error

func InsertMany

func InsertMany(db *sql.DB, events []Event) (int, error)

func PollOnce

func PollOnce(db *sql.DB, scratch string, repos []string, policy *Policy, backfill int64) (int, error)

PollOnce runs one pass over the pull-based sources. The frontmost sampler is push-based and lives in the daemon loop instead.

backfill caps how far back a first run reaches. A second brain with no history is amnesiac on day one, but silently ingesting a year of browsing should be a choice rather than a default.

func Prune

func Prune(db *sql.DB, olderThanTS int64) (int, error)

Prune drops raw events past the retention window. Rollups must already have extracted anything worth keeping — that is the whole contract of the two-tier design.

func Render

func Render(events []Event, verbose bool) string

Render produces a human-readable day. verbose keeps the incidental sub-8s focus flickers that are otherwise noise.

func ReplaceCalendarWindow

func ReplaceCalendarWindow(db *sql.DB, from int64, events []Event) (int, error)

ReplaceCalendarWindow swaps out the captured calendar window wholesale.

Calendar is the one source that captures the future, and the future changes: meetings move, get cancelled, get added. Cursoring an append-only table would accumulate stale ghosts of rescheduled meetings. Deleting everything from `from` onward and re-inserting the fresh window keeps the stored view honest and idempotent — re-polling never duplicates a meeting.

func SetCursor

func SetCursor(db *sql.DB, source string, cursor int64) error

func TodayBounds

func TodayBounds() (int64, int64)

TodayBounds returns [start, end) of the current local day.

Types

type AppTotal

type AppTotal struct {
	App  string
	Secs int64
}

AppTotal is time spent in one app over a window.

func ByApp

func ByApp(events []Event) []AppTotal

ByApp is the first thing anyone wants from a timeline.

type Coalescer

type Coalescer struct {
	// contains filtered or unexported fields
}

Coalescer collapses a stream of identical samples into durable sessions.

Polling frontmost-app every 5s produces ~17k rows per day per source, almost all repeats. Coalescing happens on write, not on read: storing the raw stream and aggregating at query time costs disk and query latency forever in exchange for nothing.

func NewCoalescer

func NewCoalescer(maxGapS int64) *Coalescer

func (*Coalescer) Flush

func (c *Coalescer) Flush() *Event

Flush closes the session in flight, e.g. on shutdown.

func (*Coalescer) Open

func (c *Coalescer) Open() *Event

func (*Coalescer) Push

func (c *Coalescer) Push(sample Event) *Event

Push feeds one sample, returning a completed session if this sample ended one.

type Event

type Event = event.Event

func ByIDs

func ByIDs(db *sql.DB, ids []int64) ([]Event, error)

ByIDs fetches specific events, for showing the evidence behind a proposal. Ordered by time rather than by id so the reader sees a narrative.

func Range

func Range(db *sql.DB, from, to int64) ([]Event, error)

Range returns events in a window, oldest first.

type Kind

type Kind = event.Kind

type Policy

type Policy struct {
	BlockedApps []string
	Paused      bool
}

Policy fails closed everywhere: an app we cannot identify is treated as blocked, because wrongly recording a password manager costs far more than a gap in the timeline.

func DefaultPolicy

func DefaultPolicy() *Policy

func (*Policy) ShouldDrop

func (p *Policy) ShouldDrop(e Event) bool

ShouldDrop reports whether a sample must never be written. Dropped means never persisted — not written-then-filtered, which would leave the content on disk.

func (*Policy) WithExtra

func (p *Policy) WithExtra(extra []string) *Policy

Directories

Path Synopsis
Package sources pulls episodic events off the machine.
Package sources pulls episodic events off the machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL