hebbian 0.5.3 → 0.7.0
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 +228 -41
- package/dist/bin/hebbian.js.map +1 -1
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/digest.d.ts +47 -0
- package/dist/digest.d.ts.map +1 -1
- package/dist/evolve.d.ts +2 -1
- package/dist/evolve.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +177 -24
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/constants.d.ts
CHANGED
|
@@ -23,4 +23,10 @@ export declare const SESSION_STATE_DIR = "hippocampus/session_state";
|
|
|
23
23
|
export declare const PROTECTED_REGIONS_CONTRA: string[];
|
|
24
24
|
/** Resolve brain root path from flag, env var, or defaults */
|
|
25
25
|
export declare function resolveBrainRoot(brainFlag?: string): string;
|
|
26
|
+
/** Resolve agent-specific brain path within a multi-brain setup */
|
|
27
|
+
export declare function resolveAgentBrain(brainRoot: string, agentName: string): string;
|
|
28
|
+
/** Resolve shared brain path within a multi-brain setup */
|
|
29
|
+
export declare function resolveSharedBrain(brainRoot: string): string;
|
|
30
|
+
export declare const AGENTS_DIR = "agents";
|
|
31
|
+
export declare const SHARED_DIR = "shared";
|
|
26
32
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,OAAO,2FAQV,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQtD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQnD,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQhD,CAAC;AAEF,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM/C,CAAC;AAEF,eAAO,MAAM,YAAY,yCAA0C,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,YAAY,2BAA2B,CAAC;AACrD,eAAO,MAAM,UAAU,yBAAyB,CAAC;AAGjD,eAAO,MAAM,WAAW,cAAc,CAAC;AAGvC,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAGvD,eAAO,MAAM,aAAa,mCAAoC,CAAC;AAC/D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAC7D,eAAO,MAAM,wBAAwB,UAAqC,CAAC;AAK3E,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAK3D"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,OAAO,2FAQV,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQtD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQnD,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQhD,CAAC;AAEF,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM/C,CAAC;AAEF,eAAO,MAAM,YAAY,yCAA0C,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,YAAY,2BAA2B,CAAC;AACrD,eAAO,MAAM,UAAU,yBAAyB,CAAC;AAGjD,eAAO,MAAM,WAAW,cAAc,CAAC;AAGvC,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAGvD,eAAO,MAAM,aAAa,mCAAoC,CAAC;AAC/D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAC7D,eAAO,MAAM,wBAAwB,UAAqC,CAAC;AAK3E,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,eAAO,MAAM,UAAU,WAAW,CAAC;AACnC,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/dist/digest.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface DigestResult {
|
|
2
2
|
corrections: number;
|
|
3
3
|
skipped: number;
|
|
4
|
+
toolFailures: number;
|
|
4
5
|
transcriptPath: string;
|
|
5
6
|
sessionId: string;
|
|
6
7
|
}
|
|
@@ -10,6 +11,30 @@ export interface ExtractedCorrection {
|
|
|
10
11
|
prefix: 'NO' | 'DO' | 'MUST' | 'WARN';
|
|
11
12
|
keywords: string[];
|
|
12
13
|
}
|
|
14
|
+
interface TranscriptLine {
|
|
15
|
+
type?: string;
|
|
16
|
+
message?: {
|
|
17
|
+
role?: string;
|
|
18
|
+
content?: string | Array<{
|
|
19
|
+
type: string;
|
|
20
|
+
text?: string;
|
|
21
|
+
tool_use_id?: string;
|
|
22
|
+
is_error?: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
25
|
+
toolUseResult?: {
|
|
26
|
+
stdout?: string;
|
|
27
|
+
stderr?: string;
|
|
28
|
+
status?: string;
|
|
29
|
+
};
|
|
30
|
+
sessionId?: string;
|
|
31
|
+
uuid?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ToolFailure {
|
|
34
|
+
toolName: string;
|
|
35
|
+
exitCode: number;
|
|
36
|
+
errorText: string;
|
|
37
|
+
}
|
|
13
38
|
/**
|
|
14
39
|
* Parse hook input from stdin to extract transcript path and session ID.
|
|
15
40
|
*/
|
|
@@ -22,9 +47,31 @@ export declare function readHookInput(stdin: string): {
|
|
|
22
47
|
* Auto-processes inbox and writes audit log.
|
|
23
48
|
*/
|
|
24
49
|
export declare function digestTranscript(brainRoot: string, transcriptPath: string, sessionId?: string): DigestResult;
|
|
50
|
+
/**
|
|
51
|
+
* Parse tool_result blocks from a Claude Code transcript.
|
|
52
|
+
* Returns detected failures (exit code ≠ 0, is_error = true).
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseToolResults(transcriptPath: string): ToolFailure[];
|
|
55
|
+
/**
|
|
56
|
+
* Detect retry patterns — same error appearing 3+ times in a session.
|
|
57
|
+
* Returns deduplicated failures with retry count.
|
|
58
|
+
*/
|
|
59
|
+
export declare function detectRetryPatterns(failures: ToolFailure[]): ToolFailure[];
|
|
60
|
+
/**
|
|
61
|
+
* Detect a tool failure from a tool_result block.
|
|
62
|
+
* Returns failure info if exit code ≠ 0, null otherwise.
|
|
63
|
+
*/
|
|
64
|
+
export declare function detectToolFailure(block: {
|
|
65
|
+
content?: string | Array<{
|
|
66
|
+
type: string;
|
|
67
|
+
text?: string;
|
|
68
|
+
}>;
|
|
69
|
+
is_error?: boolean;
|
|
70
|
+
}, toolUseResult?: TranscriptLine['toolUseResult']): ToolFailure | null;
|
|
25
71
|
/**
|
|
26
72
|
* Extract corrections from user messages using pattern matching.
|
|
27
73
|
* Returns up to MAX_CORRECTIONS_PER_SESSION corrections.
|
|
28
74
|
*/
|
|
29
75
|
export declare function extractCorrections(messages: string[]): ExtractedCorrection[];
|
|
76
|
+
export {};
|
|
30
77
|
//# sourceMappingURL=digest.d.ts.map
|
package/dist/digest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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,YAAY,EAAE,MAAM,CAAC;IACrB,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;AAED,UAAU,cAAc;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KACpG,CAAC;IACF,aAAa,CAAC,EAAE;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AA+CD;;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,CA8E5G;AAiDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,EAAE,CA4BtE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAoB1E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,EACxF,aAAa,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,GAC7C,WAAW,GAAG,IAAI,CA8BpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,mBAAmB,EAAE,CAiC5E"}
|
package/dist/evolve.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export interface EvolveResult {
|
|
|
12
12
|
skipped: number;
|
|
13
13
|
dryRun: boolean;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
15
|
+
export type EvolveMode = 'default' | 'prune';
|
|
16
|
+
export declare function runEvolve(brainRoot: string, dryRun: boolean, mode?: EvolveMode): Promise<EvolveResult>;
|
|
16
17
|
export declare function buildBrainSummary(brain: Brain): string;
|
|
17
18
|
export declare function buildPrompt(summary: string, episodes: Episode[], outcomeSummary?: string): string;
|
|
18
19
|
export declare function callGemini(prompt: string, apiKey: string): Promise<EvolveAction[]>;
|
package/dist/evolve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evolve.d.ts","sourceRoot":"","sources":["../src/evolve.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAYrC,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;AAWD,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"evolve.d.ts","sourceRoot":"","sources":["../src/evolve.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAYrC,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;AAWD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7C,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAE,UAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoEvH;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAuBtD;AAeD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAyCjG;AAgDD,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,CAwBtF;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA8BjF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -24,13 +24,13 @@ export { processInbox, ensureInbox, appendCorrection } from './inbox';
|
|
|
24
24
|
export type { Correction, InboxResult } from './inbox';
|
|
25
25
|
export { installHooks, uninstallHooks, checkHooks } from './hooks';
|
|
26
26
|
export type { HookStatus } from './hooks';
|
|
27
|
-
export { digestTranscript, extractCorrections, readHookInput } from './digest';
|
|
28
|
-
export type { DigestResult, ExtractedCorrection } from './digest';
|
|
29
|
-
export { resolveBrainRoot } from './constants';
|
|
27
|
+
export { digestTranscript, extractCorrections, readHookInput, parseToolResults, detectToolFailure, detectRetryPatterns } from './digest';
|
|
28
|
+
export type { DigestResult, ExtractedCorrection, ToolFailure } from './digest';
|
|
29
|
+
export { resolveBrainRoot, resolveAgentBrain, resolveSharedBrain } from './constants';
|
|
30
30
|
export { growCandidate, promoteCandidates, listCandidates, toCandidatePath, fromCandidatePath } from './candidates';
|
|
31
31
|
export type { CandidateInfo, PromoteResult } from './candidates';
|
|
32
32
|
export { runEvolve } from './evolve';
|
|
33
|
-
export type { EvolveAction, EvolveResult } from './evolve';
|
|
33
|
+
export type { EvolveAction, EvolveResult, EvolveMode } from './evolve';
|
|
34
34
|
export { captureSessionStart, detectOutcome, buildOutcomeSummary, classifyOutcome } from './outcome';
|
|
35
35
|
export type { SessionState, OutcomeResult } from './outcome';
|
|
36
36
|
export { contraNeuron } from './fire';
|
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;
|
|
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,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACzI,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACpH,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGvE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACrG,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -65,6 +65,14 @@ function resolveBrainRoot(brainFlag) {
|
|
|
65
65
|
if (existsSync(resolve("./brain"))) return resolve("./brain");
|
|
66
66
|
return resolve(process.env.HOME || "~", "hebbian", "brain");
|
|
67
67
|
}
|
|
68
|
+
function resolveAgentBrain(brainRoot, agentName) {
|
|
69
|
+
return resolve(brainRoot, "agents", agentName);
|
|
70
|
+
}
|
|
71
|
+
function resolveSharedBrain(brainRoot) {
|
|
72
|
+
return resolve(brainRoot, "shared");
|
|
73
|
+
}
|
|
74
|
+
var AGENTS_DIR = "agents";
|
|
75
|
+
var SHARED_DIR = "shared";
|
|
68
76
|
|
|
69
77
|
// src/scanner.ts
|
|
70
78
|
import { readdirSync, statSync, readFileSync, existsSync as existsSync2 } from "fs";
|
|
@@ -882,8 +890,8 @@ function computeHash(result) {
|
|
|
882
890
|
}
|
|
883
891
|
|
|
884
892
|
// src/init.ts
|
|
885
|
-
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, existsSync as existsSync9, readdirSync as readdirSync6 } from "fs";
|
|
886
|
-
import { join as join10 } from "path";
|
|
893
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, readFileSync as readFileSync3, existsSync as existsSync9, readdirSync as readdirSync6, appendFileSync } from "fs";
|
|
894
|
+
import { join as join10, dirname as dirname2 } from "path";
|
|
887
895
|
var REGION_TEMPLATES = {
|
|
888
896
|
brainstem: {
|
|
889
897
|
description: "Absolute principles. Immutable. Read-only conscience.\nP0 \u2014 highest priority. bomb here halts EVERYTHING.",
|
|
@@ -944,6 +952,7 @@ ${template.description}
|
|
|
944
952
|
}
|
|
945
953
|
}
|
|
946
954
|
mkdirSync4(join10(brainPath, "_agents", "global_inbox"), { recursive: true });
|
|
955
|
+
autoGitignore(brainPath);
|
|
947
956
|
console.log(`\u{1F9E0} Brain initialized at ${brainPath}`);
|
|
948
957
|
console.log(` 7 regions created: ${REGIONS.join(", ")}`);
|
|
949
958
|
console.log("");
|
|
@@ -951,17 +960,41 @@ ${template.description}
|
|
|
951
960
|
console.log(` hebbian grow brainstem/NO_your_rule --brain ${brainPath}`);
|
|
952
961
|
console.log(` hebbian emit claude --brain ${brainPath}`);
|
|
953
962
|
}
|
|
963
|
+
function autoGitignore(brainPath) {
|
|
964
|
+
let dir = dirname2(brainPath);
|
|
965
|
+
for (let i = 0; i < 10; i++) {
|
|
966
|
+
if (existsSync9(join10(dir, ".git"))) {
|
|
967
|
+
const gitignorePath = join10(dir, ".gitignore");
|
|
968
|
+
const brainDirName = brainPath.replace(dir + "/", "") + "/";
|
|
969
|
+
if (existsSync9(gitignorePath)) {
|
|
970
|
+
const content = readFileSync3(gitignorePath, "utf8");
|
|
971
|
+
if (content.includes(brainDirName) || content.includes(brainDirName.replace(/\/$/, ""))) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
appendFileSync(gitignorePath, `
|
|
976
|
+
# hebbian brain (personal learning data)
|
|
977
|
+
${brainDirName}
|
|
978
|
+
`, "utf8");
|
|
979
|
+
console.log(` \u{1F4DD} Added ${brainDirName} to .gitignore`);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const parent = dirname2(dir);
|
|
983
|
+
if (parent === dir) break;
|
|
984
|
+
dir = parent;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
954
987
|
|
|
955
988
|
// src/api.ts
|
|
956
989
|
import { createServer } from "http";
|
|
957
990
|
|
|
958
991
|
// src/inbox.ts
|
|
959
|
-
import { readFileSync as
|
|
992
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync9, existsSync as existsSync12, mkdirSync as mkdirSync7 } from "fs";
|
|
960
993
|
import { join as join13 } from "path";
|
|
961
994
|
|
|
962
995
|
// src/candidates.ts
|
|
963
996
|
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync7, renameSync as renameSync3, rmSync, statSync as statSync3 } from "fs";
|
|
964
|
-
import { join as join11, dirname as
|
|
997
|
+
import { join as join11, dirname as dirname3, relative as relative3 } from "path";
|
|
965
998
|
var CANDIDATE_THRESHOLD = 3;
|
|
966
999
|
var CANDIDATE_DECAY_DAYS = 14;
|
|
967
1000
|
var CANDIDATE_SEGMENT = "_candidates";
|
|
@@ -991,7 +1024,7 @@ function moveCandidate(brainRoot, candidatePath, targetPath) {
|
|
|
991
1024
|
fireNeuron(brainRoot, targetPath);
|
|
992
1025
|
rmSync(src, { recursive: true, force: true });
|
|
993
1026
|
} else {
|
|
994
|
-
mkdirSync5(
|
|
1027
|
+
mkdirSync5(dirname3(dst), { recursive: true });
|
|
995
1028
|
renameSync3(src, dst);
|
|
996
1029
|
}
|
|
997
1030
|
console.log(`\u{1F393} promoted: ${candidatePath} \u2192 ${targetPath}`);
|
|
@@ -1067,7 +1100,7 @@ function readCounter(dir) {
|
|
|
1067
1100
|
}
|
|
1068
1101
|
|
|
1069
1102
|
// src/episode.ts
|
|
1070
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
1103
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync4, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, existsSync as existsSync11 } from "fs";
|
|
1071
1104
|
import { join as join12 } from "path";
|
|
1072
1105
|
var MAX_EPISODES = 100;
|
|
1073
1106
|
var SESSION_LOG_DIR = "hippocampus/session_log";
|
|
@@ -1104,7 +1137,7 @@ function readEpisodes(brainRoot) {
|
|
|
1104
1137
|
for (const entry of entries) {
|
|
1105
1138
|
if (!entry.startsWith("memory") || !entry.endsWith(".neuron")) continue;
|
|
1106
1139
|
try {
|
|
1107
|
-
const content =
|
|
1140
|
+
const content = readFileSync4(join12(logDir, entry), "utf8");
|
|
1108
1141
|
if (content.trim()) {
|
|
1109
1142
|
episodes.push(JSON.parse(content));
|
|
1110
1143
|
}
|
|
@@ -1138,7 +1171,7 @@ function processInbox(brainRoot) {
|
|
|
1138
1171
|
if (!existsSync12(inboxPath)) {
|
|
1139
1172
|
return { processed: 0, skipped: 0, errors: [] };
|
|
1140
1173
|
}
|
|
1141
|
-
const content =
|
|
1174
|
+
const content = readFileSync5(inboxPath, "utf8").trim();
|
|
1142
1175
|
if (!content) {
|
|
1143
1176
|
return { processed: 0, skipped: 0, errors: [] };
|
|
1144
1177
|
}
|
|
@@ -1233,7 +1266,7 @@ function ensureInbox(brainRoot) {
|
|
|
1233
1266
|
function appendCorrection(brainRoot, correction) {
|
|
1234
1267
|
const filePath = ensureInbox(brainRoot);
|
|
1235
1268
|
const line = JSON.stringify(correction) + "\n";
|
|
1236
|
-
const existing =
|
|
1269
|
+
const existing = readFileSync5(filePath, "utf8");
|
|
1237
1270
|
writeFileSync9(filePath, existing + line, "utf8");
|
|
1238
1271
|
}
|
|
1239
1272
|
|
|
@@ -1503,7 +1536,7 @@ function clearReports() {
|
|
|
1503
1536
|
}
|
|
1504
1537
|
|
|
1505
1538
|
// src/hooks.ts
|
|
1506
|
-
import { readFileSync as
|
|
1539
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync10, existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "fs";
|
|
1507
1540
|
import { execSync as execSync2 } from "child_process";
|
|
1508
1541
|
import { join as join14, resolve as resolve2 } from "path";
|
|
1509
1542
|
var SETTINGS_DIR = ".claude";
|
|
@@ -1534,7 +1567,7 @@ function installHooks(brainRoot, projectRoot, global) {
|
|
|
1534
1567
|
let settings = {};
|
|
1535
1568
|
if (existsSync13(settingsPath)) {
|
|
1536
1569
|
try {
|
|
1537
|
-
settings = JSON.parse(
|
|
1570
|
+
settings = JSON.parse(readFileSync6(settingsPath, "utf8"));
|
|
1538
1571
|
} catch {
|
|
1539
1572
|
console.log(`\u26A0\uFE0F settings.local.json was malformed, overwriting`);
|
|
1540
1573
|
}
|
|
@@ -1600,7 +1633,7 @@ function uninstallHooks(projectRoot, global) {
|
|
|
1600
1633
|
}
|
|
1601
1634
|
let settings;
|
|
1602
1635
|
try {
|
|
1603
|
-
settings = JSON.parse(
|
|
1636
|
+
settings = JSON.parse(readFileSync6(settingsPath, "utf8"));
|
|
1604
1637
|
} catch {
|
|
1605
1638
|
console.log("settings.local.json is malformed, nothing to uninstall");
|
|
1606
1639
|
return;
|
|
@@ -1643,7 +1676,7 @@ function checkHooks(projectRoot, global) {
|
|
|
1643
1676
|
}
|
|
1644
1677
|
let settings;
|
|
1645
1678
|
try {
|
|
1646
|
-
settings = JSON.parse(
|
|
1679
|
+
settings = JSON.parse(readFileSync6(settingsPath, "utf8"));
|
|
1647
1680
|
} catch {
|
|
1648
1681
|
console.log(`\u274C settings.local.json is malformed`);
|
|
1649
1682
|
return status;
|
|
@@ -1683,7 +1716,7 @@ function hasBrainRegions(dir) {
|
|
|
1683
1716
|
}
|
|
1684
1717
|
|
|
1685
1718
|
// src/digest.ts
|
|
1686
|
-
import { readFileSync as
|
|
1719
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync11, existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
|
|
1687
1720
|
import { join as join15, basename } from "path";
|
|
1688
1721
|
var NEGATION_PATTERNS = [
|
|
1689
1722
|
/\bdon[''\u2019]?t\b/i,
|
|
@@ -1746,14 +1779,30 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1746
1779
|
const logPath = join15(logDir, `${resolvedSessionId}.jsonl`);
|
|
1747
1780
|
if (existsSync14(logPath)) {
|
|
1748
1781
|
console.log(`\u23ED already digested session ${resolvedSessionId}, skip`);
|
|
1749
|
-
return { corrections: 0, skipped: 0, transcriptPath, sessionId: resolvedSessionId };
|
|
1782
|
+
return { corrections: 0, skipped: 0, toolFailures: 0, transcriptPath, sessionId: resolvedSessionId };
|
|
1750
1783
|
}
|
|
1751
1784
|
const messages = parseTranscript(transcriptPath);
|
|
1785
|
+
const toolFailures = parseToolResults(transcriptPath);
|
|
1786
|
+
for (const failure of toolFailures) {
|
|
1787
|
+
logEpisode(brainRoot, "tool-failure", failure.toolName, failure.errorText);
|
|
1788
|
+
}
|
|
1789
|
+
const retries = detectRetryPatterns(toolFailures);
|
|
1790
|
+
for (const retry of retries) {
|
|
1791
|
+
logEpisode(brainRoot, "retry-pattern", retry.toolName, retry.errorText);
|
|
1792
|
+
}
|
|
1793
|
+
const totalSignals = toolFailures.length + retries.length;
|
|
1794
|
+
if (totalSignals > 0) {
|
|
1795
|
+
console.log(`\u{1F527} digest: ${toolFailures.length} tool failure(s), ${retries.length} retry pattern(s) logged`);
|
|
1796
|
+
}
|
|
1752
1797
|
const corrections = extractCorrections(messages);
|
|
1753
|
-
if (corrections.length === 0) {
|
|
1798
|
+
if (corrections.length === 0 && toolFailures.length === 0) {
|
|
1754
1799
|
console.log(`\u{1F4DD} digest: no corrections found in session ${resolvedSessionId}`);
|
|
1755
1800
|
writeAuditLog(brainRoot, resolvedSessionId, []);
|
|
1756
|
-
return { corrections: 0, skipped: messages.length, transcriptPath, sessionId: resolvedSessionId };
|
|
1801
|
+
return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
|
|
1802
|
+
}
|
|
1803
|
+
if (corrections.length === 0) {
|
|
1804
|
+
writeAuditLog(brainRoot, resolvedSessionId, []);
|
|
1805
|
+
return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
|
|
1757
1806
|
}
|
|
1758
1807
|
let applied = 0;
|
|
1759
1808
|
const auditEntries = [];
|
|
@@ -1773,12 +1822,13 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1773
1822
|
return {
|
|
1774
1823
|
corrections: applied,
|
|
1775
1824
|
skipped: messages.length - corrections.length,
|
|
1825
|
+
toolFailures: toolFailures.length,
|
|
1776
1826
|
transcriptPath,
|
|
1777
1827
|
sessionId: resolvedSessionId
|
|
1778
1828
|
};
|
|
1779
1829
|
}
|
|
1780
1830
|
function parseTranscript(transcriptPath) {
|
|
1781
|
-
const content =
|
|
1831
|
+
const content = readFileSync7(transcriptPath, "utf8");
|
|
1782
1832
|
const lines = content.split("\n").filter(Boolean);
|
|
1783
1833
|
const messages = [];
|
|
1784
1834
|
for (const line of lines) {
|
|
@@ -1804,6 +1854,64 @@ function extractText(content) {
|
|
|
1804
1854
|
}
|
|
1805
1855
|
return null;
|
|
1806
1856
|
}
|
|
1857
|
+
var MAX_FAILURES_PER_SESSION = 20;
|
|
1858
|
+
function parseToolResults(transcriptPath) {
|
|
1859
|
+
const content = readFileSync7(transcriptPath, "utf8");
|
|
1860
|
+
const lines = content.split("\n").filter(Boolean);
|
|
1861
|
+
const failures = [];
|
|
1862
|
+
for (const line of lines) {
|
|
1863
|
+
if (failures.length >= MAX_FAILURES_PER_SESSION) break;
|
|
1864
|
+
let entry;
|
|
1865
|
+
try {
|
|
1866
|
+
entry = JSON.parse(line);
|
|
1867
|
+
} catch {
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
if (entry.type !== "user") continue;
|
|
1871
|
+
if (!entry.message || !Array.isArray(entry.message.content)) continue;
|
|
1872
|
+
for (const block of entry.message.content) {
|
|
1873
|
+
if (block.type !== "tool_result") continue;
|
|
1874
|
+
if (!block.is_error) continue;
|
|
1875
|
+
const failure = detectToolFailure(block, entry.toolUseResult);
|
|
1876
|
+
if (failure) failures.push(failure);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
return failures;
|
|
1880
|
+
}
|
|
1881
|
+
function detectRetryPatterns(failures) {
|
|
1882
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1883
|
+
for (const f of failures) {
|
|
1884
|
+
const key = f.toolName.toLowerCase().trim();
|
|
1885
|
+
const existing = counts.get(key);
|
|
1886
|
+
if (existing) {
|
|
1887
|
+
existing.count++;
|
|
1888
|
+
} else {
|
|
1889
|
+
counts.set(key, { failure: f, count: 1 });
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
return [...counts.values()].filter((entry) => entry.count >= 3).map((entry) => ({
|
|
1893
|
+
...entry.failure,
|
|
1894
|
+
toolName: `[retry x${entry.count}] ${entry.failure.toolName}`
|
|
1895
|
+
}));
|
|
1896
|
+
}
|
|
1897
|
+
function detectToolFailure(block, toolUseResult) {
|
|
1898
|
+
if (!block.is_error) return null;
|
|
1899
|
+
let errorText = "";
|
|
1900
|
+
if (typeof block.content === "string") {
|
|
1901
|
+
errorText = block.content;
|
|
1902
|
+
} else if (Array.isArray(block.content)) {
|
|
1903
|
+
errorText = block.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
|
|
1904
|
+
}
|
|
1905
|
+
if (!errorText && typeof toolUseResult === "string") {
|
|
1906
|
+
errorText = toolUseResult;
|
|
1907
|
+
}
|
|
1908
|
+
if (!errorText) return null;
|
|
1909
|
+
const exitMatch = errorText.match(/^Exit code (\d+)/);
|
|
1910
|
+
const exitCode = exitMatch ? parseInt(exitMatch[1], 10) : 1;
|
|
1911
|
+
const firstLine = errorText.split("\n").find((l) => l.trim() && !l.startsWith("Exit code")) || "unknown";
|
|
1912
|
+
const toolName = firstLine.trim().slice(0, 80);
|
|
1913
|
+
return { toolName, exitCode, errorText: errorText.slice(0, 500) };
|
|
1914
|
+
}
|
|
1807
1915
|
function extractCorrections(messages) {
|
|
1808
1916
|
const corrections = [];
|
|
1809
1917
|
for (const text of messages) {
|
|
@@ -1998,12 +2106,12 @@ function writeAuditLog(brainRoot, sessionId, entries) {
|
|
|
1998
2106
|
}
|
|
1999
2107
|
|
|
2000
2108
|
// src/evolve.ts
|
|
2001
|
-
import { existsSync as existsSync16, readFileSync as
|
|
2109
|
+
import { existsSync as existsSync16, readFileSync as readFileSync9, writeFileSync as writeFileSync13 } from "fs";
|
|
2002
2110
|
import { join as join17 } from "path";
|
|
2003
2111
|
|
|
2004
2112
|
// src/outcome.ts
|
|
2005
2113
|
import { execSync as execSync3 } from "child_process";
|
|
2006
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, readFileSync as
|
|
2114
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, readFileSync as readFileSync8, readdirSync as readdirSync10, rmSync as rmSync2, statSync as statSync4 } from "fs";
|
|
2007
2115
|
import { join as join16 } from "path";
|
|
2008
2116
|
import { randomUUID } from "crypto";
|
|
2009
2117
|
function captureSessionStart(brainRoot) {
|
|
@@ -2202,7 +2310,7 @@ function readLatestSessionState(brainRoot) {
|
|
|
2202
2310
|
}
|
|
2203
2311
|
if (!latest) return null;
|
|
2204
2312
|
try {
|
|
2205
|
-
return JSON.parse(
|
|
2313
|
+
return JSON.parse(readFileSync8(latest.path, "utf8"));
|
|
2206
2314
|
} catch {
|
|
2207
2315
|
return null;
|
|
2208
2316
|
}
|
|
@@ -2229,7 +2337,7 @@ var DEFAULT_MODEL = "gemini-2.0-flash-lite";
|
|
|
2229
2337
|
var API_TIMEOUT = 3e4;
|
|
2230
2338
|
var RETRY_DELAY = 5e3;
|
|
2231
2339
|
var EVOLVE_COOLDOWN_FILE = "hippocampus/evolve_last_run";
|
|
2232
|
-
async function runEvolve(brainRoot, dryRun) {
|
|
2340
|
+
async function runEvolve(brainRoot, dryRun, mode = "default") {
|
|
2233
2341
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
2234
2342
|
if (!apiKey) {
|
|
2235
2343
|
console.error("\u274C GEMINI_API_KEY not set. Get one at https://aistudio.google.com/apikey");
|
|
@@ -2239,7 +2347,7 @@ async function runEvolve(brainRoot, dryRun) {
|
|
|
2239
2347
|
const cooldownMs = (parseInt(process.env.EVOLVE_COOLDOWN_SECONDS ?? "60", 10) || 60) * 1e3;
|
|
2240
2348
|
const cooldownPath = join17(brainRoot, EVOLVE_COOLDOWN_FILE);
|
|
2241
2349
|
if (existsSync16(cooldownPath)) {
|
|
2242
|
-
const lastRun = parseInt(
|
|
2350
|
+
const lastRun = parseInt(readFileSync9(cooldownPath, "utf8").trim(), 10);
|
|
2243
2351
|
const elapsed = Date.now() - lastRun;
|
|
2244
2352
|
if (elapsed < cooldownMs) {
|
|
2245
2353
|
const remaining = Math.ceil((cooldownMs - elapsed) / 1e3);
|
|
@@ -2252,7 +2360,7 @@ async function runEvolve(brainRoot, dryRun) {
|
|
|
2252
2360
|
const brain = scanBrain(brainRoot);
|
|
2253
2361
|
const summary = buildBrainSummary(brain);
|
|
2254
2362
|
const outcomeSummary = buildOutcomeSummary(brainRoot);
|
|
2255
|
-
const prompt = buildPrompt(summary, episodes, outcomeSummary);
|
|
2363
|
+
const prompt = mode === "prune" ? buildPrunePrompt(summary, episodes) : buildPrompt(summary, episodes, outcomeSummary);
|
|
2256
2364
|
let rawActions;
|
|
2257
2365
|
try {
|
|
2258
2366
|
rawActions = await callGemini(prompt, apiKey);
|
|
@@ -2343,6 +2451,44 @@ Focus on: strengthening repeatedly-used rules, pruning ineffective ones, growing
|
|
|
2343
2451
|
Respond with a JSON array of actions:
|
|
2344
2452
|
[{"type":"fire","path":"cortex/NO_console_log","reason":"fired 3 times in recent sessions"}]`;
|
|
2345
2453
|
}
|
|
2454
|
+
function buildPrunePrompt(summary, episodes) {
|
|
2455
|
+
const episodeLines = episodes.length > 0 ? episodes.map((e) => `- [${e.ts}] ${e.type}: ${sanitizeForPrompt(e.detail)}`).join("\n") : "(no recent episodes)";
|
|
2456
|
+
return `You are the PRUNING engine for a hebbian brain \u2014 a filesystem-based memory system for AI agents.
|
|
2457
|
+
|
|
2458
|
+
Your job is CLEANUP. Remove what's stale, redundant, or harmful. Healthy forgetting.
|
|
2459
|
+
|
|
2460
|
+
## Axioms
|
|
2461
|
+
- Folder = Neuron, File = Firing Trace, Counter = Activation strength
|
|
2462
|
+
- 7 regions: brainstem(P0) > limbic(P1) > hippocampus(P2) > sensors(P3) > cortex(P4) > ego(P5) > prefrontal(P6)
|
|
2463
|
+
- PROTECTED regions (brainstem, limbic, sensors): NEVER touch these
|
|
2464
|
+
|
|
2465
|
+
## Current Brain
|
|
2466
|
+
${summary}
|
|
2467
|
+
|
|
2468
|
+
## Recent Episodes (last ${episodes.length})
|
|
2469
|
+
${episodeLines}
|
|
2470
|
+
|
|
2471
|
+
## Pruning Criteria
|
|
2472
|
+
1. **Stale neurons** \u2014 counter is low AND no recent episodes mention them. They occupy space but provide no value.
|
|
2473
|
+
2. **High contra ratio** \u2014 neurons present in many reverted sessions (contra_ratio > 0.7). They correlate with bad outcomes.
|
|
2474
|
+
3. **Redundant neurons** \u2014 two neurons in the same region with very similar names/meaning. Keep the stronger one, prune the weaker.
|
|
2475
|
+
4. **Contradicted neurons** \u2014 a newer neuron explicitly overrides an older one. Remove the older.
|
|
2476
|
+
|
|
2477
|
+
## Available Actions (pruning-focused)
|
|
2478
|
+
- prune: Decrement a neuron's counter. Use for rules that aren't working.
|
|
2479
|
+
- decay: Mark inactive neurons as dormant. Use for stale rules with no recent activity.
|
|
2480
|
+
- signal: Add bomb signal to block a problematic neuron. Use for neurons that actively cause harm.
|
|
2481
|
+
|
|
2482
|
+
Do NOT use grow or fire \u2014 this is a pruning pass, not a growth pass.
|
|
2483
|
+
|
|
2484
|
+
## Constraints
|
|
2485
|
+
- Max ${MAX_ACTIONS} actions per cycle
|
|
2486
|
+
- NEVER target brainstem, limbic, or sensors regions
|
|
2487
|
+
- Be conservative \u2014 only prune what you're confident about
|
|
2488
|
+
|
|
2489
|
+
Respond with a JSON array of actions:
|
|
2490
|
+
[{"type":"prune","path":"cortex/WARN_old_rule","reason":"not fired in 30+ days, no recent episodes"}]`;
|
|
2491
|
+
}
|
|
2346
2492
|
async function callGemini(prompt, apiKey) {
|
|
2347
2493
|
const model = process.env.EVOLVE_MODEL || DEFAULT_MODEL;
|
|
2348
2494
|
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;
|
|
@@ -2481,6 +2627,7 @@ function actionIcon(type) {
|
|
|
2481
2627
|
}
|
|
2482
2628
|
}
|
|
2483
2629
|
export {
|
|
2630
|
+
AGENTS_DIR,
|
|
2484
2631
|
DECAY_DAYS,
|
|
2485
2632
|
DIGEST_LOG_DIR,
|
|
2486
2633
|
EMIT_TARGETS,
|
|
@@ -2499,6 +2646,7 @@ export {
|
|
|
2499
2646
|
REGION_KO,
|
|
2500
2647
|
REGION_PRIORITY,
|
|
2501
2648
|
SESSION_STATE_DIR,
|
|
2649
|
+
SHARED_DIR,
|
|
2502
2650
|
SIGNAL_TYPES,
|
|
2503
2651
|
SPOTLIGHT_DAYS,
|
|
2504
2652
|
appendCorrection,
|
|
@@ -2509,6 +2657,8 @@ export {
|
|
|
2509
2657
|
clearReports,
|
|
2510
2658
|
contraNeuron,
|
|
2511
2659
|
detectOutcome,
|
|
2660
|
+
detectRetryPatterns,
|
|
2661
|
+
detectToolFailure,
|
|
2512
2662
|
digestTranscript,
|
|
2513
2663
|
emitBootstrap,
|
|
2514
2664
|
emitIndex,
|
|
@@ -2529,12 +2679,15 @@ export {
|
|
|
2529
2679
|
jaccardSimilarity,
|
|
2530
2680
|
listCandidates,
|
|
2531
2681
|
logEpisode,
|
|
2682
|
+
parseToolResults,
|
|
2532
2683
|
printDiag,
|
|
2533
2684
|
processInbox,
|
|
2534
2685
|
promoteCandidates,
|
|
2535
2686
|
readEpisodes,
|
|
2536
2687
|
readHookInput,
|
|
2688
|
+
resolveAgentBrain,
|
|
2537
2689
|
resolveBrainRoot,
|
|
2690
|
+
resolveSharedBrain,
|
|
2538
2691
|
rollbackNeuron,
|
|
2539
2692
|
runDecay,
|
|
2540
2693
|
runDedup,
|