fix: address remaining greptile 4/5 items — random guard, ENOENT comment, array snapshot
1. Math.random() === 0 guard: (0).toString(36).slice(2,6) returns '' producing a trailing-hyphen slug. Added || '0000' fallback. 2. Misleading ENOENT comment: said 'when blockSessionSave was set before writeFileWithinRoot' but that branch requires writtenEntry !== null (blockSessionSave was false). Real scenario: external file deletion between inline write and post-hook drain. Comment corrected. 3. Live-array drain: for...of on postHookActions is a live iterator — a self-scheduling action could loop infinitely. Snapshot the array with [...(event.postHookActions ?? [])] before draining.
This commit is contained in:
parent
c6110a3b15
commit
a0073bfb9b
@ -332,7 +332,7 @@ const saveSessionToMemory: HookHandler = async (event) => {
|
||||
// one silently overwrites the earlier memory entry.
|
||||
if (!slug) {
|
||||
const timeSlug = now.toISOString().split("T")[1].split(".")[0].replace(/:/g, "");
|
||||
const rand = Math.random().toString(36).slice(2, 6); // 4-char alphanumeric
|
||||
const rand = Math.random().toString(36).slice(2, 6) || "0000"; // 4-char alphanumeric
|
||||
slug = `${timeSlug.slice(0, 6)}-${rand}`;
|
||||
log.debug("Using fallback timestamp slug", { slug });
|
||||
}
|
||||
@ -439,11 +439,12 @@ const saveSessionToMemory: HookHandler = async (event) => {
|
||||
await fs.unlink(memoryFilePath);
|
||||
log.debug("Session save retracted by post-hook (blockSessionSave)");
|
||||
} catch (err) {
|
||||
// ENOENT is expected when the inline write didn't happen
|
||||
// (e.g. blockSessionSave was set before writeFileWithinRoot).
|
||||
// Re-throw so triggerInternalHook logs it. Note: the error
|
||||
// is caught per-action and does NOT propagate to the caller;
|
||||
// the file may remain on disk if unlink fails (e.g. EACCES).
|
||||
// ENOENT can occur if the file was externally deleted between
|
||||
// the inline write and the post-hook drain — not a concern.
|
||||
// Re-throw non-ENOENT errors (e.g. EACCES, EROFS) so
|
||||
// triggerInternalHook logs them. Note: errors are caught
|
||||
// per-action and do NOT propagate to the session caller;
|
||||
// the file may remain on disk under adversarial FS conditions.
|
||||
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
||||
throw err;
|
||||
}
|
||||
|
||||
@ -292,7 +292,13 @@ export async function triggerInternalHook(event: InternalHookEvent): Promise<voi
|
||||
// a chance to mutate event.context, eliminating FIFO ordering issues.
|
||||
// Actions execute in push order; errors are caught per-action so one
|
||||
// failure doesn't block others.
|
||||
for (const action of event.postHookActions) {
|
||||
//
|
||||
// Snapshot the array before draining so that actions pushed *by* post-hook
|
||||
// callbacks do not execute in this drain cycle. Without this, a self-
|
||||
// scheduling action (one that pushes another action) could loop infinitely
|
||||
// because Array's for...of iterator is live and re-reads length each step.
|
||||
const pendingActions = [...(event.postHookActions ?? [])];
|
||||
for (const action of pendingActions) {
|
||||
try {
|
||||
await action();
|
||||
} catch (err) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user