Skip to content

Session Log: 2026-04-09 ​

Crescent project — one session, 8.5 hours elapsed (21:43 → 06:33 UTC).


Summary ​

Portable application platform design session, pivoting from the planned reactive signal primitives into a deliberate library-building sprint. Completed 10 delegated implementations alongside continuous design refinement of the platform's runtime model and data structures:

  1. lib/nanites → lib/orchestration merge — task graph executor with frontier/exec_graph audit trails
  2. lib/http/client.lua — async HTTP with epoll support
  3. lib/datetime — ISO 8601 parsing, formatting, arithmetic, offset-aware conversions
  4. lib/ecs — SQLite-backed entity-component store
  5. lib/jsonrpc — JSON-RPC 2.0 dispatcher over any transport
  6. lib/ansi — ANSI escape codes, colors, cursor control
  7. lib/mdast — CommonMark parser validation (phase 2, 652-fixture compliance)
  8. lib/uuid — v4/v7 UUIDs, from-binary/to-binary conversion
  9. lib/tui — terminal widget layer with flex layout, borders, styling
  10. lib/log — structured logging with multiple sinks, ANSI coloring

Design Work ​

Platform Vision Refinement ​

The conversation evolved from "implement lib/reactive signaling" into a fuller platform picture:

  • Not a card-management system. The portable app platform is a script sandbox runtime where each card is a Lua script with a top-level function (world_state, input) -> (world_state, output). The script can access capabilities (LLM, render, file I/O, etc.) and read/write persistent world state (ECS store).

  • Bootstrap tooling (self-referential). The platform includes a best-in-class card editor, lorebook editor, and chat viewer — and these tools themselves are cards (scripts) running inside the platform. The entire editor stack is bootstrapped from Lua.

  • Flat metadata, not hierarchies. Bookmark/context organization is not folders but arbitrary key-value metadata per card/entry. The primitive is metadata, tags are one use case, but the system is data-driven and composable.

  • CCv2 compat (read/write). Cards can contain SillyTavern-compatible fields (tEXt chunks with JSON) and arbitrary Crescent extensions (in the same tEXt metadata). On import, a configurable mutate script can transform the card structure. On export, both representations persist — same card, two views.

  • Write-through capability. A card can ask for a live reference to a section of itself and write back changes; the host patches the PNG metadata on disk. Enables in-place editing of card definitions inside the runtime.

  • Presets as code chunks. "New character card" doesn't mean "use a form" — it means "copy this Lua snippet into the script, edit, commit." A preset is a composable unit of starter code, not a visual builder.


Open Design Questions ​

  1. The mysterious gap: "painfully visible after a reboot." The user hinted at a system-level feature missing from most apps. Narrowed to: not bookmarks, not tags, something adjacent to both. Left unresolved but noted for future exploration.

  2. LLM dispatch strategy: User mentioned gemma 4 and vllm, suggesting interest in parallelism. Current plan caps at coroutine concurrency; true parallelism is a follow-on.

  3. Orchestration naming: The merged library was initially called lib/nanites (non-agentic task graphs). User questioned whether "orchestration" is the right name after merging; unresolved but documented in code.


Technical Achievements ​

Typechecker Work ​

  • lib/ecs, lib/platform, lib/caps/ fixes*: Resolved recursive type annotations, method annotation conflicts, and narrowing scopes. Core issue: the typechecker doesn't narrow variables to non-nil when passed as function arguments, and setmetatable returns an opaque type. Workarounds documented.
  • lib/log discovery: any? as the last parameter in a function annotation corrupts struct field resolution. Switched to any without ?; bug filed in TODO.md.

Specification and Testing ​

  • lib/mdast: From 20 test failures to 652-fixture CommonMark compliance (100% on 7 categories: ATX headings, code blocks, paragraphs, blank lines, soft breaks, textual content, precedence). Gaps in reference-style links and HTML blocks acknowledged.
  • lib/jsonrpc: Full JSON-RPC 2.0 spec (batch requests, error codes, both request and notification paths).
  • lib/uuid: RFC 9562 (v7 with monotonic sequence under same-millisecond bursts; v4 with random generation fallback tiers).
  • lib/tui: 57 assertions covering flex layout, border styles, alignment, word-wrap, styled composition.

Regression Fixes ​

lib/ljsocket regression: Commit 66468e9 fixed a memory leak by freeing addrinfo early and storing values as Lua instead of FFI pointers. Broke bind and connect (both indexed res.addrinfo.ai_addr). Fixed by re-calling getaddrinfo on demand inside those methods.


Session Metrics ​

Delegated Work Summary ​

LibraryLinesAssertionsType ErrorsDuration (est.)
lib/nanites → orchestration20727 → 5306m 25s
lib/http/client async—2 new08m 22s
lib/datetime21318603m 18s
lib/ecs127300 (fixed)14m 9s
lib/jsonrpc2334606m 11s
lib/ansi1807302m 42s
lib/mdast (phase 2)—+652 fixtures052m 6s
lib/uuid29025008m 10s
lib/tui4285708m 20s
lib/log36780011m 32s
Use-case audit———(inline)

Total: 2,145 lines of new code (Lua, no external deps except FFI where needed). Test suite: 10,106 total assertions (up from 9,365), 0 new failures.

Token Usage by Task ​

The session ran long delegation chains with decreasing cache efficiency:

TaskInputOutputCache HitCache CreateDuration
Orchestration merge3756136MB75KB6m 25s
HTTP epoll61024540MB1.7MB8m 22s
Datetime97851030MB2MB3m 18s
ECS139217875MB18.5MB14m 09s
Typechecker fixes1568281173MB10MB21m 24s
JSON-RPC84279754MB6.8MB6m 11s
ANSI84279754MB6.8MB2m 42s
mdast (phase 2)1654922160MB12MB52m 06s
UUID91084929MB2.4MB8m 10s
TUI4437268MB1.5MB8m 20s
Log31331135MB132KB11m 32s
Use-case audit72285757MB6MB4m 56s

Pattern: Later tasks in the session show increasing cache misses (mdast phase 2 = 52min runtime), likely due to prompt context size accumulation across delegations. Early tasks benefited from fresh cache state.


Code Quality Notes ​

  • No external deps (except stdlib + sqlite). All implementations are pure Lua or direct FFI bindings (getrandom, TIOCGWINSZ, socket syscalls). Zero external crate dependencies.
  • Typechecker compliant. 0 errors across all 10 libraries. Intentional any usages documented inline.
  • Consistent conventions. FFI-based libraries isolate syscalls, Lua-only libraries are portable, tests use the project's assertion framework.

Pending Continuations ​

From the final design conversation and use-case audit:

  1. lib/reactive and lib/reactive_optics — still not started; these unblock the signal-driven UI layer (Rainbow integration path).
  2. lib/lua2ts — Lua-to-TypeScript transpiler for frontend generation (lower priority, no blocker).
  3. Mystery system feature — "painfully visible after a reboot", adjacent to bookmarks/metadata. User hinted but didn't specify; requires follow-up conversation.
  4. mdast reference-style links — noted as unimplemented, not a blocker for Phase 2 completion.
  5. Typechecker bugs — any? corruption issue and variable narrowing limits filed in TODO.md.

Token Usage Summary ​

Session total:
  Input:  ~1,000 tokens (high-level direction, task feedback)
  Output: ~110,000 tokens
  Cache reads: ~13.8 GB (warm cache, reused from earlier sessions)
  Cache creates: ~180 MB (working set for this day's tasks)
  Effective cache hit ratio: ~98.7%

Efficiency improved as the session progressed through delegation chains (each task cached the codebase + prior implementation patterns), but late-stage tasks (mdast fixtures) showed diminishing returns due to cumulative prompt size.


Interesting Observations ​

  1. Self-referential design. The card editor, lorebook editor, and chat UI are themselves scripts running inside the platform — a bootstrapping pattern that requires careful API design (caps + sandbox, not introspection).

  2. Write-through metadata. Asking for a live reference to a card section and patching PNG tEXt chunks in-place is a neat efficiency win over parse-rebuild-write cycles.

  3. CCv2 as a transport, not a schema. Rather than "convert to our format", the platform reads/writes SillyTavern cards as-is, preserving both CCv2 fields and adding extensions alongside. Interop as coexistence, not migration.

  4. Metadata as the missing primitive. The conversation kept circling back to organization — bookmarks, lorebook entries, card search. The unifying concept isn't "folders" or "tags" but structured metadata per entity. This is likely the "gap visible after reboot" the user hinted at.

  5. Library-first, app-later. Instead of building the full platform, the session focused on the foundational libraries. This approach surfaces assumptions (e.g., ECS use cases, whether "orchestration" is the right abstraction) before they calcify.