clementine-agent 1.0.34 → 1.0.36
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/dist/agent/self-improve.js +29 -7
- package/dist/cli/index.js +39 -16
- package/package.json +1 -1
|
@@ -198,6 +198,11 @@ export class SelfImproveLoop {
|
|
|
198
198
|
const loopStart = Date.now();
|
|
199
199
|
const history = this.loadExperimentLog();
|
|
200
200
|
let consecutiveLow = 0;
|
|
201
|
+
// Cap accepted proposals per run so the owner's approval queue stays
|
|
202
|
+
// scannable. The nightly loop should surface 1-3 solid ideas — not a
|
|
203
|
+
// flood — even if the hypothesizer is inspired.
|
|
204
|
+
const maxAcceptancesPerRun = 3;
|
|
205
|
+
let acceptedThisRun = 0;
|
|
201
206
|
try {
|
|
202
207
|
// Step 1: Gather baseline metrics
|
|
203
208
|
const metrics = await this.gatherMetrics();
|
|
@@ -379,6 +384,7 @@ export class SelfImproveLoop {
|
|
|
379
384
|
}
|
|
380
385
|
}
|
|
381
386
|
consecutiveLow = 0;
|
|
387
|
+
acceptedThisRun++;
|
|
382
388
|
}
|
|
383
389
|
else {
|
|
384
390
|
consecutiveLow++;
|
|
@@ -389,7 +395,13 @@ export class SelfImproveLoop {
|
|
|
389
395
|
area: proposal.area,
|
|
390
396
|
score,
|
|
391
397
|
accepted,
|
|
398
|
+
acceptedThisRun,
|
|
392
399
|
}, `Iteration ${i} complete`);
|
|
400
|
+
// Stop once we've landed enough good ideas for the owner to review.
|
|
401
|
+
if (acceptedThisRun >= maxAcceptancesPerRun) {
|
|
402
|
+
logger.info({ acceptedThisRun }, 'Reached max-acceptances per run — stopping');
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
393
405
|
}
|
|
394
406
|
catch (err) {
|
|
395
407
|
const classified = classifyError(err);
|
|
@@ -666,6 +678,17 @@ export class SelfImproveLoop {
|
|
|
666
678
|
const recentTargets = new Map();
|
|
667
679
|
const recentAreas = new Map();
|
|
668
680
|
for (const e of history.slice(-50)) {
|
|
681
|
+
// Skip error-fallback experiments. They default to `area: 'soul', target:
|
|
682
|
+
// 'unknown'` (see the error-catch block below) and historically have
|
|
683
|
+
// poisoned diversity accounting — e.g. a ~2-week stretch of API errors
|
|
684
|
+
// artificially blacklisted the whole 'soul' area even though no real
|
|
685
|
+
// attempt was made. A crashed iteration isn't evidence we explored the
|
|
686
|
+
// space, just that the SDK call failed.
|
|
687
|
+
if (e.reason?.startsWith('Error:'))
|
|
688
|
+
continue;
|
|
689
|
+
// Plateau markers also shouldn't count as attempts.
|
|
690
|
+
if (e.hypothesis?.startsWith('No new hypothesis'))
|
|
691
|
+
continue;
|
|
669
692
|
const key = `${e.area}:${e.target}`;
|
|
670
693
|
const ts = Date.parse(e.startedAt);
|
|
671
694
|
const tsMs = Number.isFinite(ts) ? ts : 0;
|
|
@@ -717,7 +740,7 @@ export class SelfImproveLoop {
|
|
|
717
740
|
(overTargeted.length > 0
|
|
718
741
|
? `These specific targets MUST NOT be re-targeted:\n${overTargeted.map(t => `- ${t}`).join('\n')}\n`
|
|
719
742
|
: '') +
|
|
720
|
-
`Choose a DIFFERENT area/target. If no other improvement is needed,
|
|
743
|
+
`Choose a DIFFERENT area/target. If no other improvement is genuinely needed today, return an empty results array: { "results": [] }.\n`
|
|
721
744
|
: '');
|
|
722
745
|
const patternAnalysis = this.analyzeExperimentPatterns(history);
|
|
723
746
|
// Format negative feedback
|
|
@@ -802,18 +825,17 @@ export class SelfImproveLoop {
|
|
|
802
825
|
agentFocusText +
|
|
803
826
|
soulCandidatesText +
|
|
804
827
|
`\n## Instructions\n` +
|
|
805
|
-
`Rank
|
|
828
|
+
`Propose **1-3 concrete, high-impact improvements** the owner should review today — no fewer (aim for at least one actionable suggestion when data warrants it), no more (the owner reads each proposal manually and you'll overwhelm them). Rank by expected impact; drop anything below "solid idea".\n\n` +
|
|
829
|
+
`For each opportunity, specify:\n` +
|
|
806
830
|
`- area: ${areas}\n` +
|
|
807
|
-
`- target: the file/agent slug that should change\n` +
|
|
831
|
+
`- target: the exact file path / agent slug / cron job name that should change (not "unknown", not "n/a")\n` +
|
|
808
832
|
`- what: a 1-sentence description of what specifically should change\n` +
|
|
809
|
-
`- why: which metric this should improve\n\n` +
|
|
833
|
+
`- why: which metric or signal from the data above this should improve\n\n` +
|
|
810
834
|
`Area notes:\n` +
|
|
811
835
|
`- For "goal": target = "{owner}/{goal-slug}" (e.g. "clementine/improve-reply-rates" or "ross-the-sdr/book-demos"). ` +
|
|
812
836
|
`Propose when you observe a pattern in completed tasks or cron runs that suggests a missing or stale goal. ` +
|
|
813
837
|
`The proposedChange must be a JSON goal object with at minimum: title, description, priority, reviewFrequency.\n\n` +
|
|
814
|
-
`
|
|
815
|
-
`[{ "area": "...", "target": "...", "what": "...", "why": "..." }]\n` +
|
|
816
|
-
`If no improvement is needed, output: []`;
|
|
838
|
+
`Return your answer as a JSON object matching the schema: { "results": [ ... ] }. Up to 3 items. If absolutely nothing actionable today, return { "results": [] }.`;
|
|
817
839
|
const analysisResult = await this.assistant.runPlanStep('si-analyze', analysisPrompt, {
|
|
818
840
|
tier: 2,
|
|
819
841
|
maxTurns: 3,
|
package/dist/cli/index.js
CHANGED
|
@@ -480,6 +480,7 @@ function cmdDoctor(opts = {}) {
|
|
|
480
480
|
console.log(` ${DIM}Running health checks...${fix ? ` (auto-fix enabled)` : ''}${RESET}`);
|
|
481
481
|
console.log();
|
|
482
482
|
let issues = 0;
|
|
483
|
+
let warnings = 0;
|
|
483
484
|
let fixed = 0;
|
|
484
485
|
const isMac = process.platform === 'darwin';
|
|
485
486
|
const isLinux = process.platform === 'linux';
|
|
@@ -497,6 +498,9 @@ function cmdDoctor(opts = {}) {
|
|
|
497
498
|
catch {
|
|
498
499
|
return false;
|
|
499
500
|
} })();
|
|
501
|
+
// One-liner to install Homebrew on macOS — surfaced when brew is missing
|
|
502
|
+
// so users have a copy-pasteable fix instead of searching for it.
|
|
503
|
+
const BREW_INSTALL_CMD = '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"';
|
|
500
504
|
/** Attempt a fix command, return true on success. */
|
|
501
505
|
function tryFix(label, cmd, opts) {
|
|
502
506
|
if (!fix)
|
|
@@ -572,24 +576,32 @@ function cmdDoctor(opts = {}) {
|
|
|
572
576
|
}
|
|
573
577
|
}
|
|
574
578
|
// FalkorDB graph engine — system dependencies: redis
|
|
579
|
+
// Optional at runtime: graph-store.ts degrades gracefully (isAvailable()
|
|
580
|
+
// returns false; graph operations become no-ops). Missing deps are a
|
|
581
|
+
// warning, not a blocking issue — daemon launches fine without them.
|
|
575
582
|
try {
|
|
576
583
|
execSync('which redis-server', { stdio: 'pipe' });
|
|
577
584
|
console.log(` ${GREEN}OK${RESET} redis-server found`);
|
|
578
585
|
}
|
|
579
586
|
catch {
|
|
580
|
-
console.log(` ${
|
|
587
|
+
console.log(` ${YELLOW}WARN${RESET} redis-server not found (optional — enables knowledge graph)`);
|
|
581
588
|
const fixCmd = hasBrew ? 'brew install redis' : hasApt ? 'sudo apt-get install -y redis-server' : null;
|
|
582
589
|
if (fixCmd && tryFix('redis-server', fixCmd)) {
|
|
583
590
|
// fixed
|
|
584
591
|
}
|
|
585
592
|
else if (!fixCmd && fix) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
593
|
+
if (isMac) {
|
|
594
|
+
console.log(` ${YELLOW}Homebrew not installed.${RESET} Install it first, then re-run ${CYAN}clementine doctor --fix${RESET}:`);
|
|
595
|
+
console.log(` ${BREW_INSTALL_CMD}`);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
console.log(` Install redis-server manually (no supported package manager detected)`);
|
|
599
|
+
}
|
|
600
|
+
warnings++;
|
|
589
601
|
}
|
|
590
602
|
else {
|
|
591
603
|
console.log(` Fix: brew install redis (macOS) or sudo apt install redis-server (Linux)`);
|
|
592
|
-
|
|
604
|
+
warnings++;
|
|
593
605
|
}
|
|
594
606
|
}
|
|
595
607
|
// FalkorDB graph engine — system dependencies: libomp
|
|
@@ -603,19 +615,25 @@ function cmdDoctor(opts = {}) {
|
|
|
603
615
|
console.log(` ${GREEN}OK${RESET} libomp (OpenMP runtime) found`);
|
|
604
616
|
}
|
|
605
617
|
catch {
|
|
606
|
-
console.log(` ${
|
|
618
|
+
console.log(` ${YELLOW}WARN${RESET} libomp (OpenMP runtime) not found (optional — enables knowledge graph)`);
|
|
607
619
|
const fixCmd = hasBrew ? 'brew install libomp' : hasApt ? 'sudo apt-get install -y libomp-dev' : null;
|
|
608
620
|
if (fixCmd && tryFix('libomp', fixCmd)) {
|
|
609
621
|
// fixed
|
|
610
622
|
}
|
|
611
623
|
else if (!fixCmd && fix) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
624
|
+
if (isMac) {
|
|
625
|
+
// Redis check above already printed the brew installer command;
|
|
626
|
+
// avoid spamming it twice by just pointing back to that guidance.
|
|
627
|
+
console.log(` Install Homebrew (see redis-server WARN above), then ${CYAN}brew install libomp${RESET}`);
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
console.log(` Install libomp manually (no supported package manager detected)`);
|
|
631
|
+
}
|
|
632
|
+
warnings++;
|
|
615
633
|
}
|
|
616
634
|
else {
|
|
617
635
|
console.log(` Fix: brew install libomp (macOS) or sudo apt install libomp-dev (Linux)`);
|
|
618
|
-
|
|
636
|
+
warnings++;
|
|
619
637
|
}
|
|
620
638
|
}
|
|
621
639
|
// FalkorDB graph engine — module binaries
|
|
@@ -624,10 +642,11 @@ function cmdDoctor(opts = {}) {
|
|
|
624
642
|
console.log(` ${GREEN}OK${RESET} FalkorDB graph engine binaries installed`);
|
|
625
643
|
}
|
|
626
644
|
catch {
|
|
627
|
-
console.log(` ${
|
|
645
|
+
console.log(` ${YELLOW}WARN${RESET} FalkorDB graph engine binaries not available (optional — enables knowledge graph)`);
|
|
628
646
|
if (!tryFix('FalkorDB binaries', `node node_modules/falkordblite/scripts/postinstall.js`, { cwd: PACKAGE_ROOT, timeout: 180000 })) {
|
|
629
647
|
console.log(` Fix: cd ${PACKAGE_ROOT} && node node_modules/falkordblite/scripts/postinstall.js`);
|
|
630
|
-
|
|
648
|
+
console.log(` ${DIM}(Usually self-heals once redis-server + libomp are installed)${RESET}`);
|
|
649
|
+
warnings++;
|
|
631
650
|
}
|
|
632
651
|
}
|
|
633
652
|
// Data home
|
|
@@ -829,17 +848,21 @@ function cmdDoctor(opts = {}) {
|
|
|
829
848
|
}
|
|
830
849
|
}
|
|
831
850
|
console.log();
|
|
832
|
-
|
|
851
|
+
const warnSuffix = warnings > 0 ? `, ${warnings} warning(s)` : '';
|
|
852
|
+
if (issues === 0 && fixed === 0 && warnings === 0) {
|
|
833
853
|
console.log(` ${GREEN}All checks passed.${RESET}`);
|
|
834
854
|
}
|
|
855
|
+
else if (issues === 0 && fixed === 0 && warnings > 0) {
|
|
856
|
+
console.log(` ${GREEN}Ready to launch.${RESET} ${warnings} optional dependency warning(s) — safe to ignore or install for full experience.`);
|
|
857
|
+
}
|
|
835
858
|
else if (issues === 0 && fixed > 0) {
|
|
836
|
-
console.log(` ${GREEN}All issues fixed!${RESET} (${fixed} auto-fixed)`);
|
|
859
|
+
console.log(` ${GREEN}All issues fixed!${RESET} (${fixed} auto-fixed${warnSuffix})`);
|
|
837
860
|
}
|
|
838
861
|
else if (fixed > 0) {
|
|
839
|
-
console.log(` ${YELLOW}${issues} issue(s) remaining${RESET} (${fixed} auto-fixed)`);
|
|
862
|
+
console.log(` ${YELLOW}${issues} issue(s) remaining${RESET} (${fixed} auto-fixed${warnSuffix})`);
|
|
840
863
|
}
|
|
841
864
|
else {
|
|
842
|
-
console.log(` ${YELLOW}${issues} issue(s) found.${RESET}${!fix ? ` Run ${CYAN}clementine doctor --fix${RESET} to auto-install dependencies.` : ''}`);
|
|
865
|
+
console.log(` ${YELLOW}${issues} issue(s) found${warnSuffix}.${RESET}${!fix ? ` Run ${CYAN}clementine doctor --fix${RESET} to auto-install dependencies.` : ''}`);
|
|
843
866
|
}
|
|
844
867
|
console.log();
|
|
845
868
|
}
|