anomalyco / anomalyco/opencode

bug(tui): session.child.first and child cycle order break after session-ID encoding wraps (2026-08-14)

Open
#42,905 2 comments 0 reactions 1 assignee View on GitHub

@kommander is already working on this.

Since Aug 16, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

session.child.first (Ctrl+X+Down, "Go to first child session") is supposed to land on the newest child, but after the session-ID encoding wraps around, it lands on an old subagent instead. The subagent footer then shows a position like (50 of 112) that has no relation to the navigation order.

Root cause: children() in packages/tui/src/routes/session/index.tsx (line 207) sorts siblings by session ID string:

const children = createMemo(() => {
  const parentID = session()?.parentID ?? session()?.id
  return sync.data.session
    .filter((x) => x.parentID === parentID || x.id === parentID)
    .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
})

and session IDs (packages/schema/src/identifier.ts) are descending-encoded timestamps:

const current = BigInt(timestamp) * 0x1000n + BigInt(counter)
const value = descending ? ~current : current
// 6-byte hex prefix

So the lexicographically smallest ID is the newest-created session — within one encoding cycle. The 48-bit value wraps when timestamp_ms * 0x1000 + counter crosses a multiple of 2^48, which happened globally at 2026-08-14 11:19:55 UTC (26 * 2^36 ms since epoch; next wrap ~2028-10). After the wrap, every new session ID sorts after all pre-wrap IDs, so:

  • moveFirstChild() (index.tsx:442, children().find(x => !!x.parentID)) lands on the newest pre-wrap child, not the actual newest.
  • moveChild() Left/Right cycling (index.tsx:448) is scrambled the same way.

The subagent footer counter uses yet a third order — subagent-footer.tsx:25-28 sorts siblings by time.created ascending (oldest = "1 of M") — so the displayed (N of M) never matches the navigation sequence. Session.children (backend) applies no ORDER BY, so ordering is purely a frontend concern.

Verified by reproducing the encoding against real session IDs: the smallest-ID child of an 829-child tree was created ~16 min before the wrap, while the actual newest child (created days later) ranks ~756th in ID order.

Steps to reproduce

  1. Have a parent session whose subagents span the wrap boundary — in practice, any session created before 2026-08-14 11:19:55 UTC that keeps spawning subagents (e.g. a long-running session from July 2026).
  2. Navigate into that parent, press Ctrl+X+Down (session.child.first), or cycle with Left/Right (session.child.next/previous).
  3. Observe: it lands on a subagent that is not the newest; the footer shows e.g. (50 of 112) — its creation-time position among siblings (oldest = 1).

Suggested fix

Sort children by time instead of ID string in index.tsx children():

.toSorted((a, b) => b.time.updated - a.time.updated)

(or b.time.created - a.time.created to match the "newest created" semantics session.child.first already implies), and align the footer counter in subagent-footer.tsx to the same ordering so (N of M) reflects navigation order.

OpenCode version

1.18.18

Operating System

Windows 11

Terminal

Windows Terminal

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.