Skip to content

Commit ed2d0b7

Browse files
Derive Waterline list badges from actionability
1 parent 8155e6c commit ed2d0b7

5 files changed

Lines changed: 94 additions & 3 deletions

File tree

app/Support/ActionabilityContract.php

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ private static function runActionability(array $payload): array
132132
default => 'not_needed',
133133
};
134134

135+
$taskProblem = ($payload['task_problem'] ?? false) === true;
136+
135137
return [
136138
'schema' => self::SCHEMA,
137139
'version' => self::VERSION,
@@ -140,9 +142,13 @@ private static function runActionability(array $payload): array
140142
'blocked_reason' => $blockedReason,
141143
'status_bucket' => $statusBucket,
142144
'closed_reason' => $closedReason,
143-
'task_problem' => ($payload['task_problem'] ?? false) === true,
145+
'task_problem' => $taskProblem,
144146
'diagnostic_only_evidence' => self::hasDiagnosticOnlyEvidence($payload),
145147
'actions' => self::runActions($payload, $repairState, $blockedReason),
148+
'badges' => [
149+
'repair' => self::repairBadge($repairState, $blockedReason),
150+
'task_problem' => self::taskProblemBadge($taskProblem),
151+
],
146152
];
147153
}
148154

@@ -192,6 +198,63 @@ private static function repairBlockedReason(string $repairState, ?string $blocke
192198
};
193199
}
194200

201+
/**
202+
* @return array{code: ?string, label: string, description: string, tone: string, badge_visible: bool, derived_from: string}
203+
*/
204+
private static function repairBadge(string $repairState, ?string $blockedReason): array
205+
{
206+
$reason = self::repairBlockedReason($repairState, $blockedReason);
207+
208+
return [
209+
'code' => $reason,
210+
'label' => match ($reason) {
211+
'unsupported_history' => 'Replay Blocked',
212+
'selected_run_not_current' => 'Run Not Current',
213+
'run_closed' => 'Run Closed',
214+
'waiting_for_compatible_worker' => 'Compatibility Wait',
215+
'repair_not_needed' => 'Repair Not Needed',
216+
'repair_state_unknown' => 'Repair Unknown',
217+
default => $repairState === 'repairable' ? 'Repairable' : 'Repair Blocked',
218+
},
219+
'description' => match ($reason) {
220+
'unsupported_history' => 'Repair is blocked because only unsupported diagnostic history remains.',
221+
'selected_run_not_current' => 'Repair is blocked because the selected run is not the current active run.',
222+
'run_closed' => 'Repair is blocked because the run is already closed.',
223+
'waiting_for_compatible_worker' => 'Repair is waiting for an active compatible worker.',
224+
'repair_not_needed' => 'Repair is not needed for this run.',
225+
'repair_state_unknown' => 'Waterline has not classified this run as repairable yet.',
226+
default => $repairState === 'repairable'
227+
? 'This run has an actionable durable repair source.'
228+
: 'Repair is currently blocked.',
229+
},
230+
'tone' => match ($reason) {
231+
'unsupported_history', 'selected_run_not_current', 'run_closed' => 'dark',
232+
'waiting_for_compatible_worker', 'repair_state_unknown' => 'warning',
233+
'repair_not_needed' => 'secondary',
234+
default => $repairState === 'repairable' ? 'success' : 'secondary',
235+
},
236+
'badge_visible' => $repairState === 'blocked',
237+
'derived_from' => 'repair_state',
238+
];
239+
}
240+
241+
/**
242+
* @return array{code: ?string, label: string, description: string, tone: string, badge_visible: bool, derived_from: string}
243+
*/
244+
private static function taskProblemBadge(bool $taskProblem): array
245+
{
246+
return [
247+
'code' => $taskProblem ? 'task_problem' : null,
248+
'label' => $taskProblem ? 'Task Problem' : 'No Task Problem',
249+
'description' => $taskProblem
250+
? 'This run recorded workflow-task problems.'
251+
: 'This run has not recorded workflow-task problems.',
252+
'tone' => $taskProblem ? 'warning' : 'secondary',
253+
'badge_visible' => $taskProblem,
254+
'derived_from' => self::SCHEMA,
255+
];
256+
}
257+
195258
/**
196259
* @param array<string, mixed> $payload
197260
*/

public/app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/mix-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"/app.js": "/app.js?id=bbec336332163e9c26b71b93398fbf3b",
2+
"/app.js": "/app.js?id=b411ae7fdc166fb6effcde55a370168f",
33
"/app-dark.css": "/app-dark.css?id=64d24ee96944ffdb4b26a9be1658c1e3",
44
"/app.css": "/app.css?id=d525454610dfd3c5a581fc49676f8a37",
55
"/img/favicon.png": "/img/favicon.png?id=7c006241b093796d6abfa3049df93a59",

resources/js/screens/flows/flow-row.vue

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@
244244
},
245245
246246
repairBlocked(flow) {
247+
const badge = this.actionabilityBadge(flow, 'repair')
248+
249+
if (badge) {
250+
return badge
251+
}
252+
247253
return flow && flow.repair_blocked
248254
? flow.repair_blocked
249255
: null
@@ -278,11 +284,24 @@
278284
},
279285
280286
taskProblem(flow) {
287+
const badge = this.actionabilityBadge(flow, 'task_problem')
288+
289+
if (badge) {
290+
return badge
291+
}
292+
281293
return flow && flow.task_problem_badge
282294
? flow.task_problem_badge
283295
: null
284296
},
285297
298+
actionabilityBadge(flow, name) {
299+
const actionability = flow && flow.actionability ? flow.actionability : null
300+
const badges = actionability && actionability.badges ? actionability.badges : null
301+
302+
return badges && badges[name] ? badges[name] : null
303+
},
304+
286305
showCompatibilityEntryBadge(flow) {
287306
return flow && flow.declared_entry_mode === 'compatibility'
288307
},

tests/Feature/V2DashboardWorkflowListTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,8 +951,17 @@ public function testV2ListResponseItemsMatchTypedListItemContract(): void
951951
$this->assertFalse($item['actionability']['actions']['repair']['allowed']);
952952
$this->assertSame('unsupported_history', $item['actionability']['actions']['repair']['reason']);
953953
$this->assertSame('repair_state', $item['actionability']['actions']['repair']['derived_from']);
954+
$this->assertSame('unsupported_history', $item['actionability']['badges']['repair']['code']);
955+
$this->assertSame('Replay Blocked', $item['actionability']['badges']['repair']['label']);
956+
$this->assertSame('dark', $item['actionability']['badges']['repair']['tone']);
957+
$this->assertTrue($item['actionability']['badges']['repair']['badge_visible']);
958+
$this->assertSame('repair_state', $item['actionability']['badges']['repair']['derived_from']);
954959
$this->assertTrue($item['task_problem']);
955960
$this->assertIsArray($item['task_problem_badge']);
961+
$this->assertSame('task_problem', $item['actionability']['badges']['task_problem']['code']);
962+
$this->assertSame('Task Problem', $item['actionability']['badges']['task_problem']['label']);
963+
$this->assertTrue($item['actionability']['badges']['task_problem']['badge_visible']);
964+
$this->assertSame('waterline.actionability', $item['actionability']['badges']['task_problem']['derived_from']);
956965
$this->assertSame('compatibility', $item['declared_entry_mode']);
957966
$this->assertSame('live_definition', $item['declared_contract_source']);
958967
$this->assertSame('no_required_marker', $item['compatibility_semantics']['state']);

0 commit comments

Comments
 (0)