Skip to content

refactor: extract a shared ring-buffer tail collector for preview and codex #94

Description

@sorafujitani

Context

"Keep only the last N items while counting the total, then unwind the ring in chronological order" is implemented twice. The total % limit index arithmetic is exactly the kind of code where an off-by-one slips in during unrelated edits.

Current state (verified locations)

  • internal/preview/preview.go:344-357 (ring write in loadMessages) + preview.go:373-387 (collectRing)
  • internal/codex/codex.go around lines 366-387 (appendMessage / collectMessages) — same pattern; read it first and note any boundary differences (total < limit, limit <= 0).

Task

  1. Add a small generic helper, suggested location internal/ringtail/ringtail.go:
    type Ring[T any] struct { buf []T; total int }
    func New[T any](limit int) *Ring[T]   // limit <= 0: define and document the behavior (match current callers)
    func (r *Ring[T]) Add(v T)
    func (r *Ring[T]) Collect() []T       // chronological order, at most limit items
    func (r *Ring[T]) Total() int
  2. Before migrating, write table-driven + property-style tests for the helper itself: total==0, total<limit, total==limit, total==limit+1, total==2*limit+3, limit==1. Property: Collect() equals the last min(total, limit) items of the full input sequence.
  3. Migrate internal/preview.loadMessages and the codex equivalent to the helper. If codex handles a boundary differently, keep its current behavior and document the difference in the test.
  4. Delete collectRing/collectMessages and their now-redundant private tests (keep any that assert caller-level behavior).

Acceptance criteria

  • One ring implementation; both callers use it.
  • go test ./... passes, including existing preview property tests.
  • go test -bench=. ./internal/preview ./internal/codex shows no regression (±5%).

Metadata

Metadata

Assignees

No one assigned

    Labels

    impact: lowLower or indirect user-visible impactrefactorInternal restructuring with no behavior change

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions