mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 16:09:43 +02:00
feat(session): say when a session is watching its own background work
An agent that arms a monitor, backgrounds a shell or hands a task to a cloud session is told to end its turn. The pane then falls quiet, Claude Code's idle_prompt notification arrives a minute later, and every surface files the session under NEEDS YOU with nothing for a human to answer. Claude states what it is still running on the last row of its screen (`⏵⏵ bypass permissions on · 1 monitor · ← for agents`). That row is now `capabilities.workDetect.watchingLine` in the CLI registry, guarded by compileVersionRegex() like every other config regex, and the idle probe reads it off the capture it already takes: `watchingLabel()` in session-activity.ts searches the last five lines only, so a session that PRINTS "1 monitor" is not mistaken for one running it. The label lands on Session.watching and rides toLightDetailedState() out to every surface. The phone overview, the desktop home rail and the rich sidebar rows wear it as a `watching` badge in the accent colour, beside the state pill and never in place of it: an agent can arm a monitor and ask a question in the same breath, and only the pill says which. Verified end to end against a throwaway session on an isolated beta instance: the payload carried `watching: "1 monitor"` once the turn ended, the badge rendered next to a yellow `waiting` pill, and both cleared when the monitor died. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9466acfc1a
commit
3f2cde2db7
@@ -485,3 +485,50 @@ describe('mobile overview run picker (CLI availability gating)', () => {
|
||||
expect(gate).toContain('isCliAvailable');
|
||||
});
|
||||
});
|
||||
|
||||
describe('mobile overview watching badge', () => {
|
||||
it('carries what the pane says is running in the background', () => {
|
||||
const app = loadOverviewApp();
|
||||
const model = app.buildMobileOverviewModel({
|
||||
sessions: [session({ id: 'a', status: 'idle', watching: '1 monitor' }), session({ id: 'b', status: 'idle' })],
|
||||
cases: CASES,
|
||||
});
|
||||
|
||||
const rows = Object.fromEntries(model.current.map((r: any) => [r.id, r.watching]));
|
||||
expect(rows).toEqual({ a: '1 monitor', b: '' });
|
||||
});
|
||||
|
||||
it('leaves a session that is ALSO blocked on a dialog in NEEDS YOU', () => {
|
||||
// An agent can arm a monitor and ask the user a question in the same breath, so the
|
||||
// badge adds a fact to the row and never moves it out of the group that says a human
|
||||
// is needed. Only the row's own pill decides that.
|
||||
const app = loadOverviewApp();
|
||||
const model = app.buildMobileOverviewModel({
|
||||
sessions: [session({ id: 'a', status: 'idle', watching: '2 shells' })],
|
||||
cases: CASES,
|
||||
pendingHooks: new Map([['a', new Set(['permission_prompt'])]]),
|
||||
});
|
||||
|
||||
expect(model.needsYou.map((r: any) => r.id)).toEqual(['a']);
|
||||
expect(model.needsYou[0].pill).toBe('needs you');
|
||||
expect(model.needsYou[0].watching).toBe('2 shells');
|
||||
});
|
||||
|
||||
it('says one word and puts the detail in the tooltip', () => {
|
||||
const app = loadOverviewApp();
|
||||
const badge = app._buildWatchingBadge('1 monitor', 'mobile-overview-pill');
|
||||
|
||||
expect(badge.className).toBe('mobile-overview-pill mobile-overview-pill--watching');
|
||||
expect(badge.textContent).toBe('watching');
|
||||
expect(badge.title).toBe('Still running in the background: 1 monitor');
|
||||
});
|
||||
|
||||
it('takes the pill class of whichever surface asks for it', () => {
|
||||
// The phone's pill styles live inside a media query the desktop rail never enters,
|
||||
// so the rail passes its own base class and gets the same badge in its own clothes.
|
||||
const app = loadOverviewApp();
|
||||
expect(app._buildWatchingBadge('1 shell', 'home-sessions-pill').className).toBe(
|
||||
'home-sessions-pill home-sessions-pill--watching'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user