hebbian 0.8.0 → 0.8.1
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 +78 -17
- package/dist/bin/hebbian.js.map +1 -1
- package/dist/digest.d.ts +13 -1
- package/dist/digest.d.ts.map +1 -1
- package/dist/index.js +76 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/digest.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare function readHookInput(stdin: string): {
|
|
|
48
48
|
*/
|
|
49
49
|
export declare function digestTranscript(brainRoot: string, transcriptPath: string, sessionId?: string): DigestResult;
|
|
50
50
|
/**
|
|
51
|
-
* Parse tool_result blocks from a Claude Code transcript.
|
|
51
|
+
* Parse tool_result blocks from a Claude Code transcript file.
|
|
52
52
|
* Returns detected failures (exit code ≠ 0, is_error = true).
|
|
53
53
|
*/
|
|
54
54
|
export declare function parseToolResults(transcriptPath: string): ToolFailure[];
|
|
@@ -68,6 +68,18 @@ export declare function detectToolFailure(block: {
|
|
|
68
68
|
}>;
|
|
69
69
|
is_error?: boolean;
|
|
70
70
|
}, toolUseResult?: TranscriptLine['toolUseResult']): ToolFailure | null;
|
|
71
|
+
/**
|
|
72
|
+
* Soft-detect a failure from a tool_result where is_error is false.
|
|
73
|
+
* Catches errors masked by `|| true` or `2>&1` by matching conservative
|
|
74
|
+
* patterns against stdout/stderr content.
|
|
75
|
+
*/
|
|
76
|
+
export declare function detectSoftFailure(block: {
|
|
77
|
+
content?: string | Array<{
|
|
78
|
+
type: string;
|
|
79
|
+
text?: string;
|
|
80
|
+
}>;
|
|
81
|
+
is_error?: boolean;
|
|
82
|
+
}, toolUseResult?: TranscriptLine['toolUseResult']): ToolFailure | null;
|
|
71
83
|
/**
|
|
72
84
|
* Extract corrections from user messages using pattern matching.
|
|
73
85
|
* Returns up to MAX_CORRECTIONS_PER_SESSION corrections.
|
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":"AAqBA,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,CAwF5G;AAsDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,EAAE,CAGtE;AAqCD;;;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;;;;GAIG;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,CAiCpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,mBAAmB,EAAE,CAiC5E"}
|
package/dist/index.js
CHANGED
|
@@ -1814,12 +1814,21 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1814
1814
|
const resolvedSessionId = sessionId || basename(transcriptPath, ".jsonl");
|
|
1815
1815
|
const logDir = join15(brainRoot, DIGEST_LOG_DIR);
|
|
1816
1816
|
const logPath = join15(logDir, `${resolvedSessionId}.jsonl`);
|
|
1817
|
-
|
|
1817
|
+
const content = readFileSync7(transcriptPath, "utf8");
|
|
1818
|
+
const allLines = content.split("\n").filter(Boolean);
|
|
1819
|
+
const totalLines = allLines.length;
|
|
1820
|
+
const meta = readAuditMeta(logPath);
|
|
1821
|
+
if (existsSync14(logPath) && !meta) {
|
|
1818
1822
|
console.log(`\u23ED already digested session ${resolvedSessionId}, skip`);
|
|
1819
1823
|
return { corrections: 0, skipped: 0, toolFailures: 0, transcriptPath, sessionId: resolvedSessionId };
|
|
1820
1824
|
}
|
|
1821
|
-
const
|
|
1822
|
-
|
|
1825
|
+
const skipLines = meta ? meta.lineCount : 0;
|
|
1826
|
+
if (skipLines >= totalLines) {
|
|
1827
|
+
return { corrections: 0, skipped: 0, toolFailures: 0, transcriptPath, sessionId: resolvedSessionId };
|
|
1828
|
+
}
|
|
1829
|
+
const newLines = allLines.slice(skipLines);
|
|
1830
|
+
const messages = parseTranscriptFromLines(newLines);
|
|
1831
|
+
const toolFailures = parseToolResultsFromLines(newLines);
|
|
1823
1832
|
for (const failure of toolFailures) {
|
|
1824
1833
|
logEpisode(brainRoot, "tool-failure", failure.toolName, failure.errorText);
|
|
1825
1834
|
}
|
|
@@ -1834,11 +1843,11 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1834
1843
|
const corrections = extractCorrections(messages);
|
|
1835
1844
|
if (corrections.length === 0 && toolFailures.length === 0) {
|
|
1836
1845
|
console.log(`\u{1F4DD} digest: no corrections found in session ${resolvedSessionId}`);
|
|
1837
|
-
writeAuditLog(brainRoot, resolvedSessionId, []);
|
|
1846
|
+
writeAuditLog(brainRoot, resolvedSessionId, [], totalLines);
|
|
1838
1847
|
return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
|
|
1839
1848
|
}
|
|
1840
1849
|
if (corrections.length === 0) {
|
|
1841
|
-
writeAuditLog(brainRoot, resolvedSessionId, []);
|
|
1850
|
+
writeAuditLog(brainRoot, resolvedSessionId, [], totalLines);
|
|
1842
1851
|
return { corrections: 0, skipped: messages.length, toolFailures: toolFailures.length, transcriptPath, sessionId: resolvedSessionId };
|
|
1843
1852
|
}
|
|
1844
1853
|
let applied = 0;
|
|
@@ -1854,7 +1863,7 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1854
1863
|
auditEntries.push({ correction, applied: false });
|
|
1855
1864
|
}
|
|
1856
1865
|
}
|
|
1857
|
-
writeAuditLog(brainRoot, resolvedSessionId, auditEntries);
|
|
1866
|
+
writeAuditLog(brainRoot, resolvedSessionId, auditEntries, totalLines);
|
|
1858
1867
|
console.log(`\u{1F4DD} digest: ${applied} correction(s) from session ${resolvedSessionId}`);
|
|
1859
1868
|
return {
|
|
1860
1869
|
corrections: applied,
|
|
@@ -1864,9 +1873,7 @@ function digestTranscript(brainRoot, transcriptPath, sessionId) {
|
|
|
1864
1873
|
sessionId: resolvedSessionId
|
|
1865
1874
|
};
|
|
1866
1875
|
}
|
|
1867
|
-
function
|
|
1868
|
-
const content = readFileSync7(transcriptPath, "utf8");
|
|
1869
|
-
const lines = content.split("\n").filter(Boolean);
|
|
1876
|
+
function parseTranscriptFromLines(lines) {
|
|
1870
1877
|
const messages = [];
|
|
1871
1878
|
for (const line of lines) {
|
|
1872
1879
|
let entry;
|
|
@@ -1892,9 +1899,19 @@ function extractText(content) {
|
|
|
1892
1899
|
return null;
|
|
1893
1900
|
}
|
|
1894
1901
|
var MAX_FAILURES_PER_SESSION = 20;
|
|
1902
|
+
var SOFT_ERROR_PATTERNS = [
|
|
1903
|
+
/(?:^|\n)\S*(?:\(\w+\):\d+: )?command not found:/m,
|
|
1904
|
+
// shell: command not found
|
|
1905
|
+
/(?:^|\n)npm error\b/m,
|
|
1906
|
+
// npm error (not npm warn)
|
|
1907
|
+
/(?:^|\n)fatal: /m
|
|
1908
|
+
// git fatal
|
|
1909
|
+
];
|
|
1895
1910
|
function parseToolResults(transcriptPath) {
|
|
1896
1911
|
const content = readFileSync7(transcriptPath, "utf8");
|
|
1897
|
-
|
|
1912
|
+
return parseToolResultsFromLines(content.split("\n").filter(Boolean));
|
|
1913
|
+
}
|
|
1914
|
+
function parseToolResultsFromLines(lines) {
|
|
1898
1915
|
const failures = [];
|
|
1899
1916
|
for (const line of lines) {
|
|
1900
1917
|
if (failures.length >= MAX_FAILURES_PER_SESSION) break;
|
|
@@ -1908,9 +1925,13 @@ function parseToolResults(transcriptPath) {
|
|
|
1908
1925
|
if (!entry.message || !Array.isArray(entry.message.content)) continue;
|
|
1909
1926
|
for (const block of entry.message.content) {
|
|
1910
1927
|
if (block.type !== "tool_result") continue;
|
|
1911
|
-
if (
|
|
1912
|
-
|
|
1913
|
-
|
|
1928
|
+
if (block.is_error) {
|
|
1929
|
+
const failure = detectToolFailure(block, entry.toolUseResult);
|
|
1930
|
+
if (failure) failures.push(failure);
|
|
1931
|
+
} else {
|
|
1932
|
+
const failure = detectSoftFailure(block, entry.toolUseResult);
|
|
1933
|
+
if (failure) failures.push(failure);
|
|
1934
|
+
}
|
|
1914
1935
|
}
|
|
1915
1936
|
}
|
|
1916
1937
|
return failures;
|
|
@@ -1949,6 +1970,30 @@ function detectToolFailure(block, toolUseResult) {
|
|
|
1949
1970
|
const toolName = firstLine.trim().slice(0, 80);
|
|
1950
1971
|
return { toolName, exitCode, errorText: errorText.slice(0, 500) };
|
|
1951
1972
|
}
|
|
1973
|
+
function detectSoftFailure(block, toolUseResult) {
|
|
1974
|
+
let text = "";
|
|
1975
|
+
if (typeof block.content === "string") {
|
|
1976
|
+
text = block.content;
|
|
1977
|
+
} else if (Array.isArray(block.content)) {
|
|
1978
|
+
text = block.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
|
|
1979
|
+
}
|
|
1980
|
+
if (toolUseResult && typeof toolUseResult === "object") {
|
|
1981
|
+
if (toolUseResult.stderr) text += "\n" + toolUseResult.stderr;
|
|
1982
|
+
}
|
|
1983
|
+
if (!text) return null;
|
|
1984
|
+
for (const pattern of SOFT_ERROR_PATTERNS) {
|
|
1985
|
+
const match = text.match(pattern);
|
|
1986
|
+
if (match) {
|
|
1987
|
+
const matchedLine = text.split("\n").find((l) => pattern.test(l)) || "unknown";
|
|
1988
|
+
return {
|
|
1989
|
+
toolName: `[soft] ${matchedLine.trim().slice(0, 70)}`,
|
|
1990
|
+
exitCode: 0,
|
|
1991
|
+
errorText: text.slice(0, 500)
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
return null;
|
|
1996
|
+
}
|
|
1952
1997
|
function extractCorrections(messages) {
|
|
1953
1998
|
const corrections = [];
|
|
1954
1999
|
for (const text of messages) {
|
|
@@ -2123,13 +2168,28 @@ function extractKeywords(text) {
|
|
|
2123
2168
|
]);
|
|
2124
2169
|
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));
|
|
2125
2170
|
}
|
|
2126
|
-
function
|
|
2171
|
+
function readAuditMeta(logPath) {
|
|
2172
|
+
if (!existsSync14(logPath)) return null;
|
|
2173
|
+
try {
|
|
2174
|
+
const content = readFileSync7(logPath, "utf8");
|
|
2175
|
+
const firstLine = content.split("\n")[0];
|
|
2176
|
+
if (!firstLine) return null;
|
|
2177
|
+
const parsed = JSON.parse(firstLine);
|
|
2178
|
+
if (parsed._meta && typeof parsed.lineCount === "number") {
|
|
2179
|
+
return { lineCount: parsed.lineCount };
|
|
2180
|
+
}
|
|
2181
|
+
} catch {
|
|
2182
|
+
}
|
|
2183
|
+
return null;
|
|
2184
|
+
}
|
|
2185
|
+
function writeAuditLog(brainRoot, sessionId, entries, lineCount) {
|
|
2127
2186
|
const logDir = join15(brainRoot, DIGEST_LOG_DIR);
|
|
2128
2187
|
if (!existsSync14(logDir)) {
|
|
2129
2188
|
mkdirSync9(logDir, { recursive: true });
|
|
2130
2189
|
}
|
|
2131
2190
|
const logPath = join15(logDir, `${sessionId}.jsonl`);
|
|
2132
|
-
const
|
|
2191
|
+
const metaLine = JSON.stringify({ _meta: true, lineCount, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
2192
|
+
const entryLines = entries.map(
|
|
2133
2193
|
(e) => JSON.stringify({
|
|
2134
2194
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2135
2195
|
path: e.correction.path,
|
|
@@ -2139,7 +2199,7 @@ function writeAuditLog(brainRoot, sessionId, entries) {
|
|
|
2139
2199
|
applied: e.applied
|
|
2140
2200
|
})
|
|
2141
2201
|
);
|
|
2142
|
-
writeFileSync11(logPath,
|
|
2202
|
+
writeFileSync11(logPath, [metaLine, ...entryLines].join("\n") + "\n", "utf8");
|
|
2143
2203
|
}
|
|
2144
2204
|
|
|
2145
2205
|
// src/evolve.ts
|