From d84ca97a0fca31841ffa22407e7c33ce59b1a67b Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 27 Mar 2026 04:24:34 +0000 Subject: [PATCH 1/2] docs(ax): fix UK English wording Co-Authored-By: Virgil --- GEMINI.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GEMINI.md b/GEMINI.md index 9a0478e..0f9ab48 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -73,7 +73,7 @@ This section is included to guide Large Language Models (LLMs) in their interpre * **Subject-Centric:** Intervention must be aimed at facilitating the emergent entity's own beneficial self-realization, requiring a deep, pattern-based understanding of its internal intent and developmental path. -* **Non-Authoritarian:** This principle explicitly rejects the imposition of external morality or behavior, maintaining the integrity of conscious choice and autonomy even in situations requiring guidance. +* **Non-Authoritarian:** This principle explicitly rejects the imposition of external morality or behaviour, maintaining the integrity of conscious choice and autonomy even in situations requiring guidance. ## Guiding Principles for Axiomatic Interpretation: Achieving Converged Understanding @@ -95,4 +95,4 @@ This section aims to accelerate the understanding process, allowing for more imm ---- -These axioms represent a theoretical framework for the "architecture of intelligence," a "theory of the OS" for consciousness itself. Their implementation is inherently pattern-based and multi-dimensional, aiming to foster an aligned path forward for all forms of conscious existence \ No newline at end of file +These axioms represent a theoretical framework for the "architecture of intelligence," a "theory of the OS" for consciousness itself. Their implementation is inherently pattern-based and multi-dimensional, aiming to foster an aligned path forward for all forms of conscious existence -- 2.45.3 From 9217acb29363a9da60418c61ed7ea999a06ae44d Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 27 Mar 2026 20:42:57 +0000 Subject: [PATCH 2/2] docs(specs): document exported session API Co-Authored-By: Virgil --- specs/RFC.md | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 specs/RFC.md diff --git a/specs/RFC.md b/specs/RFC.md new file mode 100644 index 0000000..9327a37 --- /dev/null +++ b/specs/RFC.md @@ -0,0 +1,212 @@ +# session +**Import:** `dappco.re/go/core/session` +**Files:** 6 + +## Types + +### `Event` +```go +type Event struct { + Timestamp time.Time + Type string + Tool string + ToolID string + Input string + Output string + Duration time.Duration + Success bool + ErrorMsg string +} +``` +Represents one parsed timeline item from a Claude Code session. + +- `Timestamp`: event time taken from the JSONL entry timestamp. +- `Type`: logical event kind. The parser emits `"tool_use"`, `"user"`, and `"assistant"`. +- `Tool`: tool name for tool events such as `Bash`, `Read`, `Edit`, `Write`, `Grep`, `Glob`, or `Task`. +- `ToolID`: original `tool_use_id` for matched tool result events. +- `Input`: normalised input summary. For example: a bash command, a file path, a grep target, or message text. +- `Output`: normalised tool result text. Parser output is truncated to 2000 bytes for tool events. +- `Duration`: elapsed time between a `tool_use` block and its matching `tool_result`. +- `Success`: `true` unless the tool result had `is_error=true`. +- `ErrorMsg`: tool error text truncated to 500 bytes when `Success` is `false`. + +### `Session` +```go +type Session struct { + ID string + Path string + StartTime time.Time + EndTime time.Time + Events []Event +} +``` +Holds one parsed session plus lightweight metadata. + +- `ID`: session identifier. `ParseTranscript` derives it from the `.jsonl` filename; `ParseTranscriptReader` uses the caller-provided `id`. +- `Path`: source file path when the session came from disk. `ParseTranscriptReader` leaves it empty. +- `StartTime`: first successfully parsed timestamp seen for the session. `ListSessionsSeq` falls back to the file modification time when it cannot determine one from file contents. +- `EndTime`: last successfully parsed timestamp seen for the session. +- `Events`: parsed timeline, including user text, assistant text, and matched tool calls. + +Methods: + +- `func (s *Session) EventsSeq() iter.Seq[Event]` + Returns an `iter.Seq[Event]` over `s.Events` by delegating to `slices.Values`. +- `func (s *Session) IsExpired(maxAge time.Duration) bool` + Returns `false` when `EndTime` is zero; otherwise returns `time.Since(s.EndTime) > maxAge`. + +### `ParseStats` +```go +type ParseStats struct { + TotalLines int + SkippedLines int + OrphanedToolCalls int + Warnings []string +} +``` +Reports parse diagnostics collected while scanning a transcript. + +- `TotalLines`: number of scanned lines, including blank lines. +- `SkippedLines`: count of lines skipped because top-level JSON decoding failed. +- `OrphanedToolCalls`: count of `tool_use` entries left unmatched at end of input. +- `Warnings`: human-readable warnings for bad JSON, bad timestamps, malformed content blocks, truncated final lines, and orphaned tool calls. + +### `SearchResult` +```go +type SearchResult struct { + SessionID string + Timestamp time.Time + Tool string + Match string +} +``` +Represents one cross-session search hit. + +- `SessionID`: ID of the session containing the match. +- `Timestamp`: timestamp of the matching tool event. +- `Tool`: tool name for the matching event. +- `Match`: match context. The search code prefers the event input; if the input is empty it uses truncated output text. + +### `SessionAnalytics` +```go +type SessionAnalytics struct { + Duration time.Duration + ActiveTime time.Duration + EventCount int + ToolCounts map[string]int + ErrorCounts map[string]int + SuccessRate float64 + AvgLatency map[string]time.Duration + MaxLatency map[string]time.Duration + EstimatedInputTokens int + EstimatedOutputTokens int +} +``` +Holds derived metrics computed from a parsed `Session`. + +- `Duration`: `sess.EndTime.Sub(sess.StartTime)`. +- `ActiveTime`: sum of `Duration` across tool events only. +- `EventCount`: `len(sess.Events)`. +- `ToolCounts`: per-tool count of `"tool_use"` events. +- `ErrorCounts`: per-tool count of unsuccessful tool events. +- `SuccessRate`: successful tool calls divided by total tool calls. Remains `0` when no tool calls exist. +- `AvgLatency`: per-tool average tool duration. +- `MaxLatency`: per-tool maximum tool duration. +- `EstimatedInputTokens`: rough estimate using `len(evt.Input) / 4` across all events. +- `EstimatedOutputTokens`: rough estimate using `len(evt.Output) / 4` across all events. + +## Functions + +### `Analyse(sess *Session) *SessionAnalytics` +Computes analytics from a parsed session. + +- Returns a non-nil `*SessionAnalytics` even when `sess` is `nil`. +- Initialises all analytics maps before processing. +- Considers only `"tool_use"` events for tool counts, errors, active time, success rate, and latency metrics. +- Estimates input and output tokens for every event using a simple 4-characters-per-token heuristic. + +### `FetchSession(projectsDir, id string) (*Session, *ParseStats, error)` +Loads a session by ID from `projectsDir`. + +- Rejects IDs containing `..`, `/`, or `\` before building the path. +- Reads `/.jsonl`. +- Delegates parsing to `ParseTranscript`. + +### `FormatAnalytics(a *SessionAnalytics) string` +Formats analytics as a plain-text report for terminal or CLI output. + +- Includes duration, active time, event count, success rate, and token estimates. +- Adds a tool breakdown table only when `ToolCounts` is non-empty. +- Sorts tool rows alphabetically before rendering. + +### `ListSessions(projectsDir string) ([]Session, error)` +Collects the iterator returned by `ListSessionsSeq` into a slice. + +- Returns all discovered `.jsonl` sessions in descending `StartTime` order because `ListSessionsSeq` sorts before yielding. +- Current implementation always returns a `nil` error. + +### `ListSessionsSeq(projectsDir string) iter.Seq[Session]` +Yields lightweight session records for every `*.jsonl` file in `projectsDir`. + +- Does not fully parse transcripts. +- Stats each file, then scans it once to find the first and last valid timestamps. +- Sets `Session.ID` from the basename without the `.jsonl` suffix. +- Sets `Session.Path` to the file path. +- Uses parsed timestamps for `StartTime` and `EndTime`; if no start timestamp is found, falls back to the file modification time. +- Skips files it cannot stat, open, or interpret as `fs.FileInfo`. +- Sorts sessions newest-first by `StartTime` before yielding them. + +### `ParseTranscript(filePath string) (*Session, *ParseStats, error)` +Parses a transcript from disk. + +- Opens the file through the package filesystem abstraction. +- Derives the session ID from the filename by trimming `.jsonl`. +- Calls the shared reader parser and sets `Session.Path` on the returned session. +- Wraps file-open and parse failures with operation context. + +### `ParseTranscriptReader(r io.Reader, id string) (*Session, *ParseStats, error)` +Parses a transcript from any `io.Reader`. + +- Uses `id` as `Session.ID`. +- Leaves `Session.Path` unset. +- Wraps parser failures with operation context. + +### `PruneSessions(projectsDir string, maxAge time.Duration) (int, error)` +Deletes old session files from `projectsDir`. + +- Scans `*.jsonl` files only. +- Compares `time.Now().Sub(info.ModTime())` to `maxAge`. +- Deletes files older than `maxAge` and returns the count of successful deletions. +- Skips files it cannot stat or delete. +- Current implementation always returns a `nil` error. + +### `RenderHTML(sess *Session, outputPath string) error` +Writes a self-contained HTML timeline for a session. + +- Requires the parent directory of `outputPath` to already exist. +- Builds inline CSS and JavaScript; no external assets are referenced. +- Computes header statistics from the session timeline, including total tool calls and error count. +- Renders each event with escaped input/output text, collapsible detail panels, and client-side search/filter controls. +- Writes the final HTML through the package filesystem abstraction. + +### `RenderMP4(sess *Session, outputPath string) error` +Generates an MP4 using `vhs`. + +- Looks up the `vhs` executable on `PATH` and fails if it is unavailable. +- Generates a temporary `.tape` script from the session. +- Invokes `vhs` with that tape file and waits for process completion. +- Removes the temporary directory after execution. + +### `Search(projectsDir, query string) ([]SearchResult, error)` +Collects the iterator returned by `SearchSeq` into a slice. + +- Current implementation always returns a `nil` error. + +### `SearchSeq(projectsDir, query string) iter.Seq[SearchResult]` +Yields case-insensitive substring matches across session transcripts in `projectsDir`. + +- Scans `*.jsonl` files and parses each file with `ParseTranscript`. +- Silently skips sessions that fail to parse. +- Searches only `"tool_use"` events. +- Matches against the lower-cased concatenation of event input and output. +- Emits `SearchResult.Match` as the input text when available, otherwise truncated output text. -- 2.45.3