@zq-silk/yui 0.6.8 → 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/cli/commandCatalog.js +1 -1
- package/dist/commands/taskCommands.js +63 -28
- package/dist/commands/taskContextCommand.js +27 -1
- package/dist/commands/taskRoleRuntimeStatus.js +17 -6
- package/dist/controller/agentRuntimeObserver.js +6 -3
- package/dist/controller/controller.js +29 -47
- package/dist/controller/fileSchedulerStoreAdapter.js +572 -258
- package/dist/controller/runtime.js +8 -1
- package/dist/controller/runtimeEventInbox.js +16 -5
- package/dist/controller/runtimeHookRunFence.js +51 -5
- package/dist/controller/runtimeObservationHook.js +8 -2
- package/dist/coordination/workMailbox.js +408 -28
- package/dist/coordination/workMailboxQueue.js +12 -10
- package/dist/executor/agentExecutor.js +101 -94
- package/dist/executor/executorRegistry.js +47 -2
- package/dist/executor/fileRoleLaunchPlanner.js +4 -2
- package/dist/lifecycle/exactRunTerminalization.js +1 -7
- package/dist/repository/taskWorkspaceCoordinator.js +9 -4
- package/dist/runtime/agentDriver.js +83 -4
- package/dist/runtime/agentDriverObservation.js +25 -10
- package/dist/runtime/builtinAgentDrivers.js +168 -18
- package/dist/runtime/codexAppServerRuntime.js +355 -0
- package/dist/runtime/continuationManager.js +117 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/lifecycleReservation.js +4 -3
- package/dist/runtime/promptEnvelope.js +14 -3
- package/dist/runtime/providerContinuation.js +225 -0
- package/dist/runtime/providerContinuationReconciliationService.js +172 -0
- package/dist/runtime/providerRuntimeIdentity.js +232 -0
- package/dist/runtime/providerRuntimeReconciler.js +166 -0
- package/dist/runtime/runtimeContinuationProjection.js +34 -0
- package/dist/runtime/runtimeObservation.js +217 -6
- package/dist/runtime/runtimeProjection.js +172 -11
- package/dist/scheduler/activeRoleRunDelivery.js +314 -1
- package/dist/scheduler/leaderWakeupProcessor.js +2 -1
- package/dist/scheduler/operatorInputNotificationProcessor.js +3 -2
- package/dist/scheduler/roleRunLiveness.js +8 -7
- package/dist/scheduler/roleRunStall.js +4 -2
- package/dist/scheduler/taskExecutionProjection.js +2 -2
- package/dist/storage/migration/productionRegistry.js +474 -1
- package/dist/storage/sqliteSchema.js +102 -21
- package/dist/storage/sqliteStore.js +52 -110
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +0 -1
- package/dist/storage/taskStore.js +40 -53
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -21
- package/dist/task/nextAction.js +1 -1
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +233 -4
- package/dist/web/assets/client/i18n.js +166 -2
- package/dist/web/assets/client/view.js +30 -13
- package/dist/web/assets/styles/cards.js +62 -0
- package/dist/web/assets/styles/widgets.js +1 -0
- package/dist/web/webSnapshot.js +11 -2
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +33 -24
- package/skills/yui-operator/SKILL.md +7 -5
|
@@ -88,6 +88,159 @@ export function anchorSection(id, head, body) {
|
|
|
88
88
|
return section;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// --- Task-first execution status -------------------------------------------
|
|
92
|
+
// The projection is the current read-model vocabulary: one derived status,
|
|
93
|
+
// owner, next action, and the attention/blocker facts behind it.
|
|
94
|
+
const EXEC_STATUS_TONE = {
|
|
95
|
+
"needs-leader-action": "is-accent",
|
|
96
|
+
"waiting-on-agents": "is-active",
|
|
97
|
+
"waiting-user": "is-warning",
|
|
98
|
+
"recovering": "is-warning",
|
|
99
|
+
"attention": "is-danger",
|
|
100
|
+
"progressing-with-attention": "is-warning",
|
|
101
|
+
"blocked": "is-danger",
|
|
102
|
+
"working": "is-active",
|
|
103
|
+
"completed": "is-muted",
|
|
104
|
+
"retired": "is-muted",
|
|
105
|
+
"archived": "is-muted"
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export function executionBand(projection, t, locale) {
|
|
109
|
+
if (!projection) return null;
|
|
110
|
+
const tone = EXEC_STATUS_TONE[projection.status] || "";
|
|
111
|
+
const band = node("div", "exec-band " + tone);
|
|
112
|
+
|
|
113
|
+
const head = node("div", "exec-band-head");
|
|
114
|
+
head.append(pill(t, "exec.status", projection.status));
|
|
115
|
+
head.append(node("span", "exec-band-owner",
|
|
116
|
+
t("exec.owner." + projection.owner) + " · " + t("exec.action." + projection.action)));
|
|
117
|
+
if (projection.activeExecutorCount > 0) {
|
|
118
|
+
head.append(node("span", "exec-band-executors",
|
|
119
|
+
projection.activeExecutorCount + " " + t("exec.executors")));
|
|
120
|
+
}
|
|
121
|
+
if (projection.monitoring === "stopped") {
|
|
122
|
+
head.append(node("span", "exec-band-stopped", t("exec.monitoring.stopped")));
|
|
123
|
+
}
|
|
124
|
+
if (projection.failClosed) {
|
|
125
|
+
head.append(node("span", "exec-band-failclosed", t("exec.failClosed")));
|
|
126
|
+
}
|
|
127
|
+
band.append(head);
|
|
128
|
+
|
|
129
|
+
if (projection.summary) {
|
|
130
|
+
band.append(node("p", "exec-band-summary", projection.summary));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (projection.attention && projection.attention.length) {
|
|
134
|
+
const list = node("div", "exec-signal-list");
|
|
135
|
+
projection.attention.forEach(function (item) {
|
|
136
|
+
const row = node("div", "exec-signal is-attention");
|
|
137
|
+
row.append(node("span", "exec-signal-kind", t("exec.attention." + item.kind)));
|
|
138
|
+
row.append(node("span", "exec-signal-text", item.summary));
|
|
139
|
+
list.append(row);
|
|
140
|
+
});
|
|
141
|
+
band.append(list);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (projection.blockers && projection.blockers.length) {
|
|
145
|
+
const list = node("div", "exec-signal-list");
|
|
146
|
+
projection.blockers.forEach(function (blocker) {
|
|
147
|
+
const row = node("div", "exec-signal is-blocker");
|
|
148
|
+
row.append(node("span", "exec-signal-kind",
|
|
149
|
+
t("exec.blocker." + blocker.kind) + " · " + t("exec.owner." + blocker.owner)));
|
|
150
|
+
row.append(node("span", "exec-signal-text", blocker.summary));
|
|
151
|
+
list.append(row);
|
|
152
|
+
});
|
|
153
|
+
band.append(list);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return band;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// --- Unified execution Group (Lanes + resolution) ---------------------------
|
|
160
|
+
export function executionGroupCard(summary, t, locale) {
|
|
161
|
+
const card = node("article", "record-card exec-group");
|
|
162
|
+
const head = node("div", "record-head");
|
|
163
|
+
const titleRow = node("div", "record-title-row");
|
|
164
|
+
titleRow.append(node("strong", "record-title", summary.groupId));
|
|
165
|
+
head.append(titleRow);
|
|
166
|
+
const pills = node("div", "record-pills");
|
|
167
|
+
pills.append(pill(t, "exec.purpose", summary.purpose));
|
|
168
|
+
const strategy = summary.strategy.mode === "fixed"
|
|
169
|
+
? t("exec.strategy.fixed").replace("{count}", String(summary.strategy.count))
|
|
170
|
+
: t("exec.strategy.adaptive").replace("{max}", String(summary.strategy.max));
|
|
171
|
+
pills.append(chip(strategy));
|
|
172
|
+
if (summary.failedLaneCount > 0) {
|
|
173
|
+
pills.append(chip(summary.failedLaneCount + " " + t("exec.lanesFailed"), "is-danger"));
|
|
174
|
+
}
|
|
175
|
+
head.append(pills);
|
|
176
|
+
card.append(head);
|
|
177
|
+
|
|
178
|
+
const lanes = node("div", "lane-list");
|
|
179
|
+
summary.laneSummaries.forEach(function (lane) {
|
|
180
|
+
const row = node("div", "lane-row");
|
|
181
|
+
row.append(statusDot(lane.status));
|
|
182
|
+
row.append(node("span", "lane-role", lane.roleName));
|
|
183
|
+
row.append(node("span", "lane-status", t("lane." + lane.status)));
|
|
184
|
+
if (lane.summary) {
|
|
185
|
+
row.append(node("span", "lane-summary", lane.summary));
|
|
186
|
+
}
|
|
187
|
+
if (lane.decision) {
|
|
188
|
+
row.append(chip(t("resolution." + lane.decision), "is-active"));
|
|
189
|
+
}
|
|
190
|
+
lanes.append(row);
|
|
191
|
+
});
|
|
192
|
+
card.append(lanes);
|
|
193
|
+
|
|
194
|
+
if (summary.resolution) {
|
|
195
|
+
const res = node("div", "exec-resolution");
|
|
196
|
+
res.append(node("span", "exec-resolution-decision",
|
|
197
|
+
t("resolution." + summary.resolution.decision)));
|
|
198
|
+
res.append(node("span", "exec-resolution-summary", summary.resolution.summary));
|
|
199
|
+
res.append(node("time", "", formatDateTime(summary.resolution.decidedAt, locale)));
|
|
200
|
+
card.append(res);
|
|
201
|
+
}
|
|
202
|
+
return card;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// --- WorkItem Candidates -----------------------------------------------------
|
|
206
|
+
export function candidateList(candidates, t, locale) {
|
|
207
|
+
if (!candidates || !candidates.length) return null;
|
|
208
|
+
const block = node("div", "record-block");
|
|
209
|
+
block.append(node("small", "", t("detail.candidates")));
|
|
210
|
+
const list = node("div", "candidate-list");
|
|
211
|
+
candidates.slice().sort(function (a, b) { return b.sequence - a.sequence; })
|
|
212
|
+
.forEach(function (candidate) {
|
|
213
|
+
const row = node("div", "candidate-row");
|
|
214
|
+
row.append(node("span", "candidate-seq", "#" + candidate.sequence));
|
|
215
|
+
row.append(node("span", "candidate-summary", candidate.summary));
|
|
216
|
+
const source = candidate.source.type === "direct"
|
|
217
|
+
? t("candidate.source.direct")
|
|
218
|
+
: t("candidate.source.run") + " " + candidate.source.runId;
|
|
219
|
+
row.append(node("span", "candidate-source", source));
|
|
220
|
+
row.append(node("time", "", formatDateTime(candidate.createdAt, locale)));
|
|
221
|
+
list.append(row);
|
|
222
|
+
});
|
|
223
|
+
block.append(list);
|
|
224
|
+
return block;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// --- Execution findings (checks / review findings) ---------------------------
|
|
228
|
+
export function findingsBlock(label, findings, t) {
|
|
229
|
+
if (!findings || !findings.length) return null;
|
|
230
|
+
const block = node("div", "record-block");
|
|
231
|
+
block.append(node("small", "", label));
|
|
232
|
+
const list = node("div", "finding-list");
|
|
233
|
+
findings.forEach(function (finding) {
|
|
234
|
+
const row = node("div", "finding-row is-" + finding.severity);
|
|
235
|
+
row.append(chip(t("finding.severity." + finding.severity), "is-" + finding.severity));
|
|
236
|
+
row.append(node("span", "finding-summary", finding.summary));
|
|
237
|
+
row.append(chip(t("finding.status." + finding.status)));
|
|
238
|
+
list.append(row);
|
|
239
|
+
});
|
|
240
|
+
block.append(list);
|
|
241
|
+
return block;
|
|
242
|
+
}
|
|
243
|
+
|
|
91
244
|
// --- Progressive disclosure --------------------------------------------------
|
|
92
245
|
// Re-render is cheap and happens whenever the underlying data changes, so all
|
|
93
246
|
// disclosure state (collapsed blocks, visible pages) is deliberately
|
|
@@ -242,6 +395,10 @@ export function inputCard(input, _options, t, locale, actions) {
|
|
|
242
395
|
const blocked = input.blockedRefs.map(function (ref) { return ref.type + "·" + ref.id; }).join(" ");
|
|
243
396
|
top.append(node("span", "input-blocked", blocked));
|
|
244
397
|
}
|
|
398
|
+
if (input.requester) {
|
|
399
|
+
top.append(node("span", "input-requester",
|
|
400
|
+
t("detail.requester") + " · " + input.requester.roleName + " / " + input.requester.runId));
|
|
401
|
+
}
|
|
245
402
|
card.append(top);
|
|
246
403
|
card.append(answerActions(input, actions, t));
|
|
247
404
|
return card;
|
|
@@ -286,6 +443,9 @@ export function workItemCard(item, titles, t, locale, actions, taskId) {
|
|
|
286
443
|
if (item.assignee) meta.append(node("span", "meta-name", item.assignee));
|
|
287
444
|
meta.append(node("span", "mono", item.id));
|
|
288
445
|
meta.append(node("time", "", formatDateTime(item.updatedAt, locale)));
|
|
446
|
+
if (item.endedAt) {
|
|
447
|
+
meta.append(node("span", "", t("detail.endedAt") + " · " + formatDateTime(item.endedAt, locale)));
|
|
448
|
+
}
|
|
289
449
|
body.append(meta);
|
|
290
450
|
|
|
291
451
|
if (item.objective && item.objective !== item.title) {
|
|
@@ -307,6 +467,28 @@ export function workItemCard(item, titles, t, locale, actions, taskId) {
|
|
|
307
467
|
}
|
|
308
468
|
if (chipCols.childNodes.length) body.append(chipCols);
|
|
309
469
|
|
|
470
|
+
// Current execution iteration: the unified Group with its Lanes and the
|
|
471
|
+
// Leader's resolution when the iteration is settled.
|
|
472
|
+
if (item.currentExecution) {
|
|
473
|
+
body.append(executionGroupCard(item.currentExecution, t, locale));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Review candidates submitted for this WorkItem, newest first.
|
|
477
|
+
const candidates = candidateList(item.candidates, t, locale);
|
|
478
|
+
if (candidates) body.append(candidates);
|
|
479
|
+
|
|
480
|
+
// Explicit Leader retirement disposition.
|
|
481
|
+
if (item.disposition) {
|
|
482
|
+
const disposition = node("div", "record-block disposition-block");
|
|
483
|
+
disposition.append(node("small", "", t("detail.disposition")));
|
|
484
|
+
const text = item.disposition.summary
|
|
485
|
+
+ (item.disposition.replacementWorkItemId
|
|
486
|
+
? " · " + t("detail.replacementWorkItem") + " " + item.disposition.replacementWorkItemId
|
|
487
|
+
: "");
|
|
488
|
+
disposition.append(node("p", "muted", text));
|
|
489
|
+
body.append(disposition);
|
|
490
|
+
}
|
|
491
|
+
|
|
310
492
|
if (item.outcome) {
|
|
311
493
|
body.append(richText(t("detail.outcome"), item.outcome, t, { extraClass: "outcome-callout", muted: true }));
|
|
312
494
|
}
|
|
@@ -323,7 +505,8 @@ export function runCard(run, t, locale) {
|
|
|
323
505
|
idRow.append(node("span", "role", run.roleName));
|
|
324
506
|
idRow.append(node("span", "", run.id));
|
|
325
507
|
if (run.workItemId) idRow.append(node("span", "", t("detail.workItem") + " · " + run.workItemId));
|
|
326
|
-
idRow.append(
|
|
508
|
+
if (run.purpose) idRow.append(chip(t("run.purpose." + run.purpose)));
|
|
509
|
+
idRow.append(node("time", "", formatDateTime(run.endedAt || run.updatedAt, locale)));
|
|
327
510
|
card.append(idRow);
|
|
328
511
|
|
|
329
512
|
card.append(richText(t("detail.instruction"), run.input, t, { className: "execute-io", threshold: 320 }));
|
|
@@ -334,6 +517,10 @@ export function runCard(run, t, locale) {
|
|
|
334
517
|
const foot = node("div", "execute-foot");
|
|
335
518
|
const tags = node("div", "execute-tags");
|
|
336
519
|
tags.append(chip(t("mode." + run.mode)));
|
|
520
|
+
if (run.executionGroupId) {
|
|
521
|
+
tags.append(chip(t("detail.lineage") + " · " + run.executionGroupId
|
|
522
|
+
+ (run.executionLaneId ? "/" + run.executionLaneId : "")));
|
|
523
|
+
}
|
|
337
524
|
const deliveryKey = run.deliveredAt
|
|
338
525
|
? "delivery.delivered"
|
|
339
526
|
: run.pushedAt
|
|
@@ -354,6 +541,26 @@ export function runCard(run, t, locale) {
|
|
|
354
541
|
card.append(eff);
|
|
355
542
|
}
|
|
356
543
|
|
|
544
|
+
// Leader Run disposition: the machine-derived outcome of a terminal Leader
|
|
545
|
+
// Run, plus any structured wait reference.
|
|
546
|
+
if (run.disposition) {
|
|
547
|
+
const disposition = node("div", "record-meta");
|
|
548
|
+
disposition.append(node("span", "", t("run.disposition") + " · " + t("run.disposition." + run.disposition)));
|
|
549
|
+
if (run.waitReason) {
|
|
550
|
+
disposition.append(node("span", "", t("run.waitReason") + " · " + run.waitReason.kind
|
|
551
|
+
+ (run.waitReason.ref ? " (" + run.waitReason.ref + ")" : "")));
|
|
552
|
+
}
|
|
553
|
+
card.append(disposition);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Idempotent yield receipt on a yielded Run.
|
|
557
|
+
if (run.yieldReceipt) {
|
|
558
|
+
const receipt = node("div", "record-meta");
|
|
559
|
+
receipt.append(node("span", "mono", t("run.yieldReceipt") + " · " + run.yieldReceipt.receiptId));
|
|
560
|
+
receipt.append(node("time", "", formatDateTime(run.yieldReceipt.committedAt, locale)));
|
|
561
|
+
card.append(receipt);
|
|
562
|
+
}
|
|
563
|
+
|
|
357
564
|
return card;
|
|
358
565
|
}
|
|
359
566
|
|
|
@@ -363,7 +570,10 @@ export function reviewCard(round, t, locale) {
|
|
|
363
570
|
const titleRow = node("div", "record-title-row");
|
|
364
571
|
titleRow.append(node("strong", "record-title", round.id));
|
|
365
572
|
head.append(titleRow);
|
|
366
|
-
|
|
573
|
+
const headPills = node("div", "record-pills");
|
|
574
|
+
if (round.scope) headPills.append(pill(t, "review.scope", round.scope));
|
|
575
|
+
headPills.append(pill(t, "review", round.status));
|
|
576
|
+
head.append(headPills);
|
|
367
577
|
card.append(head);
|
|
368
578
|
const meta = node("div", "record-meta");
|
|
369
579
|
meta.append(node("span", "meta-name", round.reviewerRoleName));
|
|
@@ -376,13 +586,20 @@ export function reviewCard(round, t, locale) {
|
|
|
376
586
|
if (round.evidenceCommit) {
|
|
377
587
|
meta.append(node("span", "", t("detail.evidence") + " · " + round.evidenceCommit));
|
|
378
588
|
}
|
|
589
|
+
if (round.workspaceDisposition) {
|
|
590
|
+
meta.append(node("span", "", t("detail.workspaceDisposition") + " · "
|
|
591
|
+
+ t("disposition." + round.workspaceDisposition.kind)));
|
|
592
|
+
}
|
|
379
593
|
card.append(meta);
|
|
380
594
|
if (round.checks && round.checks.length) {
|
|
381
595
|
card.append(richText(t("detail.checks"), round.checks.map(function (check) {
|
|
382
596
|
return check.name + "=" + check.outcome;
|
|
383
597
|
}).join(", "), t));
|
|
384
598
|
}
|
|
599
|
+
const findings = findingsBlock(t("detail.findings"), round.findings, t);
|
|
600
|
+
if (findings) card.append(findings);
|
|
385
601
|
if (round.summary) card.append(richText(null, round.summary, t));
|
|
602
|
+
if (round.report) card.append(richText(t("detail.report"), round.report, t, { muted: true }));
|
|
386
603
|
return card;
|
|
387
604
|
}
|
|
388
605
|
|
|
@@ -562,14 +779,18 @@ export function attentionRow(item, t, locale, onSelect) {
|
|
|
562
779
|
return row;
|
|
563
780
|
}
|
|
564
781
|
|
|
565
|
-
export function overviewRow(task, t, locale, onSelect) {
|
|
782
|
+
export function overviewRow(task, label, variant, t, locale, onSelect) {
|
|
566
783
|
const hasInputs = task.openInputCount > 0;
|
|
567
|
-
const row = node("button", "overview-row"
|
|
784
|
+
const row = node("button", "overview-row"
|
|
785
|
+
+ (hasInputs || variant === "has-inputs" ? " has-inputs" : ""));
|
|
568
786
|
row.type = "button";
|
|
569
787
|
row.append(statusDot(task.status));
|
|
570
788
|
const main = node("span", "overview-row-title", task.title);
|
|
571
789
|
main.title = task.title;
|
|
572
790
|
row.append(main);
|
|
791
|
+
if (label) {
|
|
792
|
+
row.append(node("span", "overview-row-label", label));
|
|
793
|
+
}
|
|
573
794
|
row.append(node("span", "overview-row-time", relativeTime(task.updatedAt, locale, t)));
|
|
574
795
|
row.addEventListener("click", function () { onSelect(task.id); });
|
|
575
796
|
return row;
|
|
@@ -588,6 +809,14 @@ export function taskCard(task, hasAttention, state, t, locale, onSelect) {
|
|
|
588
809
|
main.append(node("span", "task-meta", relativeTime(task.updatedAt, locale, t)));
|
|
589
810
|
button.append(main);
|
|
590
811
|
|
|
812
|
+
// Derived Task-first execution status for active tasks (blocked, waiting on
|
|
813
|
+
// agents, recovering, etc.) — a richer signal than the raw lifecycle status.
|
|
814
|
+
if (task.executionStatus && task.status === "active") {
|
|
815
|
+
const exec = node("span", "task-exec is-" + task.executionStatus,
|
|
816
|
+
t("exec.status." + task.executionStatus));
|
|
817
|
+
button.append(exec);
|
|
818
|
+
}
|
|
819
|
+
|
|
591
820
|
// One signal only: an open input (needs the user) outranks a running count.
|
|
592
821
|
if (hasAttention) {
|
|
593
822
|
const badge = node("span", "task-signal is-input", String(task.openInputCount || 1));
|
|
@@ -117,6 +117,7 @@ const messages = {
|
|
|
117
117
|
"group.attention": "Needs input",
|
|
118
118
|
"group.draft": "Draft",
|
|
119
119
|
"group.finished": "Completed",
|
|
120
|
+
"group.retired": "Retired",
|
|
120
121
|
"input.answered": "Input answered.",
|
|
121
122
|
"input.blocking": "Blocking",
|
|
122
123
|
"input.freeText": "Type your answer",
|
|
@@ -214,7 +215,88 @@ const messages = {
|
|
|
214
215
|
"work.superseded": "Superseded",
|
|
215
216
|
"stats.running": "running",
|
|
216
217
|
"stats.inputs": "inputs",
|
|
217
|
-
"stats.stalledRuns": "stalled Runs"
|
|
218
|
+
"stats.stalledRuns": "stalled Runs",
|
|
219
|
+
"exec.status.needs-leader-action": "Needs leader action",
|
|
220
|
+
"exec.status.waiting-on-agents": "Waiting on agents",
|
|
221
|
+
"exec.status.waiting-user": "Waiting on you",
|
|
222
|
+
"exec.status.recovering": "Recovering",
|
|
223
|
+
"exec.status.attention": "Needs attention",
|
|
224
|
+
"exec.status.progressing-with-attention": "Progressing with attention",
|
|
225
|
+
"exec.status.blocked": "Blocked",
|
|
226
|
+
"exec.status.working": "Working",
|
|
227
|
+
"exec.status.completed": "Completed",
|
|
228
|
+
"exec.status.retired": "Retired",
|
|
229
|
+
"exec.status.archived": "Archived",
|
|
230
|
+
"exec.owner.leader": "Leader",
|
|
231
|
+
"exec.owner.worker": "Worker",
|
|
232
|
+
"exec.owner.reviewer": "Reviewer",
|
|
233
|
+
"exec.owner.tester": "Tester",
|
|
234
|
+
"exec.owner.operator": "Operator",
|
|
235
|
+
"exec.owner.user": "You",
|
|
236
|
+
"exec.owner.none": "—",
|
|
237
|
+
"exec.action.advance-task": "Advance task",
|
|
238
|
+
"exec.action.wait-for-agents": "Wait for agents",
|
|
239
|
+
"exec.action.answer-input": "Answer input",
|
|
240
|
+
"exec.action.inspect-attention": "Inspect attention",
|
|
241
|
+
"exec.action.recover-leader": "Recover leader",
|
|
242
|
+
"exec.action.resolve-blocker": "Resolve blocker",
|
|
243
|
+
"exec.action.complete-task": "Complete task",
|
|
244
|
+
"exec.action.none": "—",
|
|
245
|
+
"exec.attention.leader-recovery": "Leader recovery",
|
|
246
|
+
"exec.attention.leader-stalled": "Leader stalled",
|
|
247
|
+
"exec.attention.checkpoint-overdue": "Checkpoint overdue",
|
|
248
|
+
"exec.attention.identity-mismatch": "Identity mismatch",
|
|
249
|
+
"exec.attention.delivery-uncertain": "Delivery uncertain",
|
|
250
|
+
"exec.blocker.work": "Work",
|
|
251
|
+
"exec.blocker.review": "Review",
|
|
252
|
+
"exec.blocker.integration": "Integration",
|
|
253
|
+
"exec.blocker.input": "Input",
|
|
254
|
+
"exec.blocker.identity": "Identity",
|
|
255
|
+
"exec.monitoring.stopped": "Monitoring stopped",
|
|
256
|
+
"exec.failClosed": "Fail-closed",
|
|
257
|
+
"exec.executors": "active",
|
|
258
|
+
"exec.purpose.execution": "Execution",
|
|
259
|
+
"exec.purpose.review": "Review",
|
|
260
|
+
"exec.strategy.fixed": "Fixed · {count} lanes",
|
|
261
|
+
"exec.strategy.adaptive": "Adaptive · up to {max}",
|
|
262
|
+
"exec.lanesFailed": "failed",
|
|
263
|
+
"lane.pending": "Pending",
|
|
264
|
+
"lane.running": "Running",
|
|
265
|
+
"lane.yielded": "Yielded",
|
|
266
|
+
"lane.completed": "Completed",
|
|
267
|
+
"lane.failed": "Failed",
|
|
268
|
+
"resolution.accept": "Accepted",
|
|
269
|
+
"resolution.reject": "Rejected",
|
|
270
|
+
"resolution.retry": "Retry",
|
|
271
|
+
"resolution.blocked": "Blocked",
|
|
272
|
+
"detail.candidates": "Candidates",
|
|
273
|
+
"detail.disposition": "Retirement",
|
|
274
|
+
"detail.replacementWorkItem": "Replaced by",
|
|
275
|
+
"detail.endedAt": "Ended",
|
|
276
|
+
"detail.findings": "Findings",
|
|
277
|
+
"detail.report": "Report",
|
|
278
|
+
"detail.workspaceDisposition": "Workspace",
|
|
279
|
+
"detail.lineage": "Execution",
|
|
280
|
+
"detail.requester": "Requested by",
|
|
281
|
+
"candidate.source.direct": "Direct",
|
|
282
|
+
"candidate.source.run": "Run",
|
|
283
|
+
"finding.severity.low": "Low",
|
|
284
|
+
"finding.severity.medium": "Medium",
|
|
285
|
+
"finding.severity.high": "High",
|
|
286
|
+
"finding.severity.critical": "Critical",
|
|
287
|
+
"finding.status.open": "Open",
|
|
288
|
+
"finding.status.resolved": "Resolved",
|
|
289
|
+
"run.purpose.execution": "Execution",
|
|
290
|
+
"run.purpose.review": "Review",
|
|
291
|
+
"run.disposition": "Disposition",
|
|
292
|
+
"run.disposition.progress": "Progressing",
|
|
293
|
+
"run.disposition.waiting": "Waiting",
|
|
294
|
+
"run.disposition.blocked": "Blocked",
|
|
295
|
+
"run.disposition.completed": "Completed",
|
|
296
|
+
"run.waitReason": "Waiting on",
|
|
297
|
+
"run.yieldReceipt": "Yield receipt",
|
|
298
|
+
"review.scope.work-item": "Work item",
|
|
299
|
+
"review.scope.task": "Task"
|
|
218
300
|
},
|
|
219
301
|
"zh-CN": {
|
|
220
302
|
"a11y.skip": "跳到主面板",
|
|
@@ -333,6 +415,7 @@ const messages = {
|
|
|
333
415
|
"group.attention": "需输入",
|
|
334
416
|
"group.draft": "草稿",
|
|
335
417
|
"group.finished": "已完成",
|
|
418
|
+
"group.retired": "已退役",
|
|
336
419
|
"input.answered": "输入已回答。",
|
|
337
420
|
"input.blocking": "阻塞",
|
|
338
421
|
"input.freeText": "输入回答",
|
|
@@ -430,7 +513,88 @@ const messages = {
|
|
|
430
513
|
"work.superseded": "已替代",
|
|
431
514
|
"stats.running": "运行中",
|
|
432
515
|
"stats.inputs": "项输入",
|
|
433
|
-
"stats.stalledRuns": "停滞运行"
|
|
516
|
+
"stats.stalledRuns": "停滞运行",
|
|
517
|
+
"exec.status.needs-leader-action": "待负责人处理",
|
|
518
|
+
"exec.status.waiting-on-agents": "等待智能体",
|
|
519
|
+
"exec.status.waiting-user": "等待你回答",
|
|
520
|
+
"exec.status.recovering": "恢复中",
|
|
521
|
+
"exec.status.attention": "需要关注",
|
|
522
|
+
"exec.status.progressing-with-attention": "推进中(有注意项)",
|
|
523
|
+
"exec.status.blocked": "已阻塞",
|
|
524
|
+
"exec.status.working": "执行中",
|
|
525
|
+
"exec.status.completed": "已完成",
|
|
526
|
+
"exec.status.retired": "已退役",
|
|
527
|
+
"exec.status.archived": "已归档",
|
|
528
|
+
"exec.owner.leader": "负责人",
|
|
529
|
+
"exec.owner.worker": "执行者",
|
|
530
|
+
"exec.owner.reviewer": "评审者",
|
|
531
|
+
"exec.owner.tester": "测试者",
|
|
532
|
+
"exec.owner.operator": "Operator",
|
|
533
|
+
"exec.owner.user": "你",
|
|
534
|
+
"exec.owner.none": "—",
|
|
535
|
+
"exec.action.advance-task": "推进任务",
|
|
536
|
+
"exec.action.wait-for-agents": "等待智能体",
|
|
537
|
+
"exec.action.answer-input": "回答输入",
|
|
538
|
+
"exec.action.inspect-attention": "检查注意项",
|
|
539
|
+
"exec.action.recover-leader": "恢复负责人",
|
|
540
|
+
"exec.action.resolve-blocker": "解决阻塞",
|
|
541
|
+
"exec.action.complete-task": "完成任务",
|
|
542
|
+
"exec.action.none": "—",
|
|
543
|
+
"exec.attention.leader-recovery": "负责人恢复",
|
|
544
|
+
"exec.attention.leader-stalled": "负责人停滞",
|
|
545
|
+
"exec.attention.checkpoint-overdue": "检查点超时",
|
|
546
|
+
"exec.attention.identity-mismatch": "身份不匹配",
|
|
547
|
+
"exec.attention.delivery-uncertain": "送达不确定",
|
|
548
|
+
"exec.blocker.work": "工作",
|
|
549
|
+
"exec.blocker.review": "评审",
|
|
550
|
+
"exec.blocker.integration": "集成",
|
|
551
|
+
"exec.blocker.input": "输入",
|
|
552
|
+
"exec.blocker.identity": "身份",
|
|
553
|
+
"exec.monitoring.stopped": "监控已停止",
|
|
554
|
+
"exec.failClosed": "失败关闭",
|
|
555
|
+
"exec.executors": "活跃",
|
|
556
|
+
"exec.purpose.execution": "执行",
|
|
557
|
+
"exec.purpose.review": "评审",
|
|
558
|
+
"exec.strategy.fixed": "固定 · {count} 条泳道",
|
|
559
|
+
"exec.strategy.adaptive": "自适应 · 最多 {max}",
|
|
560
|
+
"exec.lanesFailed": "失败",
|
|
561
|
+
"lane.pending": "待处理",
|
|
562
|
+
"lane.running": "运行中",
|
|
563
|
+
"lane.yielded": "已交付",
|
|
564
|
+
"lane.completed": "已完成",
|
|
565
|
+
"lane.failed": "失败",
|
|
566
|
+
"resolution.accept": "已接受",
|
|
567
|
+
"resolution.reject": "已拒绝",
|
|
568
|
+
"resolution.retry": "已重试",
|
|
569
|
+
"resolution.blocked": "已阻塞",
|
|
570
|
+
"detail.candidates": "候选方案",
|
|
571
|
+
"detail.disposition": "退役处置",
|
|
572
|
+
"detail.replacementWorkItem": "替代项",
|
|
573
|
+
"detail.endedAt": "结束时间",
|
|
574
|
+
"detail.findings": "发现",
|
|
575
|
+
"detail.report": "报告",
|
|
576
|
+
"detail.workspaceDisposition": "工作区",
|
|
577
|
+
"detail.lineage": "执行谱系",
|
|
578
|
+
"detail.requester": "请求方",
|
|
579
|
+
"candidate.source.direct": "直接",
|
|
580
|
+
"candidate.source.run": "运行",
|
|
581
|
+
"finding.severity.low": "低",
|
|
582
|
+
"finding.severity.medium": "中",
|
|
583
|
+
"finding.severity.high": "高",
|
|
584
|
+
"finding.severity.critical": "严重",
|
|
585
|
+
"finding.status.open": "未解决",
|
|
586
|
+
"finding.status.resolved": "已解决",
|
|
587
|
+
"run.purpose.execution": "执行",
|
|
588
|
+
"run.purpose.review": "评审",
|
|
589
|
+
"run.disposition": "处置",
|
|
590
|
+
"run.disposition.progress": "推进中",
|
|
591
|
+
"run.disposition.waiting": "等待中",
|
|
592
|
+
"run.disposition.blocked": "已阻塞",
|
|
593
|
+
"run.disposition.completed": "已完成",
|
|
594
|
+
"run.waitReason": "等待",
|
|
595
|
+
"run.yieldReceipt": "交付回执",
|
|
596
|
+
"review.scope.work-item": "工作项",
|
|
597
|
+
"review.scope.task": "任务"
|
|
434
598
|
}
|
|
435
599
|
};
|
|
436
600
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
attentionRow,
|
|
9
9
|
conclusionMeta,
|
|
10
10
|
emptyRow,
|
|
11
|
+
executionBand,
|
|
11
12
|
historyEventRow,
|
|
12
13
|
inputCard,
|
|
13
14
|
messageCard,
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
workItemCard
|
|
28
29
|
} from "/assets/js/components.js";
|
|
29
30
|
|
|
30
|
-
const statuses = ["all", "active", "draft", "completed", "archived"];
|
|
31
|
+
const statuses = ["all", "active", "draft", "completed", "retired", "archived"];
|
|
31
32
|
|
|
32
33
|
export function renderFilters(container, state, t, onFilter) {
|
|
33
34
|
const counts = state.counts || {};
|
|
@@ -49,7 +50,7 @@ export function renderFilters(container, state, t, onFilter) {
|
|
|
49
50
|
dot.classList.add(status);
|
|
50
51
|
btn.append(dot);
|
|
51
52
|
}
|
|
52
|
-
btn.append(
|
|
53
|
+
btn.append(node("span", "filter-label", translatedStatus(t, "status", status)));
|
|
53
54
|
const badge = node("span", "filter-count");
|
|
54
55
|
btn.append(badge);
|
|
55
56
|
btn.addEventListener("click", function () { onFilter(status); });
|
|
@@ -61,6 +62,8 @@ export function renderFilters(container, state, t, onFilter) {
|
|
|
61
62
|
const btn = row.querySelector('.filter-chip[data-status="' + status + '"]');
|
|
62
63
|
if (!btn) return;
|
|
63
64
|
btn.classList.toggle("is-active", state.filter === status);
|
|
65
|
+
const label = btn.querySelector(".filter-label");
|
|
66
|
+
if (label) label.textContent = translatedStatus(t, "status", status);
|
|
64
67
|
const count = status === "all" ? counts.total : counts[status];
|
|
65
68
|
const badge = btn.querySelector(".filter-count");
|
|
66
69
|
if (badge) {
|
|
@@ -78,6 +81,7 @@ function taskGroupOf(task, attentionIds) {
|
|
|
78
81
|
if (attentionIds.has(task.id)) return "attention";
|
|
79
82
|
if (task.status === "active") return "active";
|
|
80
83
|
if (task.status === "draft") return "draft";
|
|
84
|
+
if (task.status === "retired") return "retired";
|
|
81
85
|
if (task.status === "archived") return "archived";
|
|
82
86
|
return "finished";
|
|
83
87
|
}
|
|
@@ -96,7 +100,7 @@ export function renderTasks(container, state, t, locale, onSelect) {
|
|
|
96
100
|
clear(container);
|
|
97
101
|
const query = state.query.trim().toLocaleLowerCase(locale);
|
|
98
102
|
const attentionIds = new Set((state.attention || []).map(function (item) { return item.taskId; }));
|
|
99
|
-
const groups = { attention: [], active: [], draft: [], finished: [], archived: [] };
|
|
103
|
+
const groups = { attention: [], active: [], draft: [], finished: [], retired: [], archived: [] };
|
|
100
104
|
(state.tasks || []).forEach(function (task) {
|
|
101
105
|
if (state.filter !== "all" && task.status !== state.filter) return;
|
|
102
106
|
if (!taskMatchesQuery(task, query, locale)) return;
|
|
@@ -108,6 +112,7 @@ export function renderTasks(container, state, t, locale, onSelect) {
|
|
|
108
112
|
["active", t("group.active")],
|
|
109
113
|
["draft", t("group.draft")],
|
|
110
114
|
["finished", t("group.finished")],
|
|
115
|
+
["retired", t("group.retired")],
|
|
111
116
|
["archived", t("group.archived")]
|
|
112
117
|
];
|
|
113
118
|
const firstGroup = order.find(function (entry) { return groups[entry[0]].length > 0; });
|
|
@@ -134,7 +139,7 @@ function overviewBlock(head, tasks, t, locale, onSelect) {
|
|
|
134
139
|
block.append(sectionHead(head, { count: tasks.length }));
|
|
135
140
|
const list = node("div", "overview-list");
|
|
136
141
|
tasks.forEach(function (task) {
|
|
137
|
-
list.append(overviewRow(task, t, locale, onSelect));
|
|
142
|
+
list.append(overviewRow(task, null, null, t, locale, onSelect));
|
|
138
143
|
});
|
|
139
144
|
block.append(list);
|
|
140
145
|
return block;
|
|
@@ -174,23 +179,30 @@ export function renderOverview(detail, state, t, locale, onSelect) {
|
|
|
174
179
|
}
|
|
175
180
|
wrap.append(inbox);
|
|
176
181
|
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
// Tasks whose Task-first projection says they need attention: blocked,
|
|
183
|
+
// recovering, or in an attention state. This replaces the raw stalled-run
|
|
184
|
+
// count with the derived execution status.
|
|
185
|
+
const attentionTasks = (state.tasks || []).filter(function (task) {
|
|
186
|
+
const status = task.executionStatus;
|
|
187
|
+
return status === "blocked"
|
|
188
|
+
|| status === "attention"
|
|
189
|
+
|| status === "recovering"
|
|
190
|
+
|| status === "progressing-with-attention";
|
|
179
191
|
});
|
|
180
|
-
if (
|
|
181
|
-
const
|
|
182
|
-
|
|
192
|
+
if (attentionTasks.length) {
|
|
193
|
+
const attentionBlock = node("section", "overview-block");
|
|
194
|
+
attentionBlock.append(node("h3", "", t("overview.attention") + " · " + attentionTasks.length));
|
|
183
195
|
const list = node("div", "overview-list");
|
|
184
|
-
|
|
196
|
+
attentionTasks.forEach(function (task) {
|
|
185
197
|
list.append(overviewRow(
|
|
186
198
|
task,
|
|
187
|
-
|
|
199
|
+
t("exec.status." + task.executionStatus),
|
|
188
200
|
"has-inputs",
|
|
189
201
|
onSelect
|
|
190
202
|
));
|
|
191
203
|
});
|
|
192
|
-
|
|
193
|
-
wrap.append(
|
|
204
|
+
attentionBlock.append(list);
|
|
205
|
+
wrap.append(attentionBlock);
|
|
194
206
|
}
|
|
195
207
|
|
|
196
208
|
// Active work and the freshest updates sit side by side on wide screens, so
|
|
@@ -274,6 +286,11 @@ export function renderTaskDetail(detail, data, t, locale, actions) {
|
|
|
274
286
|
headBlock.append(meta);
|
|
275
287
|
summaryBody.append(headBlock);
|
|
276
288
|
|
|
289
|
+
// Task-first execution status: the derived status, owner, next action, and
|
|
290
|
+
// the attention/blocker facts behind it.
|
|
291
|
+
const band = executionBand(data.execution, t, locale);
|
|
292
|
+
if (band) summaryBody.append(band);
|
|
293
|
+
|
|
277
294
|
if (task.completionSummary) {
|
|
278
295
|
const conclusion = node("div", "conclusion");
|
|
279
296
|
conclusion.append(node("h3", "", t("detail.conclusion")));
|