Merge pull request #491 from irisitymichaelgrundberg/fix/artifact-comment-monitor-needs-you

fix(session): alert for an agent waiting on artifact comments

# Conflicts:
#	src/config/cli-registry/stock.ts
This commit is contained in:
Codeman maintainer
2026-09-28 16:20:52 +02:00
4 changed files with 52 additions and 2 deletions
+3
View File
@@ -67,6 +67,9 @@ agents` while a monitor, a backgrounded shell or a cloud session is live. Codema
into `Session.watching`, and an idle prompt from such a session opens already acknowledged,
so a pane waiting for its own background work never raises an alert a human cannot answer.
Group 1 is the label, and a CLI that declares no pattern reports no background work.
Claude's Artifact comment monitor is the one chip that does not count. It waits for a human
to comment on a page the agent published, so Claude's pattern refuses any footer that
carries it, and the idle alert goes out as usual.
Two CLIs declare such a row today, and they put it in different places. Claude writes its
chip on the last row of the screen, so it keeps the default one-row window and anchors on
+4
View File
@@ -127,6 +127,10 @@ plain prose is not a dialog, so an agent that starts a monitor and then writes "
should I target?" is quiet along with the rest — check a watching session yourself if it has
been quiet longer than the work it is waiting for should take.
An agent waiting for your comments on an artifact it published never counts as watching.
Claude shows that as "1 Artifact comment monitor", but the agent hears nothing until you
comment, so the session alerts you like any other quiet session.
## The phone overview
On phones, tapping the "C" logo gives a session overview with **NEEDS YOU** first, then
+9 -1
View File
@@ -237,7 +237,15 @@ const CLAUDE: CliEntry = {
// carry a count. A footer that ever drew the chip as its only item would report no
// watching rather than open that door. See `watchingLabel()` in
// `session-activity.ts`.
watchingLine: String.raw`·\s*(\d+ (?:monitors?|shells?|teams?|local agents?|cloud sessions?|MCP tasks?|background tasks?|(?:background|remote) dynamic workflows?|Artifact comment monitors?))`,
// ⚠️ An Artifact comment monitor is the one chip that waits on the user. The agent
// has published a page and hears nothing until somebody comments on it, so the
// lookahead refuses the whole row while that chip is on it, whatever else is
// running beside it. The `^` is what makes the lookahead judge the row once:
// without it the engine retries from each later position, and a start past the
// chip reports the shell beside it. The lookahead stops short of "monitor", so a
// footer cut off mid-chip still counts. Counting the chip as watching kept the
// idle alert quiet for a session that was waiting for a human.
watchingLine: String.raw`^(?!.*Artifact comment).*?·\s*(\d+ (?:monitors?|shells?|teams?|local agents?|cloud sessions?|MCP tasks?|background tasks?|(?:background|remote) dynamic workflows?))`,
// When a turn ends while background agents or an ultracode workflow are still
// running, Claude swaps its `✻ Brewed for 1m 18s` closing row for
// `✻ Waiting for 2 background agents and 1 dynamic workflow to finish` and resumes
+36 -1
View File
@@ -133,7 +133,6 @@ describe('watchingLabel', () => {
'1 MCP task',
'1 background dynamic workflow',
'2 remote dynamic workflows',
'1 Artifact comment monitor',
'2 teams',
];
for (const label of labels) {
@@ -141,6 +140,42 @@ describe('watchingLabel', () => {
}
});
it('reports no watching while the agent waits for comments on an artifact', () => {
// An agent that publishes an artifact arms a monitor for its comments and ends its
// turn. That monitor waits on the user, so the idle alert has to reach them. The
// singular footer is a live capture from 2026-09-25; the plural is assumed.
expect(
watchingLabel(pane('⏵⏵ bypass permissions on · 1 Artifact comment monitor · ← for agents'), CLAUDE_WATCHING)
).toBeNull();
expect(
watchingLabel(pane('⏵⏵ bypass permissions on · 2 Artifact comment monitors · ← for agents'), CLAUDE_WATCHING)
).toBeNull();
});
it('lets a comment monitor outrank other background work on the same row', () => {
// A shell beside the monitor is still running, but the agent needs the user all the
// same, and the chip order on the footer must not decide that. The second row is
// the one that needs the `^` in front of the lookahead.
expect(
watchingLabel(
pane('⏵⏵ bypass permissions on · 1 shell · 1 Artifact comment monitor · ← for agents'),
CLAUDE_WATCHING
)
).toBeNull();
expect(
watchingLabel(
pane('⏵⏵ bypass permissions on · 1 Artifact comment monitor · 1 shell · ← for agents'),
CLAUDE_WATCHING
)
).toBeNull();
});
it('still refuses a footer cut off in the middle of the comment monitor', () => {
expect(
watchingLabel(pane('⏵⏵ bypass permissions on · 1 shell · 1 Artifact comment moni…'), CLAUDE_WATCHING)
).toBeNull();
});
it('says nothing about a pane that is running nothing', () => {
expect(watchingLabel(NOTHING_RUNNING, CLAUDE_WATCHING)).toBeNull();
expect(watchingLabel('', CLAUDE_WATCHING)).toBeNull();