@atolis-hq/wake 0.2.75 → 0.2.77
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.
|
@@ -53,6 +53,7 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
53
53
|
.pill-needs-human { background: #4a3510; color: #ffcf7f; }
|
|
54
54
|
.pill-error { background: #3d1f1f; color: #ff8f7f; }
|
|
55
55
|
.pill-finished { background: #252830; color: #9aa2ad; }
|
|
56
|
+
.pill-frozen { background: #5c2a11; color: #ffd7a3; border: 1px solid #ff9f43; }
|
|
56
57
|
nav { display: flex; gap: 0.25rem; padding: 0.4rem 1rem 0 0.3rem; background: var(--brand-darker); border-bottom: 1px solid #2c313a; }
|
|
57
58
|
nav button { background: none; border: none; border-bottom: 2px solid transparent; color: rgba(255, 255, 255, 0.65); padding: 0.4rem 0.7rem 0.45rem; margin-bottom: -1px; cursor: pointer; font-size: 0.85rem; transition: color 0.12s ease; }
|
|
58
59
|
nav button:hover { color: #fff; }
|
|
@@ -368,6 +369,7 @@ function renderCardSummaryNodes(item) {
|
|
|
368
369
|
return [
|
|
369
370
|
el('div', { class: 'meta', style: 'display:flex;align-items:center;gap:0.3rem;flex-wrap:wrap;margin-top:0.2rem;' }, [
|
|
370
371
|
el('span', { class: pillClass, text: item.condition }),
|
|
372
|
+
...(item.isFrozen ? [el('span', { class: 'pill pill-frozen', text: 'Frozen' })] : []),
|
|
371
373
|
document.createTextNode('| ' + item.workflow + ' | ' + item.stage + (isFinished ? '' : ' | ' + fmtMs(item.timeInStageMs) + ' in stage')),
|
|
372
374
|
]),
|
|
373
375
|
el('div', { class: 'card-stats', text: statsText }),
|
|
@@ -111,6 +111,7 @@ export async function buildBoard(input) {
|
|
|
111
111
|
.map((item) => {
|
|
112
112
|
const lastRun = item.wake.lastRunId === undefined ? null : (runsById.get(item.wake.lastRunId) ?? null);
|
|
113
113
|
const { condition, reason } = deriveCondition(item, lastRun, input.config);
|
|
114
|
+
const isFrozen = isWorkItemFrozen(item);
|
|
114
115
|
const activeChildRuns = activeChildRunsForItem(item, runs, input.now);
|
|
115
116
|
const activeMainRun = lastRun?.status === 'running'
|
|
116
117
|
? {
|
|
@@ -137,6 +138,7 @@ export async function buildBoard(input) {
|
|
|
137
138
|
stage: item.wake.stage,
|
|
138
139
|
workflow: workflowNameForProjection(item, input.config),
|
|
139
140
|
labels: item.issue.labels,
|
|
141
|
+
isFrozen,
|
|
140
142
|
condition,
|
|
141
143
|
conditionReason: reason,
|
|
142
144
|
timeInStageMs: timeInStageMs(item, input.now),
|
|
@@ -1470,14 +1470,22 @@ export function createTickRunner(deps) {
|
|
|
1470
1470
|
? { lastDispatchedEventId: watcherTriggerForRun.eventId }
|
|
1471
1471
|
: { lastDispatchedSlot: watcherTriggerForRun.slot });
|
|
1472
1472
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1473
|
+
// Watcher runs execute a *different* workflow's stage (e.g. plan-review)
|
|
1474
|
+
// against the same parent projection, not a stage transition of the
|
|
1475
|
+
// parent's own workflow — writing labels here would stamp the child
|
|
1476
|
+
// workflow's stage/workflow onto the parent's GitHub issue. The parent's
|
|
1477
|
+
// labels must only ever reflect the parent's own action (see the mirrored
|
|
1478
|
+
// guard on the completion path below).
|
|
1479
|
+
if (!watcherRun) {
|
|
1480
|
+
await deliverOutboundEvent(createLabelsEvent({
|
|
1481
|
+
projection: candidate,
|
|
1482
|
+
runId,
|
|
1483
|
+
statusLabel: 'wake:status.working',
|
|
1484
|
+
stageLabel: stageLabelForStage(claimedStage),
|
|
1485
|
+
workflowLabel: workflowLabelForWorkflowName(workflowName),
|
|
1486
|
+
occurredAt: eventStampNow(),
|
|
1487
|
+
}));
|
|
1488
|
+
}
|
|
1481
1489
|
let leaseRenewalTimer;
|
|
1482
1490
|
function startLeaseRenewal() {
|
|
1483
1491
|
leaseRenewalTimer = setInterval(() => {
|
|
@@ -2101,18 +2109,28 @@ export function createTickRunner(deps) {
|
|
|
2101
2109
|
// network error) never reached the agent, so it isn't an answer to the
|
|
2102
2110
|
// triggering comment. Leaving it unset lets the next tick retry the same
|
|
2103
2111
|
// request instead of silently eating it (S9).
|
|
2112
|
+
// Mirrors the happy-path completion payload below: without this flag,
|
|
2113
|
+
// projection-updater.ts folds sentinel/workflowOutcome onto the
|
|
2114
|
+
// *parent's* context, even though this failure belongs to a watcher's
|
|
2115
|
+
// own child-workflow run, not the parent's own action.
|
|
2116
|
+
...(watcherRun ? { watcherRun: true, watcherTrigger: watcherTriggerForRun } : {}),
|
|
2104
2117
|
},
|
|
2105
2118
|
});
|
|
2106
2119
|
await deps.stateStore.appendEventEnvelope(runCompletedEvent);
|
|
2107
2120
|
await projectionUpdater.rebuildFromEvents([runCompletedEvent]);
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2121
|
+
// See the matching guard on the claim path above: a watcher run's
|
|
2122
|
+
// failure is not the parent's own action failing, so it must not
|
|
2123
|
+
// stamp the child workflow's stage/workflow onto the parent's labels.
|
|
2124
|
+
if (!watcherRun) {
|
|
2125
|
+
await deliverOutboundEvent(createLabelsEvent({
|
|
2126
|
+
projection: candidate,
|
|
2127
|
+
runId,
|
|
2128
|
+
statusLabel: 'wake:status.failed',
|
|
2129
|
+
stageLabel: stageLabelForStage(claimedStage),
|
|
2130
|
+
workflowLabel: workflowLabelForWorkflowName(workflowName),
|
|
2131
|
+
occurredAt: finishedAt,
|
|
2132
|
+
}));
|
|
2133
|
+
}
|
|
2116
2134
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
2117
2135
|
const infraFailureResult = {
|
|
2118
2136
|
result: errorMessage,
|
package/dist/src/version.js
CHANGED