Skip to content

fix(watch): give sessions the hooks their status depends on - #34

Merged
pfriedrix merged 3 commits into
masterfrom
fix/session-status-hooks
Aug 6, 2026
Merged

fix(watch): give sessions the hooks their status depends on#34
pfriedrix merged 3 commits into
masterfrom
fix/session-status-hooks

Conversation

@pfriedrix

Copy link
Copy Markdown
Owner
  • Three defects in one chain, every one of them silent: the daemon wrote hooks.json and never handed it to claude --settings, the hook handler ignored the --socket baked into its own command line, and a session whose subagents were doing the work still reported idle. Nothing lcc launched had ever reported its own status — lcc open showed whatever the first byte of pty output left behind, for as long as the session ran.
  • Checked against real Claude Code 2.1.223, not units alone: a session run through the daemon now traces starting → active → idle → exited, and a spawned subagent puts it back to active. SubagentStart maps to active rather than waiting on purpose — yellow has to go on meaning that a person is blocking the session, and subagents block on nobody.
  • Base is chore/hide-daemon-concept (refactor(cli): talk about sessions, not the daemon behind them #33), not master: the comments here use the lcc open --stop-all vocabulary that PR introduces. /bin/cat also stops working as a test stand-in once sessions are launched with real flags — it exits on the unknown option — so the daemon tests write a script stand-in into their own tmpdir.

The daemon bakes its own socket into every hook command line precisely
so a report cannot be misdirected by the environment it inherits: a hook
runs with the session's, which belongs to whichever shell started that
session. The flag was parsed into HookOpts and then never read, so every
report went to whatever watch_paths.socket derived from that environment
instead.

Those two agree on a default install, which is why it survived. A daemon
under LCC_WATCH_DIR received nothing, silently, and its sessions sat at
the status they registered with for as long as they ran.
writeHookSettings wrote hooks.json at startup and nothing ever handed it
to `claude --settings`, so no session lcc launched carried a single lcc
hook. Every unit passed and the registry looked healthy. Sessions
reached idle on their first byte of output — which only means the exec
worked — and stayed there through hours of work, because nothing was
left that could report anything else.

The flag goes on in the daemon rather than in a client. There are two
register paths, `lcc start --watch` and the dashboard's enter, and a
flag added to one and forgotten in the other is exactly how the hooks
came to be written but never installed.

/bin/cat can no longer stand in for claude in the tests: launched the
way a real session now is, it exits with "illegal option" before a test
can type into it. The stand-in is a script in the test's own tmpdir that
ignores what it is handed, which is what a stand-in for a program with
flags has to do.
A main agent that hands work to subagents ends its own turn, so Stop
fires and the row reads idle — "finished, come back whenever" — while a
dynamic workflow grinds away underneath it. The one question this
dashboard exists to answer is where the work is, and idle was the wrong
answer to it.

active rather than waiting, because yellow has to go on meaning that a
person is blocking the session. Subagents block on nobody, and one
colour covering two states that call for opposite responses is a colour
that means neither.
Base automatically changed from chore/hide-daemon-concept to master August 6, 2026 16:22
@pfriedrix
pfriedrix merged commit 19320b1 into master Aug 6, 2026
@pfriedrix
pfriedrix deleted the fix/session-status-hooks branch August 6, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant