@evomap/evolver 1.89.19 → 1.90.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.
- package/index.js +85 -1
- package/package.json +1 -1
- package/scripts/skill2recipes.js +118 -0
- package/src/adapters/claudeCode.js +3 -3
- package/src/adapters/codex.js +2 -2
- package/src/adapters/kiro.js +2 -2
- package/src/adapters/opencode.js +2 -2
- package/src/evolve/guards.js +1 -1
- package/src/evolve/pipeline/collect.js +1 -1
- package/src/evolve/pipeline/dispatch.js +1 -1
- package/src/evolve/pipeline/enrich.js +1 -1
- package/src/evolve/pipeline/hub.js +1 -1
- package/src/evolve/pipeline/select.js +1 -1
- package/src/evolve/pipeline/signals.js +1 -1
- package/src/evolve/utils.js +1 -1
- package/src/evolve.js +1 -1
- package/src/gep/a2aProtocol.js +1 -1
- package/src/gep/antiAbuseTelemetry.js +1 -1
- package/src/gep/autoDistillConv.js +1 -1
- package/src/gep/autoDistillLlm.js +1 -1
- package/src/gep/candidateEval.js +1 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/contentHash.js +1 -1
- package/src/gep/conversationDistiller.js +1 -1
- package/src/gep/conversationSniffer.js +1 -1
- package/src/gep/crypto.js +1 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +1 -1
- package/src/gep/envFingerprint.js +1 -1
- package/src/gep/epigenetics.js +1 -1
- package/src/gep/execBridge.js +1 -1
- package/src/gep/explore.js +1 -1
- package/src/gep/hash.js +1 -1
- package/src/gep/hubFetch.js +1 -1
- package/src/gep/hubReview.js +1 -1
- package/src/gep/hubSearch.js +1 -1
- package/src/gep/hubVerify.js +1 -1
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1 -1
- package/src/gep/memoryGraphAdapter.js +1 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/openPRRegistry.js +1 -1
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/prompt.js +1 -1
- package/src/gep/recallInject.js +1 -1
- package/src/gep/recallVerifier.js +1 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/savingsCore.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/skill2recipes.js +511 -0
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
- package/src/gep/tokenSavings.js +1 -1
- package/src/gep/trajectoryExport.js +1 -1
- package/src/gep/workspaceKeychain.js +1 -1
- package/src/proxy/extensions/traceControl.js +1 -1
- package/src/proxy/inject.js +1 -1
- package/src/proxy/mailbox/store.js +14 -2
- package/src/proxy/sync/outbound.js +44 -3
- package/src/proxy/trace/extractor.js +1 -1
- package/src/proxy/trace/usage.js +1 -1
- package/src/solo/breaker.js +25 -0
- package/src/solo/gitGuard.js +65 -0
- package/skills/_meta/SKILL.md +0 -41
- package/skills/index.json +0 -14
|
@@ -345,6 +345,7 @@ class MailboxStore {
|
|
|
345
345
|
synced_at: null,
|
|
346
346
|
expires_at: expiresAt || null,
|
|
347
347
|
retry_count: 0,
|
|
348
|
+
next_retry_at: null,
|
|
348
349
|
error: null,
|
|
349
350
|
};
|
|
350
351
|
this._appendMessage(msg);
|
|
@@ -372,6 +373,7 @@ class MailboxStore {
|
|
|
372
373
|
synced_at: null,
|
|
373
374
|
expires_at: expiresAt || null,
|
|
374
375
|
retry_count: 0,
|
|
376
|
+
next_retry_at: null,
|
|
375
377
|
error: null,
|
|
376
378
|
};
|
|
377
379
|
this._appendMessage(msg);
|
|
@@ -418,6 +420,7 @@ class MailboxStore {
|
|
|
418
420
|
const msg = this._messages.get(id);
|
|
419
421
|
if (!msg || msg.status !== 'pending') continue;
|
|
420
422
|
if (msg.channel !== ch) continue;
|
|
423
|
+
if (Number.isFinite(Number(msg.next_retry_at)) && Number(msg.next_retry_at) > Date.now()) continue;
|
|
421
424
|
candidates.push(msg);
|
|
422
425
|
}
|
|
423
426
|
candidates.sort((a, b) => {
|
|
@@ -450,7 +453,7 @@ class MailboxStore {
|
|
|
450
453
|
|
|
451
454
|
updateStatus(id, status, { error, syncedAt } = {}) {
|
|
452
455
|
const TERMINAL = new Set(['synced', 'delivered', 'failed', 'rejected']);
|
|
453
|
-
const fields = { status };
|
|
456
|
+
const fields = { status, next_retry_at: null };
|
|
454
457
|
if (syncedAt) fields.synced_at = syncedAt;
|
|
455
458
|
else if (status === 'synced') fields.synced_at = Date.now();
|
|
456
459
|
if (error !== undefined) fields.error = error;
|
|
@@ -470,7 +473,16 @@ class MailboxStore {
|
|
|
470
473
|
incrementRetry(id, error) {
|
|
471
474
|
const msg = this._messages.get(id);
|
|
472
475
|
const newCount = msg ? (msg.retry_count || 0) + 1 : 1;
|
|
473
|
-
this._appendUpdate(id, { retry_count: newCount, error: error || null });
|
|
476
|
+
this._appendUpdate(id, { retry_count: newCount, next_retry_at: null, error: error || null });
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
deferRetry(id, error, retryAfterMs) {
|
|
480
|
+
const delay = Math.max(1_000, Number.isFinite(Number(retryAfterMs)) ? Number(retryAfterMs) : 60_000);
|
|
481
|
+
this._appendUpdate(id, {
|
|
482
|
+
status: 'pending',
|
|
483
|
+
next_retry_at: Date.now() + delay,
|
|
484
|
+
error: error || null,
|
|
485
|
+
});
|
|
474
486
|
}
|
|
475
487
|
|
|
476
488
|
list({ type, direction, status, limit, offset } = {}) {
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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) {
|