@atolis-hq/wake 0.2.64 → 0.2.66

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.
@@ -300,6 +300,7 @@ async function renderBoard(context) {
300
300
  ]);
301
301
  const columns = el('div', { class: 'columns' }, CONDITIONS.map((cond) => {
302
302
  const items = board.filter((c) => c.condition === cond);
303
+ if (cond === 'finished') items.sort((a, b) => a.timeInStageMs - b.timeInStageMs);
303
304
  const cards = items.map((item) => el('div', {
304
305
  class: 'card',
305
306
  onclick: () => openItemModal(item.repo, item.number),
@@ -307,7 +308,7 @@ async function renderBoard(context) {
307
308
  el('div', { class: 'title', text: item.repo + '#' + item.number + ' ' + item.title }),
308
309
  el('div', { class: 'meta' }, [
309
310
  el('span', { class: 'chip', text: item.stage }),
310
- document.createTextNode(fmtMs(item.timeInStageMs) + ' in stage'),
311
+ ...(cond !== 'finished' ? [document.createTextNode(fmtMs(item.timeInStageMs) + ' in stage')] : []),
311
312
  ]),
312
313
  ...(item.labels && item.labels.length > 0
313
314
  ? [el('div', { class: 'meta' }, item.labels.map((label) => el('span', { class: 'chip chip-label', text: label })))]
@@ -85,10 +85,6 @@ export function createPolicyEngine() {
85
85
  if (issue.issue.labels.some((label) => alwaysManualIgnoredLabels.includes(label))) {
86
86
  return false;
87
87
  }
88
- const context = issue.context;
89
- if (config.workflowSelectors.length > 0) {
90
- return typeof context.workflow === 'string';
91
- }
92
88
  // Defense-in-depth: the issues source filters PR-shaped items at poll
93
89
  // time, so no NEW projection can ever have isPullRequest: true. But a
94
90
  // pre-existing state/<workId>.json written by a pre-this-branch
@@ -97,13 +93,23 @@ export function createPolicyEngine() {
97
93
  if (issue.issue.isPullRequest) {
98
94
  return false;
99
95
  }
100
- return labelsAndAssigneesQualify({
96
+ // Source policy is always checked first — workflow selectors are optional secondary filter.
97
+ if (!labelsAndAssigneesQualify({
101
98
  labels: issue.issue.labels,
102
99
  assignees: issue.issue.assignees,
103
100
  requiredLabels: config.sources.github.policy.requiredLabels,
104
101
  ignoredLabels: config.sources.github.policy.ignoredLabels,
105
102
  requiredAssignees: config.sources.github.policy.requiredAssignees,
106
- });
103
+ })) {
104
+ return false;
105
+ }
106
+ // If workflow selectors are configured as the routing mechanism, the issue must have
107
+ // a workflow assigned (set by a matching selector when the issue was first minted).
108
+ if (config.workflowSelectors.length > 0) {
109
+ const context = issue.context;
110
+ return typeof context.workflow === 'string';
111
+ }
112
+ return true;
107
113
  },
108
114
  needsWakeAction(issue, workflow = builtInDefaultWorkflowDefinition, config) {
109
115
  const context = issue.context;
@@ -289,9 +295,7 @@ export function createPolicyEngine() {
289
295
  const workflow = unresolved.payload.workflow;
290
296
  return typeof workflow === 'string' && config.workflows[workflow] !== undefined;
291
297
  }
292
- if (config.workflowSelectors.length > 0) {
293
- return selectWorkflowForEvent(unresolved, config) !== null;
294
- }
298
+ // Source policy enforcement is always checked first — workflow selectors are optional secondary routing.
295
299
  if (kind === 'issue') {
296
300
  // Real github source stamps payload.ticket (sourceEventType
297
301
  // 'ticket.upsert'); the fake ticketing harness stamps payload.issue
@@ -304,13 +308,20 @@ export function createPolicyEngine() {
304
308
  if (ticket === undefined) {
305
309
  return false;
306
310
  }
307
- return labelsAndAssigneesQualify({
311
+ if (!labelsAndAssigneesQualify({
308
312
  labels: Array.isArray(ticket.labels) ? ticket.labels : [],
309
313
  assignees: Array.isArray(ticket.assignees) ? ticket.assignees : [],
310
314
  requiredLabels: config.sources.github.policy.requiredLabels,
311
315
  ignoredLabels: config.sources.github.policy.ignoredLabels,
312
316
  requiredAssignees: config.sources.github.policy.requiredAssignees,
313
- });
317
+ })) {
318
+ return false;
319
+ }
320
+ // Issue passed source policy; if workflow selectors are configured, also check routing.
321
+ if (config.workflowSelectors.length > 0) {
322
+ return selectWorkflowForEvent(unresolved, config) !== null;
323
+ }
324
+ return true;
314
325
  }
315
326
  if (kind === 'pr') {
316
327
  if (!config.sources.github.pullRequests.enabled) {
@@ -318,10 +329,17 @@ export function createPolicyEngine() {
318
329
  }
319
330
  const pr = unresolved.payload.pr;
320
331
  const requiredAuthors = config.sources.github.pullRequests.policy.requiredAuthors;
321
- if (requiredAuthors.length === 0 || typeof pr?.author !== 'string') {
322
- return false;
332
+ // If requiredAuthors is empty, source policy allows any author.
333
+ if (requiredAuthors.length > 0) {
334
+ if (typeof pr?.author !== 'string' || !requiredAuthors.includes(pr.author)) {
335
+ return false;
336
+ }
323
337
  }
324
- return requiredAuthors.includes(pr.author);
338
+ // PR passed source policy; if workflow selectors are configured, also check routing.
339
+ if (config.workflowSelectors.length > 0) {
340
+ return selectWorkflowForEvent(unresolved, config) !== null;
341
+ }
342
+ return true;
325
343
  }
326
344
  return false;
327
345
  },
@@ -124,4 +124,4 @@ export function resolveWakeVersion(options = {}) {
124
124
  }
125
125
  return '0.1.0-dev';
126
126
  }
127
- export const wakeVersion = "ga2ac867";
127
+ export const wakeVersion = "gda2b78e";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.64",
3
+ "version": "0.2.66",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {