hebbian 0.5.3 → 0.6.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/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,26 @@ 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 a tool failure from a tool_result block.
57
+ * Returns failure info if exit code ≠ 0, null otherwise.
58
+ */
59
+ export declare function detectToolFailure(block: {
60
+ content?: string | Array<{
61
+ type: string;
62
+ text?: string;
63
+ }>;
64
+ is_error?: boolean;
65
+ }, toolUseResult?: TranscriptLine['toolUseResult']): ToolFailure | null;
25
66
  /**
26
67
  * Extract corrections from user messages using pattern matching.
27
68
  * Returns up to MAX_CORRECTIONS_PER_SESSION corrections.
28
69
  */
29
70
  export declare function extractCorrections(messages: string[]): ExtractedCorrection[];
71
+ export {};
30
72
  //# 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,CAsE5G;AAiDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,EAAE,CA4BtE;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/index.d.ts CHANGED
@@ -24,8 +24,8 @@ 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';
27
+ export { digestTranscript, extractCorrections, readHookInput, parseToolResults, detectToolFailure } from './digest';
28
+ export type { DigestResult, ExtractedCorrection, ToolFailure } from './digest';
29
29
  export { resolveBrainRoot } from './constants';
30
30
  export { growCandidate, promoteCandidates, listCandidates, toCandidatePath, fromCandidatePath } from './candidates';
31
31
  export type { CandidateInfo, PromoteResult } from './candidates';
@@ -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,MAAM,UAAU,CAAC;AACpH,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC/E,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"}
package/dist/index.js CHANGED
@@ -1746,14 +1746,25 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
1746
1746
  const logPath = join15(logDir, `${resolvedSessionId}.jsonl`);
1747
1747
  if (existsSync14(logPath)) {
1748
1748
  console.log(`\u23ED already digested session ${resolvedSessionId}, skip`);
1749
- return { corrections: 0, skipped: 0, transcriptPath, sessionId: resolvedSessionId };
1749
+ return { corrections: 0, skipped: 0, toolFailures: 0, transcriptPath, sessionId: resolvedSessionId };
1750
1750
  }
1751
1751
  const messages = parseTranscript(transcriptPath);
1752
+ const toolFailures = parseToolResults(transcriptPath);
1753
+ for (const failure of toolFailures) {
1754
+ logEpisode(brainRoot, "tool-failure", failure.toolName, failure.errorText);
1755
+ }
1756
+ if (toolFailures.length > 0) {
1757
+ console.log(`\u{1F527} digest: ${toolFailures.length} tool failure(s) logged as episodes`);
1758
+ }
1752
1759
  const corrections = extractCorrections(messages);
1753
- if (corrections.length === 0) {
1760
+ if (corrections.length === 0 && toolFailures.length === 0) {
1754
1761
  console.log(`\u{1F4DD} digest: no corrections found in session ${resolvedSessionId}`);
1755
1762
  writeAuditLog(brainRoot, resolvedSessionId, []);
1756
- return { corrections: 0, skipped: messages.length, transcriptPath, sessionId: resolvedSessionId };
1763
+ return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
1764
+ }
1765
+ if (corrections.length === 0) {
1766
+ writeAuditLog(brainRoot, resolvedSessionId, []);
1767
+ return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
1757
1768
  }
1758
1769
  let applied = 0;
1759
1770
  const auditEntries = [];
@@ -1773,6 +1784,7 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
1773
1784
  return {
1774
1785
  corrections: applied,
1775
1786
  skipped: messages.length - corrections.length,
1787
+ toolFailures: toolFailures.length,
1776
1788
  transcriptPath,
1777
1789
  sessionId: resolvedSessionId
1778
1790
  };
@@ -1804,6 +1816,48 @@ function extractText(content) {
1804
1816
  }
1805
1817
  return null;
1806
1818
  }
1819
+ var MAX_FAILURES_PER_SESSION = 20;
1820
+ function parseToolResults(transcriptPath) {
1821
+ const content = readFileSync6(transcriptPath, "utf8");
1822
+ const lines = content.split("\n").filter(Boolean);
1823
+ const failures = [];
1824
+ for (const line of lines) {
1825
+ if (failures.length >= MAX_FAILURES_PER_SESSION) break;
1826
+ let entry;
1827
+ try {
1828
+ entry = JSON.parse(line);
1829
+ } catch {
1830
+ continue;
1831
+ }
1832
+ if (entry.type !== "user") continue;
1833
+ if (!entry.message || !Array.isArray(entry.message.content)) continue;
1834
+ for (const block of entry.message.content) {
1835
+ if (block.type !== "tool_result") continue;
1836
+ if (!block.is_error) continue;
1837
+ const failure = detectToolFailure(block, entry.toolUseResult);
1838
+ if (failure) failures.push(failure);
1839
+ }
1840
+ }
1841
+ return failures;
1842
+ }
1843
+ function detectToolFailure(block, toolUseResult) {
1844
+ if (!block.is_error) return null;
1845
+ let errorText = "";
1846
+ if (typeof block.content === "string") {
1847
+ errorText = block.content;
1848
+ } else if (Array.isArray(block.content)) {
1849
+ errorText = block.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
1850
+ }
1851
+ if (!errorText && typeof toolUseResult === "string") {
1852
+ errorText = toolUseResult;
1853
+ }
1854
+ if (!errorText) return null;
1855
+ const exitMatch = errorText.match(/^Exit code (\d+)/);
1856
+ const exitCode = exitMatch ? parseInt(exitMatch[1], 10) : 1;
1857
+ const firstLine = errorText.split("\n").find((l) => l.trim() && !l.startsWith("Exit code")) || "unknown";
1858
+ const toolName = firstLine.trim().slice(0, 80);
1859
+ return { toolName, exitCode, errorText: errorText.slice(0, 500) };
1860
+ }
1807
1861
  function extractCorrections(messages) {
1808
1862
  const corrections = [];
1809
1863
  for (const text of messages) {
@@ -2509,6 +2563,7 @@ export {
2509
2563
  clearReports,
2510
2564
  contraNeuron,
2511
2565
  detectOutcome,
2566
+ detectToolFailure,
2512
2567
  digestTranscript,
2513
2568
  emitBootstrap,
2514
2569
  emitIndex,
@@ -2529,6 +2584,7 @@ export {
2529
2584
  jaccardSimilarity,
2530
2585
  listCandidates,
2531
2586
  logEpisode,
2587
+ parseToolResults,
2532
2588
  printDiag,
2533
2589
  processInbox,
2534
2590
  promoteCandidates,