Documentation
¶
Overview ¶
Package ledger implements a cross-session learning ledger that records every shipped session's metadata to a persistent markdown file (~/.m31a/LEDGER.md). The ledger supports append, filtered queries, aggregate statistics, and automatic truncation.
Index ¶
- type Ledger
- func (l *Ledger) Append(entry LedgerEntry) error
- func (l *Ledger) Clear() error
- func (l *Ledger) Entries() []LedgerEntry
- func (l *Ledger) EntriesFiltered(projectType string, keywords []string, maxResults int) []LedgerEntry
- func (l *Ledger) Path() string
- func (l *Ledger) Reload() error
- func (l *Ledger) Stats() LedgerStats
- func (l *Ledger) Truncate(maxEntries int) error
- type LedgerEntry
- type LedgerStats
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Ledger ¶
type Ledger struct {
// contains filtered or unexported fields
}
Ledger manages persistent session records in a markdown file.
func New ¶
New creates a Ledger for the given file path. If the file already exists, it parses existing entries into memory. The directory is created if needed.
func (*Ledger) Append ¶
func (l *Ledger) Append(entry LedgerEntry) error
Append adds an entry to the ledger, deduplicating by SessionID. If the file doesn't exist, it creates it with a markdown table header. Returns an error wrapping ErrTaskFailed if an entry for the same SessionID already exists (H-18 idempotency guard). Uses true append-only writes (H9 fix) instead of rewriting the entire file on every append.
func (*Ledger) Clear ¶ added in v1.1.0
Clear deletes the ledger file from disk and clears in-memory entries.
func (*Ledger) Entries ¶
func (l *Ledger) Entries() []LedgerEntry
Entries returns a copy of all entries sorted newest-first by Timestamp.
func (*Ledger) EntriesFiltered ¶
func (l *Ledger) EntriesFiltered(projectType string, keywords []string, maxResults int) []LedgerEntry
EntriesFiltered returns entries matching the given filters, sorted newest-first.
- projectType: exact match, case-insensitive. If empty, skip this filter.
- keywords: an entry passes if ANY keyword matches in GoalKeywords (substring match, case-insensitive).
- maxResults: maximum entries to return. If <= 0, defaults to 5.
func (*Ledger) Reload ¶
Reload re-reads the ledger file from disk, re-populating the entries slice. Useful if the file was modified externally.
func (*Ledger) Stats ¶
func (l *Ledger) Stats() LedgerStats
Stats computes aggregate statistics from all entries. Returns zero-valued stats for an empty ledger (never panics). Uses mtime-based caching: if LEDGER.md hasn't been modified since the last call, returns the cached result (M-16). PERF-35: Uses RLock for cache-hit path to avoid lock contention.
type LedgerEntry ¶
type LedgerEntry struct {
SessionID string `json:"session_id"`
Timestamp time.Time `json:"timestamp"`
Model string `json:"model"`
Provider string `json:"provider"`
ProjectType string `json:"project_type"`
GoalKeywords []string `json:"goal_keywords,omitempty"`
Framework string `json:"framework,omitempty"`
TaskCount int `json:"task_count"`
FailedTasks int `json:"failed_tasks"`
SkippedTasks int `json:"skipped_tasks"`
CostEstimate float64 `json:"cost_estimate"`
DurationMinutes int `json:"duration_minutes"`
CommitCount int `json:"commit_count"`
}
LedgerEntry represents a single session record stored in the ledger.
type LedgerStats ¶
type LedgerStats struct {
TotalSessions int `json:"total_sessions"`
AvgTaskCount float64 `json:"avg_task_count"`
AvgCost float64 `json:"avg_cost"`
AvgDurationMinutes float64 `json:"avg_duration_minutes"`
TotalFailedTasks int `json:"total_failed_tasks"`
TopFailures []string `json:"top_failures,omitempty"`
TopFrameworks []string `json:"top_frameworks,omitempty"`
ByProjectType map[string]int `json:"by_project_type"`
}
LedgerStats holds aggregate statistics computed from all ledger entries.