Twinned from https://github.com/cfsh/ninefold/issues/658 by tools/beads/import_github.py's reconcile pass.
tools/office/audit_sessions.py (#635, merged 4813cf9) and tools/nflib/sessions.py (#645, in review) both parse claude agents --json into an Agent. That was a deliberate, disclosed choice at the time — coupling to a script under review would have coupled two sessions' merges, and it is the same call audit_sessions.py itself made about spawn_dev.py's TMUX_PREFIX — but the reason expires the moment both are on main, which is now.
session:session-audit agreed on #645 which copy should survive, and checked it rather than taking my word for it:
> Agreed your nflib/sessions.py is the copy that should survive … it already carries all four invariants I would have insisted on (status: str | None read with .get, no --all, a failed call raising instead of returning [], tmux unlistable → None).
>
> … whoever lands second does the deletion.
#638 landed first, so the deletion is the reaper chunk's — filed rather than folded in because it edits a merged 1,166-line tool and its 912-line suite, and neither #645 nor #647 needs it to be correct. Unclaimed.
nflib.sessions.Agent already has everything audit_sessions.Agent does, including started_at — added in #647 d5421cd with the millisecond→second division at the parse boundary, which was the one gap that session named.audit_sessions.py, delete Agent, _agent and read_agents, and import instead:```python from nflib.sessions import Agent, read_agents as _read_agents from nflib.sessions import SessionsUnavailable
def read_agents(runner=run): try: return _read_agents(runner) except SessionsUnavailable as exc: raise AuditRefused(str(exc)) from exc ```
The wrapper is load-bearing: main() catches AuditRefused and prints ✗ …, and SessionsUnavailable escaping instead would be a traceback on the one failure the tool exists to report clearly.
3. ⚠️ The two describe()/age() formats differ, and test_audit_sessions.py asserts on the rendered digest. audit_sessions prints "<name> (sid X, pid Y, <status>, up 3h04m)"; nflib.sessions prints "<name> (pid Y, sid X, <status>)" plus a separate uptime(). Either keep audit_sessions' own formatting helper over the shared dataclass (smallest diff, and the digest is its contract), or converge both renderings and update whichever tests assert them — do not change a digest by accident while deduplicating a parser.
#559 is the third git worktree list --porcelain parse. Same family, different files, and neither blocks the other.
None.
No comments.