groove-dev 0.27.136 → 0.27.137

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -147,11 +147,19 @@ export class Rotator extends EventEmitter {
147
147
  const signals = signalsEarly;
148
148
  let score = this.daemon.adaptive.scoreSession(signals);
149
149
 
150
- if (ageSec > 1800) score -= 5;
151
- if (ageSec > 3600) score -= 10;
152
- if (ageSec > 7200) score -= 15;
153
- if (ageSec > 14400) score -= 20;
154
- if (ageSec > 28800) score -= 25;
150
+ // Age penalties: only for providers that don't manage their own context.
151
+ // Claude Code handles context internally via compaction — long sessions
152
+ // are normal and productive. Penalizing age causes premature rotation
153
+ // that destroys active debugging context and creates restart loops.
154
+ const providerForAge = getProvider(agent.provider);
155
+ const selfManagesForAge = providerForAge?.constructor?.managesOwnContext ?? false;
156
+ if (!selfManagesForAge) {
157
+ if (ageSec > 1800) score -= 5;
158
+ if (ageSec > 3600) score -= 10;
159
+ if (ageSec > 7200) score -= 15;
160
+ if (ageSec > 14400) score -= 20;
161
+ if (ageSec > 28800) score -= 25;
162
+ }
155
163
 
156
164
  score = Math.max(0, Math.min(100, score));
157
165
 
@@ -240,16 +248,23 @@ export class Rotator extends EventEmitter {
240
248
  }
241
249
  }
242
250
 
243
- // --- Change 4: Truncation-triggered immediate rotation (all providers) ---
244
- if (agent.consecutiveTruncations >= 2) {
251
+ // --- Change 4: Truncation-triggered rotation ---
252
+ // Self-managing providers need more consecutive truncations — single
253
+ // truncations can be transient API issues, not session degradation.
254
+ const truncationThreshold = selfManagesContext ? 4 : 2;
255
+ if (agent.consecutiveTruncations >= truncationThreshold) {
245
256
  console.log(` Rotator: ${agent.name} consecutiveTruncations=${agent.consecutiveTruncations} — FORCE rotating (incomplete_response)`);
246
257
  await this.rotate(agent.id, { reason: 'incomplete_response', qualityScore: 0 });
247
258
  continue;
248
259
  }
249
260
 
250
- // --- Change 3: Compaction-aware rotation for self-managing providers ---
261
+ // --- Change 3: Compaction-aware rotation ---
262
+ // Only for non-self-managing providers. Claude Code compacts internally
263
+ // as part of normal operation — it's healthy, not degradation. Counting
264
+ // compactions toward a ceiling causes premature rotation that destroys
265
+ // active debugging sessions and creates restart loops.
251
266
  const compactions = this.compactionCounts.get(agent.id) || 0;
252
- if (compactions >= 5) {
267
+ if (!selfManagesContext && compactions >= 5) {
253
268
  console.log(` Rotator: ${agent.name} compactions=${compactions} — FORCE rotating (compaction_ceiling)`);
254
269
  await this.rotate(agent.id, { reason: 'compaction_ceiling' });
255
270
  continue;
@@ -259,18 +274,30 @@ export class Rotator extends EventEmitter {
259
274
  // agents don't persist producing bad output for 8-10 minutes
260
275
  if (this._isOnCooldown(agent.id, QUALITY_COOLDOWN_MS)) continue;
261
276
 
262
- // Effective quality threshold: lower for agents showing degradation signals
263
- let effectiveQualityThreshold = QUALITY_THRESHOLD;
264
- if (compactions >= 3 || agent.truncationSuspected || agent.cacheResetDetected) {
265
- effectiveQualityThreshold = 55;
277
+ // Effective quality threshold depends on provider type.
278
+ // Self-managing providers (Claude Code): threshold = 15. Only rotate on
279
+ // truly catastrophic degradation. Normal debugging naturally produces
280
+ // errors, retries, and bash repetitions — the scoring model treats these
281
+ // as degradation but they're expected behavior during investigation.
282
+ // A threshold of 40 (the default) kills debugging sessions at ~8 minutes.
283
+ let effectiveQualityThreshold;
284
+ if (selfManagesContext) {
285
+ effectiveQualityThreshold = 15;
286
+ } else {
287
+ effectiveQualityThreshold = QUALITY_THRESHOLD;
288
+ if (compactions >= 3) effectiveQualityThreshold = 55;
289
+ if (agent.truncationSuspected || agent.cacheResetDetected) {
290
+ effectiveQualityThreshold = Math.max(effectiveQualityThreshold, 55);
291
+ }
266
292
  }
267
293
 
268
- // All providers: quality-based rotation — detects degradation before tokens are wasted
269
294
  const quality = this.scoreLiveSession(agent);
270
295
  if (quality.hasEnoughData && quality.score < effectiveQualityThreshold) {
271
- // Severe degradation (score < 25): rotate immediately regardless of idle state.
272
- // The agent is producing bad output waiting for idle is counterproductive.
273
- if (quality.score < 25) {
296
+ // For self-managing providers, effectiveQualityThreshold IS the severe
297
+ // threshold (15) any score below it is catastrophic, rotate immediately.
298
+ // For others, severe = < 25, moderate = 25-40/55.
299
+ const severeThreshold = selfManagesContext ? effectiveQualityThreshold : 25;
300
+ if (quality.score < severeThreshold) {
274
301
  console.log(` Rotator: ${agent.name} quality=${quality.score} — FORCE rotating (severe degradation)`);
275
302
  await this.rotate(agent.id, {
276
303
  reason: 'quality_degradation',
@@ -279,8 +306,10 @@ export class Rotator extends EventEmitter {
279
306
  });
280
307
  continue;
281
308
  }
282
- // Moderate degradation (25-40): rotate when idle
283
- if (this._idleMs(agent) > 10_000) {
309
+ // Moderate degradation (25-40): only for non-self-managing providers.
310
+ // Claude Code sessions should never be killed for "moderate" quality —
311
+ // errors during debugging are expected, not degradation.
312
+ if (!selfManagesContext && this._idleMs(agent) > 10_000) {
284
313
  console.log(` Rotator: ${agent.name} quality=${quality.score} — rotating (quality)`);
285
314
  await this.rotate(agent.id, {
286
315
  reason: 'quality_degradation',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groove-dev",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -147,11 +147,19 @@ export class Rotator extends EventEmitter {
147
147
  const signals = signalsEarly;
148
148
  let score = this.daemon.adaptive.scoreSession(signals);
149
149
 
150
- if (ageSec > 1800) score -= 5;
151
- if (ageSec > 3600) score -= 10;
152
- if (ageSec > 7200) score -= 15;
153
- if (ageSec > 14400) score -= 20;
154
- if (ageSec > 28800) score -= 25;
150
+ // Age penalties: only for providers that don't manage their own context.
151
+ // Claude Code handles context internally via compaction — long sessions
152
+ // are normal and productive. Penalizing age causes premature rotation
153
+ // that destroys active debugging context and creates restart loops.
154
+ const providerForAge = getProvider(agent.provider);
155
+ const selfManagesForAge = providerForAge?.constructor?.managesOwnContext ?? false;
156
+ if (!selfManagesForAge) {
157
+ if (ageSec > 1800) score -= 5;
158
+ if (ageSec > 3600) score -= 10;
159
+ if (ageSec > 7200) score -= 15;
160
+ if (ageSec > 14400) score -= 20;
161
+ if (ageSec > 28800) score -= 25;
162
+ }
155
163
 
156
164
  score = Math.max(0, Math.min(100, score));
157
165
 
@@ -240,16 +248,23 @@ export class Rotator extends EventEmitter {
240
248
  }
241
249
  }
242
250
 
243
- // --- Change 4: Truncation-triggered immediate rotation (all providers) ---
244
- if (agent.consecutiveTruncations >= 2) {
251
+ // --- Change 4: Truncation-triggered rotation ---
252
+ // Self-managing providers need more consecutive truncations — single
253
+ // truncations can be transient API issues, not session degradation.
254
+ const truncationThreshold = selfManagesContext ? 4 : 2;
255
+ if (agent.consecutiveTruncations >= truncationThreshold) {
245
256
  console.log(` Rotator: ${agent.name} consecutiveTruncations=${agent.consecutiveTruncations} — FORCE rotating (incomplete_response)`);
246
257
  await this.rotate(agent.id, { reason: 'incomplete_response', qualityScore: 0 });
247
258
  continue;
248
259
  }
249
260
 
250
- // --- Change 3: Compaction-aware rotation for self-managing providers ---
261
+ // --- Change 3: Compaction-aware rotation ---
262
+ // Only for non-self-managing providers. Claude Code compacts internally
263
+ // as part of normal operation — it's healthy, not degradation. Counting
264
+ // compactions toward a ceiling causes premature rotation that destroys
265
+ // active debugging sessions and creates restart loops.
251
266
  const compactions = this.compactionCounts.get(agent.id) || 0;
252
- if (compactions >= 5) {
267
+ if (!selfManagesContext && compactions >= 5) {
253
268
  console.log(` Rotator: ${agent.name} compactions=${compactions} — FORCE rotating (compaction_ceiling)`);
254
269
  await this.rotate(agent.id, { reason: 'compaction_ceiling' });
255
270
  continue;
@@ -259,18 +274,30 @@ export class Rotator extends EventEmitter {
259
274
  // agents don't persist producing bad output for 8-10 minutes
260
275
  if (this._isOnCooldown(agent.id, QUALITY_COOLDOWN_MS)) continue;
261
276
 
262
- // Effective quality threshold: lower for agents showing degradation signals
263
- let effectiveQualityThreshold = QUALITY_THRESHOLD;
264
- if (compactions >= 3 || agent.truncationSuspected || agent.cacheResetDetected) {
265
- effectiveQualityThreshold = 55;
277
+ // Effective quality threshold depends on provider type.
278
+ // Self-managing providers (Claude Code): threshold = 15. Only rotate on
279
+ // truly catastrophic degradation. Normal debugging naturally produces
280
+ // errors, retries, and bash repetitions — the scoring model treats these
281
+ // as degradation but they're expected behavior during investigation.
282
+ // A threshold of 40 (the default) kills debugging sessions at ~8 minutes.
283
+ let effectiveQualityThreshold;
284
+ if (selfManagesContext) {
285
+ effectiveQualityThreshold = 15;
286
+ } else {
287
+ effectiveQualityThreshold = QUALITY_THRESHOLD;
288
+ if (compactions >= 3) effectiveQualityThreshold = 55;
289
+ if (agent.truncationSuspected || agent.cacheResetDetected) {
290
+ effectiveQualityThreshold = Math.max(effectiveQualityThreshold, 55);
291
+ }
266
292
  }
267
293
 
268
- // All providers: quality-based rotation — detects degradation before tokens are wasted
269
294
  const quality = this.scoreLiveSession(agent);
270
295
  if (quality.hasEnoughData && quality.score < effectiveQualityThreshold) {
271
- // Severe degradation (score < 25): rotate immediately regardless of idle state.
272
- // The agent is producing bad output waiting for idle is counterproductive.
273
- if (quality.score < 25) {
296
+ // For self-managing providers, effectiveQualityThreshold IS the severe
297
+ // threshold (15) any score below it is catastrophic, rotate immediately.
298
+ // For others, severe = < 25, moderate = 25-40/55.
299
+ const severeThreshold = selfManagesContext ? effectiveQualityThreshold : 25;
300
+ if (quality.score < severeThreshold) {
274
301
  console.log(` Rotator: ${agent.name} quality=${quality.score} — FORCE rotating (severe degradation)`);
275
302
  await this.rotate(agent.id, {
276
303
  reason: 'quality_degradation',
@@ -279,8 +306,10 @@ export class Rotator extends EventEmitter {
279
306
  });
280
307
  continue;
281
308
  }
282
- // Moderate degradation (25-40): rotate when idle
283
- if (this._idleMs(agent) > 10_000) {
309
+ // Moderate degradation (25-40): only for non-self-managing providers.
310
+ // Claude Code sessions should never be killed for "moderate" quality —
311
+ // errors during debugging are expected, not degradation.
312
+ if (!selfManagesContext && this._idleMs(agent) > 10_000) {
284
313
  console.log(` Rotator: ${agent.name} quality=${quality.score} — rotating (quality)`);
285
314
  await this.rotate(agent.id, {
286
315
  reason: 'quality_degradation',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.136",
3
+ "version": "0.27.137",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",