@evomap/evolver 1.89.14 → 1.89.15

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 (64) hide show
  1. package/index.js +219 -29
  2. package/package.json +1 -1
  3. package/src/evolve/guards.js +1 -1
  4. package/src/evolve/pipeline/collect.js +1 -1
  5. package/src/evolve/pipeline/dispatch.js +1 -1
  6. package/src/evolve/pipeline/enrich.js +1 -1
  7. package/src/evolve/pipeline/hub.js +1 -1
  8. package/src/evolve/pipeline/select.js +1 -1
  9. package/src/evolve/pipeline/signals.js +1 -1
  10. package/src/evolve/utils.js +1 -1
  11. package/src/evolve.js +1 -1
  12. package/src/forceUpdate.js +499 -119
  13. package/src/gep/a2aProtocol.js +1 -1
  14. package/src/gep/antiAbuseTelemetry.js +1 -1
  15. package/src/gep/autoDistillConv.js +1 -1
  16. package/src/gep/autoDistillLlm.js +1 -1
  17. package/src/gep/candidateEval.js +1 -1
  18. package/src/gep/candidates.js +1 -1
  19. package/src/gep/cliContracts.js +1154 -0
  20. package/src/gep/contentHash.js +1 -1
  21. package/src/gep/conversationDistiller.js +1 -1
  22. package/src/gep/conversationSniffer.js +1 -1
  23. package/src/gep/crypto.js +1 -1
  24. package/src/gep/curriculum.js +1 -1
  25. package/src/gep/deviceId.js +1 -1
  26. package/src/gep/envFingerprint.js +1 -1
  27. package/src/gep/epigenetics.js +1 -1
  28. package/src/gep/execBridge.js +1 -1
  29. package/src/gep/explore.js +1 -1
  30. package/src/gep/hash.js +1 -1
  31. package/src/gep/hubFetch.js +1 -1
  32. package/src/gep/hubReview.js +1 -1
  33. package/src/gep/hubSearch.js +1 -1
  34. package/src/gep/hubVerify.js +1 -1
  35. package/src/gep/issueReporter.js +86 -0
  36. package/src/gep/learningSignals.js +1 -1
  37. package/src/gep/memoryGraph.js +1 -1
  38. package/src/gep/memoryGraphAdapter.js +1 -1
  39. package/src/gep/mutation.js +1 -1
  40. package/src/gep/narrativeMemory.js +1 -1
  41. package/src/gep/openPRRegistry.js +1 -1
  42. package/src/gep/personality.js +1 -1
  43. package/src/gep/policyCheck.js +1 -1
  44. package/src/gep/prompt.js +1 -1
  45. package/src/gep/recallInject.js +1 -1
  46. package/src/gep/recallVerifier.js +1 -1
  47. package/src/gep/reflection.js +1 -1
  48. package/src/gep/sanitize.js +20 -4
  49. package/src/gep/savingsCore.js +1 -1
  50. package/src/gep/selector.js +1 -1
  51. package/src/gep/signals.js +33 -9
  52. package/src/gep/skillDistiller.js +1 -1
  53. package/src/gep/solidify.js +1 -1
  54. package/src/gep/strategy.js +1 -1
  55. package/src/gep/tokenSavings.js +1 -1
  56. package/src/gep/workspaceKeychain.js +1 -1
  57. package/src/proxy/extensions/traceControl.js +1 -1
  58. package/src/proxy/index.js +4 -4
  59. package/src/proxy/inject.js +1 -1
  60. package/src/proxy/lifecycle/manager.js +233 -33
  61. package/src/proxy/sync/inbound.js +5 -4
  62. package/src/proxy/sync/outbound.js +3 -2
  63. package/src/proxy/trace/extractor.js +1 -1
  64. package/src/proxy/trace/usage.js +1 -1
@@ -32,6 +32,22 @@ function hasOpportunitySignal(signals) {
32
32
  return false;
33
33
  }
34
34
 
35
+ // A cycle that produced no file/line changes is a no-op ("empty cycle"), not a
36
+ // genuine failure -- even when its outcome is recorded as `failed`. The most
37
+ // common way a `failed` event ends up with zero blast radius is a claimed-
38
+ // success cycle rejected by the anti-forgery guard (`zero_blast_radius_with_
39
+ // success`): the sub-agent declared success but touched nothing -- e.g. an
40
+ // `innovate` gene that only produces metadata/strategy and never edits code.
41
+ // Empty cycles are tracked separately (consecutiveEmptyCycles) and drive
42
+ // graceful steady-state degradation, NOT the failure-loop ban. Single source of
43
+ // truth so the empty/failure split stays consistent across every counter below.
44
+ function _isEmptyCycle(evt) {
45
+ if (!evt) return false;
46
+ if (evt.meta && evt.meta.empty_cycle) return true;
47
+ var br = evt.blast_radius;
48
+ return !!(br && br.files === 0 && br.lines === 0);
49
+ }
50
+
35
51
  // Build a de-duplication set from recent evolution events.
36
52
  // Returns an object: { suppressedSignals: Set<string>, recentIntents: string[], consecutiveRepairCount: number }
37
53
  function analyzeRecentHistory(recentEvents) {
@@ -85,13 +101,11 @@ function analyzeRecentHistory(recentEvents) {
85
101
 
86
102
  var recentIntents = recent.map(function(e) { return e.intent || 'unknown'; });
87
103
 
88
- // Count empty cycles (blast_radius.files === 0) in last 8 events.
104
+ // Count empty cycles (no file/line changes) in last 8 events.
89
105
  // High ratio indicates the evolver is spinning without producing real changes.
90
106
  var emptyCycleCount = 0;
91
107
  for (var ec = 0; ec < tail.length; ec++) {
92
- var br = tail[ec].blast_radius;
93
- var em = tail[ec].meta && tail[ec].meta.empty_cycle;
94
- if (em || (br && br.files === 0 && br.lines === 0)) {
108
+ if (_isEmptyCycle(tail[ec])) {
95
109
  emptyCycleCount++;
96
110
  }
97
111
  }
@@ -101,19 +115,25 @@ function analyzeRecentHistory(recentEvents) {
101
115
  // zero-change cycles. Used to trigger graceful degradation to steady-state mode.
102
116
  var consecutiveEmptyCycles = 0;
103
117
  for (var se = recent.length - 1; se >= 0; se--) {
104
- var seBr = recent[se].blast_radius;
105
- var seEm = recent[se].meta && recent[se].meta.empty_cycle;
106
- if (seEm || (seBr && seBr.files === 0 && seBr.lines === 0)) {
118
+ if (_isEmptyCycle(recent[se])) {
107
119
  consecutiveEmptyCycles++;
108
120
  } else {
109
121
  break;
110
122
  }
111
123
  }
112
124
 
113
- // Count consecutive failures at the tail of recent events.
125
+ // Count consecutive *productive* failures at the tail of recent events.
114
126
  // This tells the evolver "you have been failing N times in a row -- slow down."
127
+ //
128
+ // A no-op (zero-blast) cycle breaks the streak instead of extending it: it is
129
+ // already counted as an empty cycle above, which drives graceful steady-state
130
+ // degradation. Without this guard a gene that keeps producing empty cycles --
131
+ // or a sub-agent whose claimed-success cycles are anti-forgery-rejected to
132
+ // `failed` with zero blast radius -- would double-trigger failure_loop_detected
133
+ // + ban_gene and file a spurious recurring-failure GitHub issue (see #577).
115
134
  var consecutiveFailureCount = 0;
116
135
  for (var cf = recent.length - 1; cf >= 0; cf--) {
136
+ if (_isEmptyCycle(recent[cf])) break;
117
137
  var outcome = recent[cf].outcome;
118
138
  if (outcome && outcome.status === 'failed') {
119
139
  consecutiveFailureCount++;
@@ -122,9 +142,12 @@ function analyzeRecentHistory(recentEvents) {
122
142
  }
123
143
  }
124
144
 
125
- // Count total failures in last 8 events (failure ratio).
145
+ // Count total *productive* failures in last 8 events (failure ratio).
146
+ // Empty (zero-blast) cycles are excluded for the same reason as the
147
+ // consecutive-failure streak above -- a no-op is saturation, not a failure.
126
148
  var recentFailureCount = 0;
127
149
  for (var rf = 0; rf < tail.length; rf++) {
150
+ if (_isEmptyCycle(tail[rf])) continue;
128
151
  var rfOut = tail[rf].outcome;
129
152
  if (rfOut && rfOut.status === 'failed') recentFailureCount++;
130
153
  }
@@ -727,4 +750,5 @@ module.exports = {
727
750
  OPPORTUNITY_SIGNALS, SIGNAL_PROFILES,
728
751
  _extractRegex, _extractKeywordScore, _extractLLM, _mergeSignals,
729
752
  _curlHubIpFamilyArgs, _curlHubIpFamilyAttempts, _curlAuthConfig,
753
+ _isEmptyCycle,
730
754
  };