@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
- await deliverOutboundEvent(createLabelsEvent({
1474
- projection: candidate,
1475
- runId,
1476
- statusLabel: 'wake:status.working',
1477
- stageLabel: stageLabelForStage(claimedStage),
1478
- workflowLabel: workflowLabelForWorkflowName(workflowName),
1479
- occurredAt: eventStampNow(),
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
- await deliverOutboundEvent(createLabelsEvent({
2109
- projection: candidate,
2110
- runId,
2111
- statusLabel: 'wake:status.failed',
2112
- stageLabel: stageLabelForStage(claimedStage),
2113
- workflowLabel: workflowLabelForWorkflowName(workflowName),
2114
- occurredAt: finishedAt,
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,
@@ -124,4 +124,4 @@ export function resolveWakeVersion(options = {}) {
124
124
  }
125
125
  return '0.1.0-dev';
126
126
  }
127
- export const wakeVersion = "g1518042";
127
+ export const wakeVersion = "gbf60f05";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.75",
3
+ "version": "0.2.77",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {