Skip to content

Commit 26301b7

Browse files
TD-078: render info-severity doctor issues distinctly from warnings
BackendCapabilities marks poll-mode queue_sync_unsupported and queue_connection_missing diagnostics as severity=info, but the doctor command routed every non-error issue through warn(), so a healthy service/poll-mode deployment rendered an informational queue note in the amber [WARN] band that operators treat as a real configuration problem. V2DoctorCommand::renderHumanSnapshot() now branches on severity and prefixes the message with the severity level: [ERROR] issues stay on error(), [WARN] issues stay on warn(), and [INFO] issues fall through to line() so they do not carry warning styling. Regression coverage in V2DoctorCommandTest proves three paths: poll-mode sync queue → [INFO] + strict success, poll-mode missing connection → [INFO] + strict success, queue-mode sync queue → [ERROR] + strict failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 820476e commit 26301b7

2 files changed

Lines changed: 53 additions & 6 deletions

File tree

src/Commands/V2DoctorCommand.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,19 @@ private function renderHumanSnapshot(array $snapshot): void
6666
continue;
6767
}
6868

69+
$severity = (string) ($issue['severity'] ?? 'warn');
6970
$message = sprintf(
70-
'[%s] %s',
71+
'[%s] [%s] %s',
72+
strtoupper($severity),
7173
(string) ($issue['code'] ?? 'capability_issue'),
7274
(string) ($issue['message'] ?? 'Capability issue detected.'),
7375
);
7476

75-
if (($issue['severity'] ?? null) === 'error') {
76-
$this->error($message);
77-
} else {
78-
$this->warn($message);
79-
}
77+
match ($severity) {
78+
'error' => $this->error($message),
79+
'info' => $this->line($message),
80+
default => $this->warn($message),
81+
};
8082
}
8183
}
8284

tests/Unit/Commands/V2DoctorCommandTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,49 @@ public function testJsonOutputSucceedsWithoutStrictMode(): void
2929
'--json' => true,
3030
])->assertSuccessful();
3131
}
32+
33+
public function testPollModeSyncQueueIsReportedAsInfoNotWarning(): void
34+
{
35+
// TD-078: in poll mode the queue-driver diagnostic is informational,
36+
// not a capability failure. The doctor command must render it with an
37+
// [INFO] tag rather than Laravel's amber [WARN] tag, and --strict must
38+
// still succeed.
39+
config()->set('queue.default', 'sync');
40+
config()->set('queue.connections.sync.driver', 'sync');
41+
config()->set('workflows.v2.task_dispatch_mode', 'poll');
42+
43+
$this->artisan('workflow:v2:doctor', ['--strict' => true])
44+
->expectsOutputToContain('[INFO] [queue_sync_unsupported]')
45+
->doesntExpectOutputToContain('[WARN] [queue_sync_unsupported]')
46+
->assertSuccessful();
47+
}
48+
49+
public function testPollModeMissingQueueConnectionIsReportedAsInfoNotWarning(): void
50+
{
51+
// Mirror of the sync-driver case for a missing queue connection in
52+
// poll mode. Same rule: info-severity output, not a warning, and
53+
// --strict still succeeds.
54+
config()->set('queue.default', 'missing-driver');
55+
config()->set('queue.connections.missing-driver', []);
56+
config()->set('workflows.v2.task_dispatch_mode', 'poll');
57+
58+
$this->artisan('workflow:v2:doctor', ['--strict' => true])
59+
->expectsOutputToContain('[INFO] [queue_connection_missing]')
60+
->doesntExpectOutputToContain('[WARN] [queue_connection_missing]')
61+
->assertSuccessful();
62+
}
63+
64+
public function testQueueModeSyncQueueIsReportedAsErrorAndFailsStrict(): void
65+
{
66+
// The flip side of the poll-mode relaxation: in default queue mode
67+
// a sync driver is an error-severity capability failure. The doctor
68+
// command must render it with [ERROR] and --strict must fail.
69+
config()->set('queue.default', 'sync');
70+
config()->set('queue.connections.sync.driver', 'sync');
71+
config()->set('workflows.v2.task_dispatch_mode', 'queue');
72+
73+
$this->artisan('workflow:v2:doctor', ['--strict' => true])
74+
->expectsOutputToContain('[ERROR] [queue_sync_unsupported]')
75+
->assertFailed();
76+
}
3277
}

0 commit comments

Comments
 (0)