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.
@@ -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
@@ -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
@@ -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;AAyDD;;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,CAiC5E"}
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 declare function runEvolve(brainRoot: string, dryRun: boolean): Promise<EvolveResult>;
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[]>;
@@ -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,CAkEzF;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;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,CAwBtF;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA8BjF"}
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';
@@ -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;AAG/C,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,MAAM,UAAU,CAAC;AAG3D,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"}
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 readFileSync4, writeFileSync as writeFileSync9, existsSync as existsSync12, mkdirSync as mkdirSync7 } from "fs";
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 dirname2, relative as relative3 } from "path";
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(dirname2(dst), { recursive: true });
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 readFileSync3, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, existsSync as existsSync11 } from "fs";
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 = readFileSync3(join12(logDir, entry), "utf8");
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 = readFileSync4(inboxPath, "utf8").trim();
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 = readFileSync4(filePath, "utf8");
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 readFileSync5, writeFileSync as writeFileSync10, existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "fs";
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(readFileSync5(settingsPath, "utf8"));
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(readFileSync5(settingsPath, "utf8"));
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(readFileSync5(settingsPath, "utf8"));
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 readFileSync6, writeFileSync as writeFileSync11, existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
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 = readFileSync6(transcriptPath, "utf8");
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 readFileSync8, writeFileSync as writeFileSync13 } from "fs";
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 readFileSync7, readdirSync as readdirSync10, rmSync as rmSync2, statSync as statSync4 } from "fs";
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(readFileSync7(latest.path, "utf8"));
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(readFileSync8(cooldownPath, "utf8").trim(), 10);
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,