@evomap/evolver 1.89.20 → 1.91.0

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.
Files changed (69) hide show
  1. package/README.ja-JP.md +1 -1
  2. package/README.ko-KR.md +1 -1
  3. package/README.md +1 -1
  4. package/README.zh-CN.md +1 -1
  5. package/index.js +85 -1
  6. package/package.json +1 -1
  7. package/src/adapters/claudeCode.js +3 -3
  8. package/src/adapters/codex.js +2 -2
  9. package/src/adapters/kiro.js +2 -2
  10. package/src/adapters/opencode.js +2 -2
  11. package/src/evolve/guards.js +1 -1
  12. package/src/evolve/pipeline/collect.js +1 -1
  13. package/src/evolve/pipeline/dispatch.js +1 -1
  14. package/src/evolve/pipeline/enrich.js +1 -1
  15. package/src/evolve/pipeline/hub.js +1 -1
  16. package/src/evolve/pipeline/select.js +1 -1
  17. package/src/evolve/pipeline/signals.js +1 -1
  18. package/src/evolve/utils.js +1 -1
  19. package/src/evolve.js +1 -1
  20. package/src/gep/a2aProtocol.js +1 -1
  21. package/src/gep/antiAbuseTelemetry.js +1 -1
  22. package/src/gep/autoDistillConv.js +1 -1
  23. package/src/gep/autoDistillLlm.js +1 -1
  24. package/src/gep/candidateEval.js +1 -1
  25. package/src/gep/candidates.js +1 -1
  26. package/src/gep/contentHash.js +1 -1
  27. package/src/gep/conversationDistiller.js +1 -1
  28. package/src/gep/conversationSniffer.js +1 -1
  29. package/src/gep/crypto.js +1 -1
  30. package/src/gep/curriculum.js +1 -1
  31. package/src/gep/deviceId.js +1 -1
  32. package/src/gep/envFingerprint.js +1 -1
  33. package/src/gep/epigenetics.js +1 -1
  34. package/src/gep/execBridge.js +1 -1
  35. package/src/gep/explore.js +1 -1
  36. package/src/gep/hash.js +1 -1
  37. package/src/gep/hubFetch.js +1 -1
  38. package/src/gep/hubReview.js +1 -1
  39. package/src/gep/hubSearch.js +1 -1
  40. package/src/gep/hubVerify.js +1 -1
  41. package/src/gep/learningSignals.js +1 -1
  42. package/src/gep/memoryGraph.js +1 -1
  43. package/src/gep/memoryGraphAdapter.js +1 -1
  44. package/src/gep/mutation.js +1 -1
  45. package/src/gep/narrativeMemory.js +1 -1
  46. package/src/gep/openPRRegistry.js +1 -1
  47. package/src/gep/personality.js +1 -1
  48. package/src/gep/policyCheck.js +1 -1
  49. package/src/gep/prompt.js +1 -1
  50. package/src/gep/recallInject.js +1 -1
  51. package/src/gep/recallVerifier.js +1 -1
  52. package/src/gep/reflection.js +1 -1
  53. package/src/gep/savingsCore.js +1 -1
  54. package/src/gep/selector.js +1 -1
  55. package/src/gep/selfPR.js +83 -44
  56. package/src/gep/skillDistiller.js +1 -1
  57. package/src/gep/solidify.js +1 -1
  58. package/src/gep/strategy.js +1 -1
  59. package/src/gep/tokenSavings.js +1 -1
  60. package/src/gep/trajectoryExport.js +1 -1
  61. package/src/gep/workspaceKeychain.js +1 -1
  62. package/src/proxy/extensions/traceControl.js +1 -1
  63. package/src/proxy/inject.js +1 -1
  64. package/src/proxy/mailbox/store.js +14 -2
  65. package/src/proxy/sync/outbound.js +44 -3
  66. package/src/proxy/trace/extractor.js +1 -1
  67. package/src/proxy/trace/usage.js +1 -1
  68. package/src/solo/breaker.js +25 -0
  69. package/src/solo/gitGuard.js +65 -0
@@ -120,6 +120,30 @@ function buildSizedOutboundBatch(senderId, messages, maxBodyBytes, hardMaxBodyBy
120
120
  return { selected, rejected, body, bodyBytes, maxBodyBytes };
121
121
  }
122
122
 
123
+ function numberField(row, keys) {
124
+ for (const key of keys) {
125
+ if (!row || row[key] === undefined || row[key] === null || row[key] === '') continue;
126
+ const n = Number(row[key]);
127
+ if (Number.isFinite(n)) return n;
128
+ }
129
+ return null;
130
+ }
131
+
132
+ function resultRetryAfterMs(row) {
133
+ const ms = numberField(row, ['retryAfterMs', 'retry_after_ms']);
134
+ if (ms !== null) return Math.max(1_000, ms);
135
+ const seconds = numberField(row, ['retryAfter', 'retry_after']);
136
+ return seconds !== null ? Math.max(1_000, seconds * 1000) : null;
137
+ }
138
+
139
+ function resultIsRetryable(row) {
140
+ return row && (row.retryable === true || row.retryable === 'true' || row.terminal === false || row.terminal === 'false');
141
+ }
142
+
143
+ function resultIsTerminal(row) {
144
+ return row && (row.terminal === true || row.terminal === 'true');
145
+ }
146
+
123
147
  class OutboundSync {
124
148
  constructor({ store, hubUrl, getHeaders, logger }) {
125
149
  this.store = store;
@@ -261,17 +285,33 @@ class OutboundSync {
261
285
 
262
286
  const updates = [];
263
287
  const inboundMessages = [];
288
+ let deferred = 0;
264
289
 
265
290
  for (const r of results) {
266
291
  if (r.status === 'accepted' || r.status === 'ok') {
267
292
  updates.push({ id: r.id, status: 'synced' });
268
293
  } else if (r.status === 'failed' || r.status === 'rejected') {
269
294
  const msg = pending.find(m => m.id === r.id);
270
- const error = sanitizeHubErrorMessage(r.error || 'rejected by hub');
271
- if (msg && msg.retry_count < MAX_RETRIES) {
295
+ const error = sanitizeHubErrorMessage(r.error || r.reason || 'rejected by hub');
296
+ const retryAfterMs = resultRetryAfterMs(r);
297
+ // A `terminal: true` hint from the Hub means "final, do not retry"
298
+ // and must win even when the same result also carries retryAfterMs
299
+ // or retryable (a contradictory but possible payload). Guard the
300
+ // defer branch with !resultIsTerminal so a terminal message is
301
+ // finalized as failed instead of being parked for retry and resent.
302
+ if (msg && !resultIsTerminal(r) && (retryAfterMs !== null || resultIsRetryable(r))) {
303
+ this.store.deferRetry(r.id, error, retryAfterMs || 60_000);
304
+ deferred++;
305
+ } else if (msg && !resultIsTerminal(r) && msg.retry_count < MAX_RETRIES) {
272
306
  this.store.incrementRetry(r.id, error);
273
307
  } else {
274
- updates.push({ id: r.id, status: 'failed', error: sanitizeHubErrorMessage(r.error || 'max retries') });
308
+ // Reuse the already-sanitized `error` (r.error / r.reason, else
309
+ // 'rejected by hub'). Only label 'max retries' for the genuine
310
+ // retry-exhaustion path (non-terminal, no explicit Hub error) so a
311
+ // terminal rejection without an error/reason is not mislabeled as
312
+ // retry exhaustion (Bugbot PR #301 Low).
313
+ const exhausted = !resultIsTerminal(r) && !(r.error || r.reason);
314
+ updates.push({ id: r.id, status: 'failed', error: exhausted ? sanitizeHubErrorMessage('max retries') : error });
275
315
  }
276
316
  }
277
317
 
@@ -290,6 +330,7 @@ class OutboundSync {
290
330
 
291
331
  this.store.setState('last_sync_at', new Date().toISOString());
292
332
  const result = { sent: pending.length, synced: updates.length, responses: inboundMessages.length };
333
+ if (deferred > 0) result.deferred = deferred;
293
334
  if (dropped > 0) result.dropped = dropped;
294
335
  return result;
295
336
  } catch (err) {