@link-assistant/hive-mind 1.25.6 → 1.25.7
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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/claude.lib.mjs +18 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.25.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ad57ea6: fix: prevent false positive error detection when multi-line stderr chunks contain JSON warnings (Issue #1354)
|
|
8
|
+
|
|
9
|
+
Previously, when Claude CLI emitted multiple JSON log lines in a single stderr chunk (newline-separated), the entire multi-line string was passed to `isStderrError()` as one unit. Since `JSON.parse()` would fail on two concatenated JSON objects, it fell through to keyword matching — finding words like `"failed"` inside warning messages — and incorrectly flagged a successful run as an error.
|
|
10
|
+
|
|
11
|
+
Additionally, `messageCount === 0 && toolUseCount === 0` could fire even after a 60-turn successful session, because the counter only checked for `data.type === 'message'` but Claude CLI emits outer events as `"assistant"` type.
|
|
12
|
+
|
|
13
|
+
Now the fix applies two targeted changes to `src/claude.lib.mjs`:
|
|
14
|
+
1. **Split multi-line stderr chunks by newline** and check each line individually with `isStderrError()`, so valid JSON warning lines are correctly parsed and not conflated with error patterns.
|
|
15
|
+
2. **Track `resultSuccessReceived`** when `data.type === 'result' && data.subtype === 'success'` is received, and add a `!resultSuccessReceived` guard to the false positive detection condition — ensuring a confirmed successful result prevents spurious error reporting.
|
|
16
|
+
|
|
17
|
+
Full case study analysis including timeline reconstruction, root cause analysis, and evidence in `docs/case-studies/issue-1354/`.
|
|
18
|
+
|
|
3
19
|
## 1.25.6
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/package.json
CHANGED
package/src/claude.lib.mjs
CHANGED
|
@@ -846,6 +846,7 @@ export const executeClaudeCommand = async params => {
|
|
|
846
846
|
let is503Error = false;
|
|
847
847
|
let isInternalServerError = false; // Issue #1331: Track 500 Internal server error
|
|
848
848
|
let stderrErrors = [];
|
|
849
|
+
let resultSuccessReceived = false; // Issue #1354: Track if result success event was received
|
|
849
850
|
let anthropicTotalCostUSD = null; // Capture Anthropic's official total_cost_usd from result
|
|
850
851
|
let errorDuringExecution = false; // Issue #1088: Track if error_during_execution subtype occurred
|
|
851
852
|
let resultSummary = null; // Issue #1263: Capture AI result summary for --attach-solution-summary
|
|
@@ -1014,6 +1015,10 @@ export const executeClaudeCommand = async params => {
|
|
|
1014
1015
|
await log(`📌 Result event received, starting ${streamCloseTimeoutMs / 1000}s stream close timeout (Issue #1280)`, { verbose: true });
|
|
1015
1016
|
resultTimeoutId = setTimeout(forceExitOnTimeout, streamCloseTimeoutMs);
|
|
1016
1017
|
}
|
|
1018
|
+
// Issue #1354: Track when result event confirms success (prevents false positive detection)
|
|
1019
|
+
if (data.subtype === 'success') {
|
|
1020
|
+
resultSuccessReceived = true;
|
|
1021
|
+
}
|
|
1017
1022
|
// Issue #1104: Only extract cost from subtype 'success' results
|
|
1018
1023
|
if (data.subtype === 'success' && data.total_cost_usd !== undefined && data.total_cost_usd !== null) {
|
|
1019
1024
|
anthropicTotalCostUSD = data.total_cost_usd;
|
|
@@ -1114,9 +1119,15 @@ export const executeClaudeCommand = async params => {
|
|
|
1114
1119
|
// Log stderr immediately
|
|
1115
1120
|
if (errorOutput) {
|
|
1116
1121
|
await log(errorOutput, { stream: 'stderr' });
|
|
1117
|
-
//
|
|
1118
|
-
|
|
1119
|
-
|
|
1122
|
+
// Issue #1354: Split multi-line stderr chunks and check each line individually.
|
|
1123
|
+
// A single chunk may contain multiple newline-separated JSON messages (e.g. two
|
|
1124
|
+
// consecutive {"level":"warn",...} lines). Passing the whole chunk to isStderrError()
|
|
1125
|
+
// causes JSON.parse() to fail (multi-object is not valid JSON), falling through to
|
|
1126
|
+
// keyword matching and producing false positives on words like "failed".
|
|
1127
|
+
for (const line of errorOutput.split('\n')) {
|
|
1128
|
+
if (isStderrError(line)) {
|
|
1129
|
+
stderrErrors.push(line.trim());
|
|
1130
|
+
}
|
|
1120
1131
|
}
|
|
1121
1132
|
}
|
|
1122
1133
|
} else if (chunk.type === 'exit') {
|
|
@@ -1255,7 +1266,10 @@ export const executeClaudeCommand = async params => {
|
|
|
1255
1266
|
// - Prevents EPERM errors and false success reports
|
|
1256
1267
|
//
|
|
1257
1268
|
// See: docs/dependencies-research/claude-code-issues/README.md for full details
|
|
1258
|
-
|
|
1269
|
+
// Issue #1354: Do not trigger if the result event already confirmed success.
|
|
1270
|
+
// A successful result event is definitive proof the command succeeded, regardless of
|
|
1271
|
+
// messageCount (which may be 0 if "assistant" events were counted instead of "message" type).
|
|
1272
|
+
if (!commandFailed && !resultSuccessReceived && stderrErrors.length > 0 && messageCount === 0 && toolUseCount === 0) {
|
|
1259
1273
|
commandFailed = true;
|
|
1260
1274
|
const errorsPreview = stderrErrors
|
|
1261
1275
|
.slice(0, 5)
|