hebbian 0.3.2 → 0.3.4
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/bin/hebbian.js +616 -117
- package/dist/bin/hebbian.js.map +1 -1
- package/dist/digest.d.ts +1 -1
- package/dist/digest.d.ts.map +1 -1
- package/dist/emit.d.ts.map +1 -1
- package/dist/evolve.d.ts +22 -0
- package/dist/evolve.d.ts.map +1 -0
- package/dist/grow.d.ts.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +307 -20
- package/dist/index.js.map +1 -1
- package/dist/update-check.d.ts +16 -0
- package/dist/update-check.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/digest.d.ts
CHANGED
package/dist/digest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,YAAY;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAwDD;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAYjG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAsD5G;AA6CD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,mBAAmB,EAAE,CAuB5E"}
|
package/dist/emit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAU,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAMxE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAuE7E;AAMD;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAuDzE;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAgDtD;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAmBpE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAY9F;
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAU,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAMxE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAuE7E;AAMD;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAuDzE;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAgDtD;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAmBpE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAY9F;AAoCD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAgCvE"}
|
package/dist/evolve.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Episode } from './episode';
|
|
2
|
+
import type { Brain } from './types';
|
|
3
|
+
export interface EvolveAction {
|
|
4
|
+
type: 'grow' | 'fire' | 'signal' | 'prune' | 'decay';
|
|
5
|
+
path: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
signal?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface EvolveResult {
|
|
10
|
+
actions: EvolveAction[];
|
|
11
|
+
executed: number;
|
|
12
|
+
skipped: number;
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function runEvolve(brainRoot: string, dryRun: boolean): Promise<EvolveResult>;
|
|
16
|
+
export declare function buildBrainSummary(brain: Brain): string;
|
|
17
|
+
export declare function buildPrompt(summary: string, episodes: Episode[]): string;
|
|
18
|
+
export declare function callGemini(prompt: string, apiKey: string): Promise<EvolveAction[]>;
|
|
19
|
+
export declare function parseActions(text: string): EvolveAction[];
|
|
20
|
+
export declare function validateActions(actions: EvolveAction[], _brain: Brain): EvolveAction[];
|
|
21
|
+
export declare function executeActions(brainRoot: string, actions: EvolveAction[]): number;
|
|
22
|
+
//# sourceMappingURL=evolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evolve.d.ts","sourceRoot":"","sources":["../src/evolve.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAWrC,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CAChB;AAUD,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CA+CzF;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAuBtD;AAID,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAsCxE;AAID,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAyDxF;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CA8BzD;AAID,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,GAAG,YAAY,EAAE,CAmBtF;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA8BjF"}
|
package/dist/grow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grow.d.ts","sourceRoot":"","sources":["../src/grow.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"grow.d.ts","sourceRoot":"","sources":["../src/grow.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAwC5E"}
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAkG1E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CA6CzD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAmD3D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,4 +27,6 @@ export type { HookStatus } from './hooks';
|
|
|
27
27
|
export { digestTranscript, extractCorrections, readHookInput } from './digest';
|
|
28
28
|
export type { DigestResult, ExtractedCorrection } from './digest';
|
|
29
29
|
export { resolveBrainRoot } from './constants';
|
|
30
|
+
export { runEvolve } from './evolve';
|
|
31
|
+
export type { EvolveAction, EvolveResult } from './evolve';
|
|
30
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG3G,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG3G,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -239,7 +239,7 @@ function runSubsumption(brain) {
|
|
|
239
239
|
|
|
240
240
|
// src/similarity.ts
|
|
241
241
|
function tokenize(name) {
|
|
242
|
-
return name.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[
|
|
242
|
+
return name.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9\u3000-\u9FFF\uAC00-\uD7AF]+/g, " ").toLowerCase().split(" ").map(stem).filter((t) => t.length > 1);
|
|
243
243
|
}
|
|
244
244
|
function stem(word) {
|
|
245
245
|
const suffixes = ["ing", "tion", "sion", "ness", "ment", "able", "ible", "ful", "less", "ous", "ive", "ity", "ies", "ed", "er", "es", "ly", "al", "en"];
|
|
@@ -376,10 +376,12 @@ function growNeuron(brainRoot, neuronPath) {
|
|
|
376
376
|
throw new Error(`Invalid region: ${regionName}. Valid: ${REGIONS.join(", ")}`);
|
|
377
377
|
}
|
|
378
378
|
const leafName = parts[parts.length - 1];
|
|
379
|
-
const
|
|
379
|
+
const newPrefix = leafName.match(/^(NO|DO|MUST|WARN)_/)?.[1] || "";
|
|
380
|
+
const newStripped = leafName.replace(/^(NO|DO|MUST|WARN)_/, "");
|
|
381
|
+
const newTokens = tokenize(newStripped);
|
|
380
382
|
const regionPath = join5(brainRoot, regionName);
|
|
381
383
|
if (existsSync5(regionPath)) {
|
|
382
|
-
const match = findSimilar(regionPath, regionPath, newTokens);
|
|
384
|
+
const match = findSimilar(regionPath, regionPath, newTokens, newPrefix);
|
|
383
385
|
if (match) {
|
|
384
386
|
const matchRelPath = regionName + "/" + relative2(regionPath, match);
|
|
385
387
|
console.log(`\u{1F504} consolidation: "${neuronPath}" \u2248 "${matchRelPath}" (firing existing)`);
|
|
@@ -392,7 +394,7 @@ function growNeuron(brainRoot, neuronPath) {
|
|
|
392
394
|
console.log(`\u{1F331} grew: ${neuronPath} (1)`);
|
|
393
395
|
return { action: "grew", path: neuronPath, counter: 1 };
|
|
394
396
|
}
|
|
395
|
-
function findSimilar(dir, regionRoot, targetTokens) {
|
|
397
|
+
function findSimilar(dir, regionRoot, targetTokens, targetPrefix) {
|
|
396
398
|
let entries;
|
|
397
399
|
try {
|
|
398
400
|
entries = readdirSync4(dir, { withFileTypes: true });
|
|
@@ -402,16 +404,19 @@ function findSimilar(dir, regionRoot, targetTokens) {
|
|
|
402
404
|
const hasNeuron = entries.some((e) => e.isFile() && e.name.endsWith(".neuron"));
|
|
403
405
|
if (hasNeuron) {
|
|
404
406
|
const folderName = dir.split("/").pop() || "";
|
|
405
|
-
const
|
|
407
|
+
const existingPrefix = folderName.match(/^(NO|DO|MUST|WARN)_/)?.[1] || "";
|
|
408
|
+
const existingStripped = folderName.replace(/^(NO|DO|MUST|WARN)_/, "");
|
|
409
|
+
const existingTokens = tokenize(existingStripped);
|
|
406
410
|
const similarity = jaccardSimilarity(targetTokens, existingTokens);
|
|
407
|
-
if (
|
|
411
|
+
if (targetPrefix !== existingPrefix && targetTokens.length <= 2) {
|
|
412
|
+
} else if (similarity >= JACCARD_THRESHOLD) {
|
|
408
413
|
return dir;
|
|
409
414
|
}
|
|
410
415
|
}
|
|
411
416
|
for (const entry of entries) {
|
|
412
417
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
413
418
|
if (entry.isDirectory()) {
|
|
414
|
-
const match = findSimilar(join5(dir, entry.name), regionRoot, targetTokens);
|
|
419
|
+
const match = findSimilar(join5(dir, entry.name), regionRoot, targetTokens, targetPrefix);
|
|
415
420
|
if (match) return match;
|
|
416
421
|
}
|
|
417
422
|
}
|
|
@@ -752,6 +757,8 @@ function writeTarget(filePath, content) {
|
|
|
752
757
|
writeFileSync6(filePath, before + content + after, "utf8");
|
|
753
758
|
return;
|
|
754
759
|
}
|
|
760
|
+
writeFileSync6(filePath, content + "\n\n" + existing, "utf8");
|
|
761
|
+
return;
|
|
755
762
|
}
|
|
756
763
|
writeFileSync6(filePath, content, "utf8");
|
|
757
764
|
}
|
|
@@ -1342,6 +1349,7 @@ function clearReports() {
|
|
|
1342
1349
|
|
|
1343
1350
|
// src/hooks.ts
|
|
1344
1351
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync10, existsSync as existsSync12, mkdirSync as mkdirSync7, readdirSync as readdirSync8 } from "fs";
|
|
1352
|
+
import { execSync as execSync2 } from "child_process";
|
|
1345
1353
|
import { join as join13, resolve as resolve2 } from "path";
|
|
1346
1354
|
var SETTINGS_DIR = ".claude";
|
|
1347
1355
|
var SETTINGS_FILE = "settings.local.json";
|
|
@@ -1355,6 +1363,11 @@ function installHooks(brainRoot, projectRoot) {
|
|
|
1355
1363
|
const settingsPath = join13(settingsDir, SETTINGS_FILE);
|
|
1356
1364
|
const defaultBrain = resolve2(root, "brain");
|
|
1357
1365
|
const brainFlag = resolvedBrain === defaultBrain ? "" : ` --brain ${resolvedBrain}`;
|
|
1366
|
+
let npxBin = "npx";
|
|
1367
|
+
try {
|
|
1368
|
+
npxBin = execSync2("which npx", { encoding: "utf8" }).trim();
|
|
1369
|
+
} catch {
|
|
1370
|
+
}
|
|
1358
1371
|
let settings = {};
|
|
1359
1372
|
if (existsSync12(settingsPath)) {
|
|
1360
1373
|
try {
|
|
@@ -1373,7 +1386,7 @@ function installHooks(brainRoot, projectRoot) {
|
|
|
1373
1386
|
matcher: "startup|resume",
|
|
1374
1387
|
entry: {
|
|
1375
1388
|
type: "command",
|
|
1376
|
-
command:
|
|
1389
|
+
command: `${npxBin} hebbian emit claude${brainFlag}`,
|
|
1377
1390
|
timeout: 10,
|
|
1378
1391
|
statusMessage: `${HOOK_MARKER} refreshing brain`
|
|
1379
1392
|
}
|
|
@@ -1382,7 +1395,7 @@ function installHooks(brainRoot, projectRoot) {
|
|
|
1382
1395
|
event: "Stop",
|
|
1383
1396
|
entry: {
|
|
1384
1397
|
type: "command",
|
|
1385
|
-
command:
|
|
1398
|
+
command: `${npxBin} hebbian digest${brainFlag}`,
|
|
1386
1399
|
timeout: 30,
|
|
1387
1400
|
statusMessage: `${HOOK_MARKER} digesting session`
|
|
1388
1401
|
}
|
|
@@ -1410,8 +1423,8 @@ function installHooks(brainRoot, projectRoot) {
|
|
|
1410
1423
|
}
|
|
1411
1424
|
writeFileSync10(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
1412
1425
|
console.log(`\u2705 hebbian hooks installed at ${settingsPath}`);
|
|
1413
|
-
console.log(` SessionStart \u2192 hebbian emit claude${brainFlag}`);
|
|
1414
|
-
console.log(` Stop \u2192 hebbian digest${brainFlag}`);
|
|
1426
|
+
console.log(` SessionStart \u2192 ${npxBin} hebbian emit claude${brainFlag}`);
|
|
1427
|
+
console.log(` Stop \u2192 ${npxBin} hebbian digest${brainFlag}`);
|
|
1415
1428
|
}
|
|
1416
1429
|
function uninstallHooks(projectRoot) {
|
|
1417
1430
|
const root = projectRoot || process.cwd();
|
|
@@ -1523,13 +1536,24 @@ var NEGATION_PATTERNS = [
|
|
|
1523
1536
|
];
|
|
1524
1537
|
var AFFIRMATION_PATTERNS = [
|
|
1525
1538
|
/\balways\b/i,
|
|
1526
|
-
/\bmust\b/i,
|
|
1527
1539
|
/\bshould\s+always\b/i,
|
|
1528
1540
|
/\buse\s+\w+\s+instead\b/i,
|
|
1529
1541
|
// Korean affirmation
|
|
1530
|
-
|
|
1542
|
+
/항상/
|
|
1543
|
+
];
|
|
1544
|
+
var MUST_PATTERNS = [
|
|
1545
|
+
/\bmust\b/i,
|
|
1546
|
+
/\brequired\b/i,
|
|
1547
|
+
// Korean
|
|
1531
1548
|
/반드시/
|
|
1532
1549
|
];
|
|
1550
|
+
var WARN_PATTERNS = [
|
|
1551
|
+
/\bcareful\b/i,
|
|
1552
|
+
/\bwatch\s+out\b/i,
|
|
1553
|
+
/\bwarning\b/i,
|
|
1554
|
+
// Korean
|
|
1555
|
+
/주의/
|
|
1556
|
+
];
|
|
1533
1557
|
function readHookInput(stdin) {
|
|
1534
1558
|
if (!stdin.trim()) return null;
|
|
1535
1559
|
try {
|
|
@@ -1626,17 +1650,24 @@ function extractCorrections(messages) {
|
|
|
1626
1650
|
}
|
|
1627
1651
|
function detectCorrection(text) {
|
|
1628
1652
|
const isNegation = NEGATION_PATTERNS.some((p) => p.test(text));
|
|
1653
|
+
const isMust = MUST_PATTERNS.some((p) => p.test(text));
|
|
1654
|
+
const isWarn = WARN_PATTERNS.some((p) => p.test(text));
|
|
1629
1655
|
const isAffirmation = AFFIRMATION_PATTERNS.some((p) => p.test(text));
|
|
1630
|
-
if (!isNegation && !isAffirmation) return null;
|
|
1631
|
-
|
|
1656
|
+
if (!isNegation && !isMust && !isWarn && !isAffirmation) return null;
|
|
1657
|
+
let prefix;
|
|
1658
|
+
if (isNegation) prefix = "NO";
|
|
1659
|
+
else if (isMust) prefix = "MUST";
|
|
1660
|
+
else if (isWarn) prefix = "WARN";
|
|
1661
|
+
else prefix = "DO";
|
|
1632
1662
|
const keywords = extractKeywords(text);
|
|
1633
1663
|
if (keywords.length === 0) return null;
|
|
1634
|
-
const pathSegment = `${prefix}_${keywords.slice(0,
|
|
1664
|
+
const pathSegment = `${prefix}_${keywords.slice(0, 3).join("_")}`;
|
|
1635
1665
|
const path = `cortex/${pathSegment}`;
|
|
1636
1666
|
return { text, path, prefix, keywords };
|
|
1637
1667
|
}
|
|
1638
1668
|
function extractKeywords(text) {
|
|
1639
1669
|
const STOP_WORDS = /* @__PURE__ */ new Set([
|
|
1670
|
+
// English stop words
|
|
1640
1671
|
"the",
|
|
1641
1672
|
"a",
|
|
1642
1673
|
"an",
|
|
@@ -1718,7 +1749,6 @@ function extractKeywords(text) {
|
|
|
1718
1749
|
"those",
|
|
1719
1750
|
"it",
|
|
1720
1751
|
"its",
|
|
1721
|
-
"i",
|
|
1722
1752
|
"me",
|
|
1723
1753
|
"my",
|
|
1724
1754
|
"we",
|
|
@@ -1747,10 +1777,33 @@ function extractKeywords(text) {
|
|
|
1747
1777
|
"should",
|
|
1748
1778
|
"like",
|
|
1749
1779
|
"want",
|
|
1750
|
-
"think"
|
|
1780
|
+
"think",
|
|
1781
|
+
"way",
|
|
1782
|
+
"make",
|
|
1783
|
+
"sure",
|
|
1784
|
+
"keep",
|
|
1785
|
+
"try",
|
|
1786
|
+
"let",
|
|
1787
|
+
"get",
|
|
1788
|
+
"put",
|
|
1789
|
+
"set",
|
|
1790
|
+
"new",
|
|
1791
|
+
"also",
|
|
1792
|
+
"using",
|
|
1793
|
+
"used",
|
|
1794
|
+
"when",
|
|
1795
|
+
"where",
|
|
1796
|
+
"how",
|
|
1797
|
+
"why",
|
|
1798
|
+
"here",
|
|
1799
|
+
"there",
|
|
1800
|
+
"careful",
|
|
1801
|
+
"warning",
|
|
1802
|
+
"watch",
|
|
1803
|
+
"out",
|
|
1804
|
+
"required"
|
|
1751
1805
|
]);
|
|
1752
|
-
|
|
1753
|
-
return tokens.filter((t) => !STOP_WORDS.has(t) && t.length > 2);
|
|
1806
|
+
return text.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-zA-Z0-9\u3000-\u9FFF\uAC00-\uD7AF]+/g, " ").toLowerCase().split(/\s+/).filter((t) => t.length > 2 && !STOP_WORDS.has(t));
|
|
1754
1807
|
}
|
|
1755
1808
|
function writeAuditLog(brainRoot, sessionId, entries) {
|
|
1756
1809
|
const logDir = join14(brainRoot, DIGEST_LOG_DIR);
|
|
@@ -1770,6 +1823,239 @@ function writeAuditLog(brainRoot, sessionId, entries) {
|
|
|
1770
1823
|
);
|
|
1771
1824
|
writeFileSync11(logPath, lines.join("\n") + (lines.length > 0 ? "\n" : ""), "utf8");
|
|
1772
1825
|
}
|
|
1826
|
+
|
|
1827
|
+
// src/evolve.ts
|
|
1828
|
+
var MAX_ACTIONS = 10;
|
|
1829
|
+
var PROTECTED_REGIONS = ["brainstem", "limbic", "sensors"];
|
|
1830
|
+
var DEFAULT_MODEL = "gemini-2.0-flash-lite";
|
|
1831
|
+
var API_TIMEOUT = 3e4;
|
|
1832
|
+
var RETRY_DELAY = 5e3;
|
|
1833
|
+
async function runEvolve(brainRoot, dryRun) {
|
|
1834
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
1835
|
+
if (!apiKey) {
|
|
1836
|
+
console.error("\u274C GEMINI_API_KEY not set. Get one at https://aistudio.google.com/apikey");
|
|
1837
|
+
return { actions: [], executed: 0, skipped: 0, dryRun };
|
|
1838
|
+
}
|
|
1839
|
+
const episodes = readEpisodes(brainRoot);
|
|
1840
|
+
const brain = scanBrain(brainRoot);
|
|
1841
|
+
const summary = buildBrainSummary(brain);
|
|
1842
|
+
const prompt = buildPrompt(summary, episodes);
|
|
1843
|
+
let rawActions;
|
|
1844
|
+
try {
|
|
1845
|
+
rawActions = await callGemini(prompt, apiKey);
|
|
1846
|
+
} catch (err) {
|
|
1847
|
+
const msg = err.message;
|
|
1848
|
+
console.log(`\u23ED\uFE0F evolve skipped: ${msg}`);
|
|
1849
|
+
logEpisode(brainRoot, "evolve-error", "", msg);
|
|
1850
|
+
return { actions: [], executed: 0, skipped: 0, dryRun };
|
|
1851
|
+
}
|
|
1852
|
+
const actions = validateActions(rawActions, brain);
|
|
1853
|
+
const skipped = rawActions.length - actions.length;
|
|
1854
|
+
if (actions.length === 0) {
|
|
1855
|
+
console.log("\u{1F9E0} evolve: no valid actions proposed");
|
|
1856
|
+
return { actions: [], executed: 0, skipped, dryRun };
|
|
1857
|
+
}
|
|
1858
|
+
if (dryRun) {
|
|
1859
|
+
console.log(`\u{1F9E0} evolve (dry-run): ${actions.length} action(s) proposed`);
|
|
1860
|
+
for (const action of actions) {
|
|
1861
|
+
console.log(` ${actionIcon(action.type)} ${action.type} ${action.path} \u2014 ${action.reason}`);
|
|
1862
|
+
}
|
|
1863
|
+
return { actions, executed: 0, skipped, dryRun: true };
|
|
1864
|
+
}
|
|
1865
|
+
const executed = executeActions(brainRoot, actions);
|
|
1866
|
+
logEpisode(brainRoot, "evolve", "", `${executed} action(s) executed, ${skipped} skipped`);
|
|
1867
|
+
console.log(`\u{1F9E0} evolve: ${executed} action(s) executed, ${skipped} skipped`);
|
|
1868
|
+
return { actions, executed, skipped, dryRun: false };
|
|
1869
|
+
}
|
|
1870
|
+
function buildBrainSummary(brain) {
|
|
1871
|
+
const lines = ["# Brain State\n"];
|
|
1872
|
+
for (const region of brain.regions) {
|
|
1873
|
+
const neurons = region.neurons;
|
|
1874
|
+
if (neurons.length === 0 && !region.hasBomb) continue;
|
|
1875
|
+
lines.push(`## ${region.name} (P${REGION_PRIORITY[region.name]})`);
|
|
1876
|
+
if (region.hasBomb) lines.push("\u26A0\uFE0F BOMB active \u2014 region blocked");
|
|
1877
|
+
for (const neuron of neurons) {
|
|
1878
|
+
const flags = [];
|
|
1879
|
+
if (neuron.isDormant) flags.push("dormant");
|
|
1880
|
+
if (neuron.hasBomb) flags.push("bomb");
|
|
1881
|
+
if (neuron.hasMemory) flags.push("memory");
|
|
1882
|
+
if (neuron.dopamine > 0) flags.push(`dopamine:${neuron.dopamine}`);
|
|
1883
|
+
const flagStr = flags.length > 0 ? ` [${flags.join(", ")}]` : "";
|
|
1884
|
+
lines.push(`- ${neuron.path} (counter:${neuron.counter}, intensity:${neuron.intensity})${flagStr}`);
|
|
1885
|
+
}
|
|
1886
|
+
lines.push("");
|
|
1887
|
+
}
|
|
1888
|
+
return lines.join("\n");
|
|
1889
|
+
}
|
|
1890
|
+
function buildPrompt(summary, episodes) {
|
|
1891
|
+
const episodeLines = episodes.length > 0 ? episodes.map((e) => `- [${e.ts}] ${e.type}: ${e.path} \u2014 ${e.detail}`).join("\n") : "(no recent episodes)";
|
|
1892
|
+
return `You are the evolve engine for a hebbian brain \u2014 a filesystem-based memory system for AI agents.
|
|
1893
|
+
|
|
1894
|
+
## Axioms
|
|
1895
|
+
- Folder = Neuron, File = Firing Trace, Counter = Activation strength
|
|
1896
|
+
- 7 regions in subsumption cascade: brainstem(P0) > limbic(P1) > hippocampus(P2) > sensors(P3) > cortex(P4) > ego(P5) > prefrontal(P6)
|
|
1897
|
+
- Lower priority ALWAYS overrides higher priority
|
|
1898
|
+
- PROTECTED regions (brainstem, limbic, sensors): NEVER propose mutations for these
|
|
1899
|
+
|
|
1900
|
+
## Current Brain
|
|
1901
|
+
${summary}
|
|
1902
|
+
|
|
1903
|
+
## Recent Episodes (last ${episodes.length})
|
|
1904
|
+
${episodeLines}
|
|
1905
|
+
|
|
1906
|
+
## Available Actions
|
|
1907
|
+
- grow: Create a new neuron at the given path (region/name). Use for recurring patterns that deserve permanent memory.
|
|
1908
|
+
- fire: Increment an existing neuron's counter. Use for strengthening well-confirmed rules.
|
|
1909
|
+
- signal: Add dopamine (reward), bomb (block), or memory signal. Use sparingly.
|
|
1910
|
+
- prune: Decrement a neuron's counter. Use for rules that aren't working or cause issues.
|
|
1911
|
+
- decay: Mark inactive neurons as dormant. Use for stale rules with no recent activity.
|
|
1912
|
+
|
|
1913
|
+
## Constraints
|
|
1914
|
+
- Max ${MAX_ACTIONS} actions per cycle
|
|
1915
|
+
- PREFER fire over grow \u2014 strengthen existing neurons before creating new ones
|
|
1916
|
+
- NEVER target brainstem, limbic, or sensors regions
|
|
1917
|
+
- Each action needs a "reason" explaining why
|
|
1918
|
+
|
|
1919
|
+
## Task
|
|
1920
|
+
Analyze the brain state and recent episodes. Propose actions to improve the brain.
|
|
1921
|
+
Focus on: strengthening repeatedly-used rules, pruning ineffective ones, growing new neurons from repeated patterns.
|
|
1922
|
+
|
|
1923
|
+
Respond with a JSON array of actions:
|
|
1924
|
+
[{"type":"fire","path":"cortex/NO_console_log","reason":"fired 3 times in recent sessions"}]`;
|
|
1925
|
+
}
|
|
1926
|
+
async function callGemini(prompt, apiKey) {
|
|
1927
|
+
const model = process.env.EVOLVE_MODEL || DEFAULT_MODEL;
|
|
1928
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
|
|
1929
|
+
const body = {
|
|
1930
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
1931
|
+
generationConfig: {
|
|
1932
|
+
responseMimeType: "application/json",
|
|
1933
|
+
temperature: 0.2
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
let lastError = null;
|
|
1937
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1938
|
+
if (attempt > 0) {
|
|
1939
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY));
|
|
1940
|
+
}
|
|
1941
|
+
try {
|
|
1942
|
+
const res = await fetch(url, {
|
|
1943
|
+
method: "POST",
|
|
1944
|
+
headers: { "Content-Type": "application/json" },
|
|
1945
|
+
body: JSON.stringify(body),
|
|
1946
|
+
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
1947
|
+
});
|
|
1948
|
+
if (!res.ok) {
|
|
1949
|
+
lastError = new Error(`Gemini API ${res.status}: ${res.statusText}`);
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
const data = await res.json();
|
|
1953
|
+
if (data.error) {
|
|
1954
|
+
lastError = new Error(`Gemini error: ${data.error.message || "unknown"}`);
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
1958
|
+
if (!text) {
|
|
1959
|
+
lastError = new Error("Gemini returned empty response");
|
|
1960
|
+
continue;
|
|
1961
|
+
}
|
|
1962
|
+
return parseActions(text);
|
|
1963
|
+
} catch (err) {
|
|
1964
|
+
lastError = err;
|
|
1965
|
+
continue;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
throw lastError || new Error("Gemini call failed");
|
|
1969
|
+
}
|
|
1970
|
+
function parseActions(text) {
|
|
1971
|
+
let parsed;
|
|
1972
|
+
try {
|
|
1973
|
+
parsed = JSON.parse(text);
|
|
1974
|
+
} catch {
|
|
1975
|
+
throw new Error(`Failed to parse LLM response as JSON: ${text.slice(0, 100)}`);
|
|
1976
|
+
}
|
|
1977
|
+
if (!Array.isArray(parsed)) {
|
|
1978
|
+
throw new Error("LLM response is not an array");
|
|
1979
|
+
}
|
|
1980
|
+
const validTypes = /* @__PURE__ */ new Set(["grow", "fire", "signal", "prune", "decay"]);
|
|
1981
|
+
const actions = [];
|
|
1982
|
+
for (const item of parsed) {
|
|
1983
|
+
if (!item || typeof item !== "object") continue;
|
|
1984
|
+
const { type, path, reason, signal } = item;
|
|
1985
|
+
if (typeof type !== "string" || !validTypes.has(type)) continue;
|
|
1986
|
+
if (typeof path !== "string" || path.length === 0) continue;
|
|
1987
|
+
if (typeof reason !== "string") continue;
|
|
1988
|
+
const action = { type, path, reason };
|
|
1989
|
+
if (type === "signal" && typeof signal === "string") {
|
|
1990
|
+
action.signal = signal;
|
|
1991
|
+
}
|
|
1992
|
+
actions.push(action);
|
|
1993
|
+
}
|
|
1994
|
+
return actions;
|
|
1995
|
+
}
|
|
1996
|
+
function validateActions(actions, _brain) {
|
|
1997
|
+
return actions.filter((action) => {
|
|
1998
|
+
const region = action.path.split("/")[0];
|
|
1999
|
+
if (!region || PROTECTED_REGIONS.includes(region)) {
|
|
2000
|
+
console.log(` \u{1F6E1}\uFE0F blocked: ${action.type} ${action.path} (protected region)`);
|
|
2001
|
+
return false;
|
|
2002
|
+
}
|
|
2003
|
+
if (!REGIONS.includes(region)) {
|
|
2004
|
+
console.log(` \u26A0\uFE0F skipped: ${action.type} ${action.path} (invalid region)`);
|
|
2005
|
+
return false;
|
|
2006
|
+
}
|
|
2007
|
+
if (action.type === "signal" && action.signal && !["dopamine", "bomb", "memory"].includes(action.signal)) {
|
|
2008
|
+
console.log(` \u26A0\uFE0F skipped: signal ${action.path} (invalid signal type: ${action.signal})`);
|
|
2009
|
+
return false;
|
|
2010
|
+
}
|
|
2011
|
+
return true;
|
|
2012
|
+
}).slice(0, MAX_ACTIONS);
|
|
2013
|
+
}
|
|
2014
|
+
function executeActions(brainRoot, actions) {
|
|
2015
|
+
let executed = 0;
|
|
2016
|
+
for (const action of actions) {
|
|
2017
|
+
try {
|
|
2018
|
+
switch (action.type) {
|
|
2019
|
+
case "fire":
|
|
2020
|
+
fireNeuron(brainRoot, action.path);
|
|
2021
|
+
break;
|
|
2022
|
+
case "grow":
|
|
2023
|
+
growNeuron(brainRoot, action.path);
|
|
2024
|
+
break;
|
|
2025
|
+
case "signal":
|
|
2026
|
+
signalNeuron(brainRoot, action.path, action.signal || "dopamine");
|
|
2027
|
+
break;
|
|
2028
|
+
case "prune":
|
|
2029
|
+
rollbackNeuron(brainRoot, action.path);
|
|
2030
|
+
break;
|
|
2031
|
+
case "decay":
|
|
2032
|
+
runDecay(brainRoot, 0);
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
console.log(` ${actionIcon(action.type)} ${action.type} ${action.path}`);
|
|
2036
|
+
executed++;
|
|
2037
|
+
} catch (err) {
|
|
2038
|
+
console.log(` \u26A0\uFE0F failed: ${action.type} ${action.path} \u2014 ${err.message}`);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
return executed;
|
|
2042
|
+
}
|
|
2043
|
+
function actionIcon(type) {
|
|
2044
|
+
switch (type) {
|
|
2045
|
+
case "fire":
|
|
2046
|
+
return "\u{1F525}";
|
|
2047
|
+
case "grow":
|
|
2048
|
+
return "\u{1F331}";
|
|
2049
|
+
case "signal":
|
|
2050
|
+
return "\u26A1";
|
|
2051
|
+
case "prune":
|
|
2052
|
+
return "\u2702\uFE0F";
|
|
2053
|
+
case "decay":
|
|
2054
|
+
return "\u{1F4A4}";
|
|
2055
|
+
default:
|
|
2056
|
+
return "\u2753";
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1773
2059
|
export {
|
|
1774
2060
|
DECAY_DAYS,
|
|
1775
2061
|
DIGEST_LOG_DIR,
|
|
@@ -1816,6 +2102,7 @@ export {
|
|
|
1816
2102
|
rollbackNeuron,
|
|
1817
2103
|
runDecay,
|
|
1818
2104
|
runDedup,
|
|
2105
|
+
runEvolve,
|
|
1819
2106
|
runSubsumption,
|
|
1820
2107
|
scanBrain,
|
|
1821
2108
|
signalNeuron,
|