@cleocode/core 2026.4.29 → 2026.4.31
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/bootstrap.d.ts +35 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/code/index.d.ts +8 -4
- package/dist/code/index.d.ts.map +1 -1
- package/dist/code/parser.d.ts +22 -9
- package/dist/code/parser.d.ts.map +1 -1
- package/dist/hooks/handlers/session-hooks.d.ts +11 -4
- package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
- package/dist/hooks/payload-schemas.d.ts +6 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3859 -3008
- package/dist/index.js.map +4 -4
- package/dist/internal.d.ts +10 -7
- package/dist/internal.d.ts.map +1 -1
- package/dist/lib/tree-sitter-languages.d.ts +11 -7
- package/dist/lib/tree-sitter-languages.d.ts.map +1 -1
- package/dist/memory/auto-extract.d.ts +27 -15
- package/dist/memory/auto-extract.d.ts.map +1 -1
- package/dist/memory/brain-backfill.d.ts +59 -0
- package/dist/memory/brain-backfill.d.ts.map +1 -0
- package/dist/memory/brain-purge.d.ts +51 -0
- package/dist/memory/brain-purge.d.ts.map +1 -0
- package/dist/memory/brain-retrieval.d.ts.map +1 -1
- package/dist/memory/brain-search.d.ts.map +1 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/engine-compat.d.ts +71 -0
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/graph-auto-populate.d.ts +65 -0
- package/dist/memory/graph-auto-populate.d.ts.map +1 -0
- package/dist/memory/graph-queries.d.ts +127 -0
- package/dist/memory/graph-queries.d.ts.map +1 -0
- package/dist/memory/learnings.d.ts +2 -0
- package/dist/memory/learnings.d.ts.map +1 -1
- package/dist/memory/patterns.d.ts +2 -0
- package/dist/memory/patterns.d.ts.map +1 -1
- package/dist/memory/quality-scoring.d.ts +90 -0
- package/dist/memory/quality-scoring.d.ts.map +1 -0
- package/dist/sessions/session-memory-bridge.d.ts +16 -10
- package/dist/sessions/session-memory-bridge.d.ts.map +1 -1
- package/dist/store/brain-accessor.d.ts +7 -0
- package/dist/store/brain-accessor.d.ts.map +1 -1
- package/dist/store/brain-schema.d.ts +185 -11
- package/dist/store/brain-schema.d.ts.map +1 -1
- package/dist/store/brain-sqlite.d.ts.map +1 -1
- package/dist/store/nexus-schema.d.ts +480 -2
- package/dist/store/nexus-schema.d.ts.map +1 -1
- package/dist/store/tasks-schema.d.ts +9 -9
- package/dist/store/validation-schemas.d.ts +44 -28
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/system/dependencies.d.ts +43 -0
- package/dist/system/dependencies.d.ts.map +1 -0
- package/dist/system/health.d.ts +3 -0
- package/dist/system/health.d.ts.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/package.json +19 -19
- package/src/bootstrap.ts +124 -0
- package/src/code/index.ts +20 -4
- package/src/code/parser.ts +310 -110
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.ts +19 -45
- package/src/hooks/handlers/__tests__/session-hooks.test.ts +42 -54
- package/src/hooks/handlers/session-hooks.ts +11 -33
- package/src/index.ts +14 -0
- package/src/internal.ts +37 -7
- package/src/lib/tree-sitter-languages.ts +11 -7
- package/src/memory/__tests__/auto-extract.test.ts +20 -82
- package/src/memory/__tests__/embedding-pipeline.test.ts +389 -0
- package/src/memory/auto-extract.ts +34 -120
- package/src/memory/brain-backfill.ts +471 -0
- package/src/memory/brain-purge.ts +315 -0
- package/src/memory/brain-retrieval.ts +43 -2
- package/src/memory/brain-search.ts +23 -6
- package/src/memory/decisions.ts +76 -3
- package/src/memory/engine-compat.ts +168 -0
- package/src/memory/graph-auto-populate.ts +173 -0
- package/src/memory/graph-queries.ts +424 -0
- package/src/memory/learnings.ts +55 -7
- package/src/memory/patterns.ts +66 -13
- package/src/memory/quality-scoring.ts +173 -0
- package/src/sessions/__tests__/session-memory-bridge.test.ts +27 -49
- package/src/sessions/session-memory-bridge.ts +19 -47
- package/src/store/__tests__/brain-accessor-pageindex.test.ts +93 -22
- package/src/store/brain-accessor.ts +48 -2
- package/src/store/brain-schema.ts +165 -13
- package/src/store/brain-sqlite.ts +35 -0
- package/src/store/nexus-schema.ts +257 -3
- package/src/system/dependencies.ts +534 -0
- package/src/system/health.ts +126 -22
- package/src/tasks/complete.ts +40 -0
package/src/system/health.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @task T4795
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { execFileSync } from 'node:child_process';
|
|
8
8
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
9
9
|
import { createRequire } from 'node:module';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
|
-
import {
|
|
11
|
+
import type { DependencyReport } from '@cleocode/contracts';
|
|
12
12
|
import { checkGitHooks, type HookCheckResult } from '../hooks.js';
|
|
13
13
|
import { checkInjection } from '../injection.js';
|
|
14
14
|
import { getAgentsHome, isProjectInitialized } from '../paths.js';
|
|
@@ -37,9 +37,15 @@ import {
|
|
|
37
37
|
checkNodeVersion,
|
|
38
38
|
checkVitalFilesTracked,
|
|
39
39
|
} from '../validation/doctor/checks.js';
|
|
40
|
+
import { checkAllDependencies } from './dependencies.js';
|
|
40
41
|
import { checkStorageMigration } from './storage-preflight.js';
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
// NOTE on storage-migration preflight consolidation (T511):
|
|
44
|
+
// `checkStorageMigration` lives in ./storage-preflight.ts and is the single
|
|
45
|
+
// source of truth. Both `self-update.ts` and `upgrade.ts` import it from
|
|
46
|
+
// `@cleocode/core/internal`. No duplication exists — this comment documents
|
|
47
|
+
// that the consolidation is already in place.
|
|
48
|
+
|
|
43
49
|
const _require = createRequire(import.meta.url);
|
|
44
50
|
|
|
45
51
|
type SqliteModule = typeof import('node:sqlite');
|
|
@@ -449,15 +455,8 @@ export interface DoctorReport {
|
|
|
449
455
|
errors: number;
|
|
450
456
|
warnings: number;
|
|
451
457
|
checks: DoctorCheck[];
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
async function commandExists(cmd: string): Promise<string | null> {
|
|
455
|
-
try {
|
|
456
|
-
const { stdout } = await execAsync('which', [cmd]);
|
|
457
|
-
return stdout.trim();
|
|
458
|
-
} catch {
|
|
459
|
-
return null;
|
|
460
|
-
}
|
|
458
|
+
/** Dependency registry report — populated by `checkAllDependencies()`. */
|
|
459
|
+
dependencies?: DependencyReport;
|
|
461
460
|
}
|
|
462
461
|
|
|
463
462
|
async function fileSize(path: string): Promise<number> {
|
|
@@ -601,6 +600,63 @@ function checkContributorChannel(projectRoot: string): DoctorCheck {
|
|
|
601
600
|
}
|
|
602
601
|
}
|
|
603
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Run adapter health checks for all discovered adapters and return doctor
|
|
605
|
+
* check entries. Returns an empty array when no adapters are initialized
|
|
606
|
+
* (adapters are optional — their absence is not an error).
|
|
607
|
+
*
|
|
608
|
+
* @param projectRoot - Absolute path to the project root
|
|
609
|
+
* @returns Array of DoctorCheck entries, one per adapter (plus a summary if none found)
|
|
610
|
+
*/
|
|
611
|
+
async function checkAdapterHealth(projectRoot: string): Promise<DoctorCheck[]> {
|
|
612
|
+
const results: DoctorCheck[] = [];
|
|
613
|
+
try {
|
|
614
|
+
const { AdapterManager } = await import('../adapters/index.js');
|
|
615
|
+
const { getPackageRoot } = await import('../scaffold.js');
|
|
616
|
+
// Prefer the caller-supplied projectRoot; fall back to the package root for
|
|
617
|
+
// adapter manifest discovery when projectRoot is not a package root itself.
|
|
618
|
+
const pkgRoot = projectRoot || getPackageRoot();
|
|
619
|
+
const manager = AdapterManager.getInstance(pkgRoot);
|
|
620
|
+
|
|
621
|
+
// Discover manifests (idempotent if already discovered)
|
|
622
|
+
manager.discover();
|
|
623
|
+
|
|
624
|
+
// Run health checks on any already-initialized adapters
|
|
625
|
+
const healthMap = await manager.healthCheckAll();
|
|
626
|
+
|
|
627
|
+
if (healthMap.size === 0) {
|
|
628
|
+
// No adapters initialized — adapters are optional, report as info
|
|
629
|
+
results.push({
|
|
630
|
+
check: 'adapter_health',
|
|
631
|
+
status: 'ok',
|
|
632
|
+
message: 'No adapters initialized (adapters are optional)',
|
|
633
|
+
});
|
|
634
|
+
} else {
|
|
635
|
+
for (const [adapterId, status] of healthMap) {
|
|
636
|
+
results.push({
|
|
637
|
+
check: `adapter_${adapterId.replace(/-/g, '_')}`,
|
|
638
|
+
status: status.healthy ? 'ok' : 'warning',
|
|
639
|
+
message: status.healthy
|
|
640
|
+
? `Adapter ${adapterId} (${status.provider}) healthy`
|
|
641
|
+
: `Adapter ${adapterId} (${status.provider}) unhealthy`,
|
|
642
|
+
...(status.details && Object.keys(status.details).length > 0
|
|
643
|
+
? { details: status.details as Record<string, unknown> }
|
|
644
|
+
: {}),
|
|
645
|
+
...(!status.healthy ? { fix: `cleo adapter health ${adapterId}` } : {}),
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
} catch {
|
|
650
|
+
// Adapter system is non-critical — never let it block the doctor report
|
|
651
|
+
results.push({
|
|
652
|
+
check: 'adapter_health',
|
|
653
|
+
status: 'warning',
|
|
654
|
+
message: 'Adapter health check unavailable (adapter system not reachable)',
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
return results;
|
|
658
|
+
}
|
|
659
|
+
|
|
604
660
|
/**
|
|
605
661
|
* Run comprehensive doctor diagnostics combining dependency checks,
|
|
606
662
|
* directory checks, data file checks, gitignore checks, and environment info.
|
|
@@ -609,15 +665,31 @@ function checkContributorChannel(projectRoot: string): DoctorCheck {
|
|
|
609
665
|
export async function coreDoctorReport(projectRoot: string): Promise<DoctorReport> {
|
|
610
666
|
const checks: DoctorCheck[] = [];
|
|
611
667
|
|
|
612
|
-
// 1.
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
668
|
+
// 1. Dependency registry — single source of truth for all external deps (T507)
|
|
669
|
+
const depReport = await checkAllDependencies();
|
|
670
|
+
// Wire individual dependency results into the doctor check list so existing
|
|
671
|
+
// consumers (CLI renderers, tests) see familiar DoctorCheck entries.
|
|
672
|
+
for (const dep of depReport.results) {
|
|
673
|
+
const isRequired = dep.category === 'required';
|
|
674
|
+
const status: 'ok' | 'warning' | 'error' = dep.healthy
|
|
675
|
+
? dep.installed
|
|
676
|
+
? 'ok'
|
|
677
|
+
: 'warning' // optional/feature not installed — warn, not error
|
|
678
|
+
: isRequired
|
|
679
|
+
? 'error'
|
|
680
|
+
: 'warning';
|
|
681
|
+
|
|
682
|
+
const message = dep.installed
|
|
683
|
+
? `${dep.name}${dep.version ? ` ${dep.version}` : ''}${dep.location ? ` (${dep.location})` : ''}`
|
|
684
|
+
: (dep.error ?? `${dep.name} not found`);
|
|
685
|
+
|
|
686
|
+
checks.push({
|
|
687
|
+
check: `dep_${dep.name.replace(/-/g, '_')}`,
|
|
688
|
+
status,
|
|
689
|
+
message,
|
|
690
|
+
...(dep.suggestedFix ? { fix: dep.suggestedFix } : {}),
|
|
691
|
+
});
|
|
692
|
+
}
|
|
621
693
|
|
|
622
694
|
// 2. Check CLEO directories
|
|
623
695
|
const cleoDir = join(projectRoot, '.cleo');
|
|
@@ -798,6 +870,38 @@ export async function coreDoctorReport(projectRoot: string): Promise<DoctorRepor
|
|
|
798
870
|
...(existsSync(agentDefPath) ? {} : { fix: 'cleo init' }),
|
|
799
871
|
});
|
|
800
872
|
|
|
873
|
+
// 5e. brain.db and memory-bridge checks (T511 — consolidate startup checks into doctor)
|
|
874
|
+
// These are checked in startupHealthCheck() as warnings. The doctor report is the
|
|
875
|
+
// comprehensive view so it must include them too, making startupHealthCheck() a subset.
|
|
876
|
+
const brainDbCheckResult = checkBrainDb(projectRoot);
|
|
877
|
+
checks.push({
|
|
878
|
+
check: 'brain_db',
|
|
879
|
+
status:
|
|
880
|
+
brainDbCheckResult.status === 'passed'
|
|
881
|
+
? 'ok'
|
|
882
|
+
: brainDbCheckResult.status === 'warning'
|
|
883
|
+
? 'warning'
|
|
884
|
+
: 'error',
|
|
885
|
+
message: brainDbCheckResult.message,
|
|
886
|
+
...(brainDbCheckResult.fix ? { fix: brainDbCheckResult.fix } : {}),
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
const memBridgeCheckResult = checkMemoryBridge(projectRoot);
|
|
890
|
+
checks.push({
|
|
891
|
+
check: 'memory_bridge',
|
|
892
|
+
status: memBridgeCheckResult.status === 'passed' ? 'ok' : 'warning',
|
|
893
|
+
message: memBridgeCheckResult.message,
|
|
894
|
+
...(memBridgeCheckResult.fix ? { fix: memBridgeCheckResult.fix } : {}),
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
// 5f. Adapter health checks (T511 — wire adapter health into doctor)
|
|
898
|
+
// `cleo adapter health` was previously isolated from the doctor report.
|
|
899
|
+
// The doctor is the comprehensive diagnostic view so adapter health belongs here.
|
|
900
|
+
const adapterChecks = await checkAdapterHealth(projectRoot);
|
|
901
|
+
for (const ac of adapterChecks) {
|
|
902
|
+
checks.push(ac);
|
|
903
|
+
}
|
|
904
|
+
|
|
801
905
|
// 6a. GitHub templates presence (informational only — non-critical)
|
|
802
906
|
const gitDir = join(projectRoot, '.git');
|
|
803
907
|
const gitHubTemplatesDir = join(projectRoot, '.github', 'ISSUE_TEMPLATE');
|
|
@@ -838,7 +942,7 @@ export async function coreDoctorReport(projectRoot: string): Promise<DoctorRepor
|
|
|
838
942
|
const warningCount = checks.filter((c) => c.status === 'warning').length;
|
|
839
943
|
const healthy = errorCount === 0;
|
|
840
944
|
|
|
841
|
-
return { healthy, errors: errorCount, warnings: warningCount, checks };
|
|
945
|
+
return { healthy, errors: errorCount, warnings: warningCount, checks, dependencies: depReport };
|
|
842
946
|
}
|
|
843
947
|
|
|
844
948
|
// ============================================================================
|
package/src/tasks/complete.ts
CHANGED
|
@@ -297,6 +297,46 @@ export async function completeTask(
|
|
|
297
297
|
/* Memory extraction is best-effort */
|
|
298
298
|
});
|
|
299
299
|
|
|
300
|
+
// Auto-populate brain graph nodes for the completed task (best-effort, T537).
|
|
301
|
+
// Runs SEPARATE from the gutted extractTaskCompletionMemory — this only writes
|
|
302
|
+
// graph topology, not memory table rows.
|
|
303
|
+
import('../memory/graph-auto-populate.js')
|
|
304
|
+
.then(({ upsertGraphNode, addGraphEdge }) =>
|
|
305
|
+
(async () => {
|
|
306
|
+
const projectRoot = cwd ?? process.cwd();
|
|
307
|
+
await upsertGraphNode(
|
|
308
|
+
projectRoot,
|
|
309
|
+
`task:${task.id}`,
|
|
310
|
+
'task',
|
|
311
|
+
`${task.id}: ${task.title}`.substring(0, 200),
|
|
312
|
+
1.0,
|
|
313
|
+
task.title,
|
|
314
|
+
{ status: 'done', priority: task.priority },
|
|
315
|
+
);
|
|
316
|
+
if (task.parentId) {
|
|
317
|
+
await upsertGraphNode(
|
|
318
|
+
projectRoot,
|
|
319
|
+
`epic:${task.parentId}`,
|
|
320
|
+
'epic',
|
|
321
|
+
task.parentId,
|
|
322
|
+
1.0,
|
|
323
|
+
'',
|
|
324
|
+
);
|
|
325
|
+
await addGraphEdge(
|
|
326
|
+
projectRoot,
|
|
327
|
+
`task:${task.id}`,
|
|
328
|
+
`epic:${task.parentId}`,
|
|
329
|
+
'part_of',
|
|
330
|
+
1.0,
|
|
331
|
+
'auto:task-complete',
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
})(),
|
|
335
|
+
)
|
|
336
|
+
.catch(() => {
|
|
337
|
+
/* Graph population is best-effort */
|
|
338
|
+
});
|
|
339
|
+
|
|
300
340
|
return {
|
|
301
341
|
task,
|
|
302
342
|
...(autoCompleted.length > 0 && { autoCompleted }),
|