Passing { limit } to recent() used to crash with 'Unknown named
parameter limit' because the options object was forwarded as the limit
value. Mirror sessions()'s QueryOptions | number signature.
Pi cannot be read as another linear JSONL stream. Its history is a tree with
a durable leaf, orphan roots, branch summaries, and two compaction forms, so
the active context is something the format states rather than something line
order implies. The adapter keeps those semantics inside itself and projects
the result into the existing canonical tables.
Sessions are keyed by (normalized header cwd, header id) rather than by path,
because Pi's --session-id lookup is project-local: two projects may reuse an
id, while a move or an identical copy is still one session. Discovery covers
both layouts Pi writes and fingerprints each file by mtime, ctime, size and
inode, so a rewrite that preserves mtime is not read as unchanged.
Abandoned branches are preserved rather than dropped. Visibility becomes
three-state -- visible, inactive, hidden -- and helpers return only visible
rows until includeInactive asks for the superseded path, labeling every row
so a caller knows which it holds. Usage counts all three, because an
abandoned call still spent tokens; message_count reports only the visible
transcript.
A committed MIT-licensed oracle transcribed from Pi 0.83.0 pins the context
algorithms, and a fixed-seed differential runs 512 generated sessions against
it on every test run. Schema changes are additive.
Mark absolute Markdown links and inline-code relative paths as file
references, resolve them against the originating message cwd, and open
them in the configured editor. Local links no longer navigate the SPA
away from the running renderer.
The canonical transcript assembly projected messages down to seven
fields, so cwd and session_id never reached the renderer. Both are added
to SessionDetailMessage: cwd because the working directory can change
mid-session, session_id because it scopes which roots a reference may
resolve inside. The main process derives those roots from the database
rather than trusting anything the renderer sends.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Treat token_count events without usage as null canonical token values so node:sqlite never receives undefined. Covers issue #1 with a parse-to-persist regression test.
- normalize Kimi thinking parts and omit empty placeholders
- add standalone session-sharing and UI demo artifacts
- add regression coverage and refresh the Kimi index marker
- bump the Electron app and CLI packages to v0.2.1
- ignore generated app build assets
Add @obelisk-apps/cli with the existing build, search, query, and attune contract plus official skill installation.
Separate the docs-only skill artifact, bootstrap installer, release layout, cross-platform CI, and package-level regression coverage.
Eliminate full-table scans from subagent tool queries and guardian retractions by indexing message_uuid on tool_calls and tool_results. Add query-plan regressions for both access paths.
SessionDetail live update:
- Extract session-view-state.mjs: capture scroll position, disclosure
(open/skill-md-open) state, and visible-UUID anchor before refresh;
reconcile messages by UUID (in-place update, append tail only); restore
scroll and disclosure state after DOM patch. findLastMessageAtOrAbove uses
binary search (O(log n)) instead of linear scan.
- scrollRevision tracks user scrolls during refresh to avoid stale anchors
overriding manual navigation.
- Throttle onScroll to one rAF per frame.
Tool renderer:
- Extract tool-renderer.js: standalone module for rendering tool call cards
(Read/Write/Edit diffs, Bash terminal output, search results, JS/TS
syntax highlighting). Replaces inline rendering in SessionDetail.
- tests/app-tool-renderer.test.mjs covers escaping, highlighting, and
terminal formatting.
Input tokens semantics migration:
- Claude provider now sums input_tokens + cache_creation_input_tokens +
cache_read_input_tokens into a single input_tokens value (was previously
only the raw field, undercounting when cache tokens are present).
- One-time index-wide re-parse triggered when the marker
__claude_input_tokens_include_cache_v1__ is absent and the DB already
has token data (self-healing on first build after upgrade).
- App indexer.ts carries the same marker check for the app's build path.
Also:
- PRODUCT.md: product register (users, purpose, brand, design principles,
accessibility targets).
- README.md: minor wording updates.
Co-Authored-By: Codex (GPT-5) <noreply@openai.com>