Skip to content

chore: sync core lib and CLAUDE.md from agent-core#34

Merged
avifenesh merged 1 commit into
mainfrom
chore/sync-core-sync-docs-20260529-103237
May 29, 2026
Merged

chore: sync core lib and CLAUDE.md from agent-core#34
avifenesh merged 1 commit into
mainfrom
chore/sync-core-sync-docs-20260529-103237

Conversation

@avifenesh

Copy link
Copy Markdown
Contributor

Automated sync of lib/ and CLAUDE.md from agent-core.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request unifies repository intelligence by folding repo-map into lib/repo-intel and introducing an opt-in embedding pipeline with binary resolution, orchestration, and post-init enrichment helpers. The review feedback highlights several robustness improvements to prevent process crashes and hangs, including handling missing redirect locations, catching unhandled EPIPE stream errors on child process stdin, implementing a fail-fast mechanism in the dual-process orchestrator pipe, and adding null guards to prevent TypeError crashes.

Comment on lines +62 to +68
var loc = res.headers.location;
if (loc && !loc.startsWith('https://')) {
reject(new Error('Refusing non-HTTPS redirect to ' + loc));
return;
}
request(loc, redirectCount + 1);
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the Location header is missing or undefined (e.g., due to a malformed redirect response), calling request(loc, ...) will pass undefined as the URL. This causes https.get(undefined, ...) to throw a synchronous TypeError inside the asynchronous response callback, resulting in an unhandled exception that crashes the Node.js process. Adding a check to ensure loc is present before proceeding prevents this crash.

Suggested change
var loc = res.headers.location;
if (loc && !loc.startsWith('https://')) {
reject(new Error('Refusing non-HTTPS redirect to ' + loc));
return;
}
request(loc, redirectCount + 1);
return;
var loc = res.headers.location;
if (!loc) {
reject(new Error('Redirect status ' + sc + ' received but no Location header found'));
return;
}
if (!loc.startsWith('https://')) {
reject(new Error('Refusing non-HTTPS redirect to ' + loc));
return;
}
request(loc, redirectCount + 1);
return;

Comment on lines +103 to +109
const tar = cp.spawn('tar', ['xz', '-C', tarDest], {
stdio: ['pipe', 'pipe', 'pipe']
});
let stderr = '';
tar.stderr.on('data', function (d) { stderr += d; });
tar.stdin.write(buf);
tar.stdin.end();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the tar process fails to spawn or exits immediately, writing to tar.stdin can emit an unhandled EPIPE or broken pipe error on the stream. In Node.js, unhandled stream errors crash the process. Registering a dummy error listener on tar.stdin prevents these crashes, as any actual process failures are already handled by the close or error events on the child process itself.

    const tar = cp.spawn('tar', ['xz', '-C', tarDest], {
      stdio: ['pipe', 'pipe', 'pipe']
    });
    tar.stdin.on('error', function () {}); // Prevent unhandled EPIPE crashes
    let stderr = '';
    tar.stderr.on('data', function (d) { stderr += d; });
    tar.stdin.write(buf);
    tar.stdin.end();

Comment thread lib/repo-intel/index.js
Comment on lines +257 to +261
const proc = cp.spawn(binPath, args, {
stdio: ['pipe', 'pipe', 'pipe'],
windowsHide: true
});
let stdout = '';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the tar extraction helper, if the agent-analyzer process exits immediately with an error, writing to proc.stdin can emit an unhandled EPIPE error on the stream and crash the Node.js process. Registering a dummy error listener on proc.stdin prevents this crash.

Suggested change
const proc = cp.spawn(binPath, args, {
stdio: ['pipe', 'pipe', 'pipe'],
windowsHide: true
});
let stdout = '';
const proc = cp.spawn(binPath, args, {
stdio: ['pipe', 'pipe', 'pipe'],
windowsHide: true
});
proc.stdin.on('error', () => {}); // Prevent unhandled EPIPE crashes
let stdout = '';

Comment on lines +185 to +201
function maybeFinish() {
if (settled || embedExit === null || setExit === null) return;
if (embedExit !== 0) {
return done(new Error(
embedBinary.EMBED_BINARY_NAME + ' exited ' + embedExit +
(embedStderr.trim() ? ': ' + embedStderr.trim().slice(0, 500) : '')
));
}
if (setExit !== 0) {
return done(new Error(
'agent-analyzer set-embeddings exited ' + setExit +
(setStderr.trim() ? ': ' + setStderr.trim().slice(0, 500) : '')
));
}
const m = setStdout.match(/(\d+)\s+files?/);
done(null, { files: m ? parseInt(m[1], 10) : undefined });
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current maybeFinish implementation requires both processes to exit (embedExit !== null && setExit !== null) before checking for failures. If one process fails early (e.g., set-embeddings exits with an error), the other process might keep running or hang waiting for input/output, causing the promise to hang indefinitely. Implementing a fail-fast approach allows the orchestrator to immediately reject the promise and terminate the surviving sibling process upon any failure.

Suggested change
function maybeFinish() {
if (settled || embedExit === null || setExit === null) return;
if (embedExit !== 0) {
return done(new Error(
embedBinary.EMBED_BINARY_NAME + ' exited ' + embedExit +
(embedStderr.trim() ? ': ' + embedStderr.trim().slice(0, 500) : '')
));
}
if (setExit !== 0) {
return done(new Error(
'agent-analyzer set-embeddings exited ' + setExit +
(setStderr.trim() ? ': ' + setStderr.trim().slice(0, 500) : '')
));
}
const m = setStdout.match(/(\d+)\s+files?/);
done(null, { files: m ? parseInt(m[1], 10) : undefined });
}
function maybeFinish() {
if (settled) return;
if (embedExit !== null && embedExit !== 0) {
return done(new Error(
embedBinary.EMBED_BINARY_NAME + ' exited ' + embedExit +
(embedStderr.trim() ? ': ' + embedStderr.trim().slice(0, 500) : '')
));
}
if (setExit !== null && setExit !== 0) {
return done(new Error(
'agent-analyzer set-embeddings exited ' + setExit +
(setStderr.trim() ? ': ' + setStderr.trim().slice(0, 500) : '')
));
}
if (embedExit === 0 && setExit === 0) {
const m = setStdout.match(/(\d+)\s+files?/);
done(null, { files: m ? parseInt(m[1], 10) : undefined });
}
}

Comment thread lib/repo-intel/enrich.js
Comment on lines +93 to +94
function topPaths(repoIntelData, n) {
const fa = repoIntelData.fileActivity || {};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If repoIntelData is null or undefined (which can happen if loadRaw returns null when the map file is missing or unreadable), accessing repoIntelData.fileActivity will throw a TypeError and crash the execution. Adding a guard ensures the function handles missing data gracefully.

Suggested change
function topPaths(repoIntelData, n) {
const fa = repoIntelData.fileActivity || {};
function topPaths(repoIntelData, n) {
const fa = (repoIntelData && repoIntelData.fileActivity) || {};

@avifenesh
avifenesh merged commit 250f1cc into main May 29, 2026
10 checks passed
@avifenesh
avifenesh deleted the chore/sync-core-sync-docs-20260529-103237 branch May 29, 2026 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant