fix: sort prompt store by updatedAt instead of filename

getLatestPromptSummary() sorted JSON filenames alphabetically to find
the most recent prompt. Since filenames are UUIDs (random, not temporal),
this returned arbitrary results. Now reads updatedAt from each record
and picks the highest.

Also fixes test isolation on Windows (USERPROFILE) and adds a regression
test that fails with the old alphabetical sort.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Facu_Viñas 2026-03-11 14:44:42 -03:00
parent a37ef56146
commit 8a00605e51
2 changed files with 74 additions and 11 deletions

View file

@ -6,12 +6,25 @@ import { tmpdir } from "node:os";
import { createPromptRecord, writePromptRecord } from "../../remote-questions/store.ts";
import { getLatestPromptSummary } from "../../remote-questions/status.ts";
test("getLatestPromptSummary returns latest stored prompt", async () => {
const home = process.env.HOME!;
const tempHome = join(tmpdir(), `gsd-remote-status-${Date.now()}`);
mkdirSync(join(tempHome, ".gsd", "runtime", "remote-questions"), { recursive: true });
process.env.HOME = tempHome;
function withTempHome(fn: (tempHome: string) => void | Promise<void>) {
return async () => {
const savedHome = process.env.HOME;
const savedUserProfile = process.env.USERPROFILE;
const tempHome = join(tmpdir(), `gsd-remote-status-${Date.now()}-${Math.random().toString(36).slice(2)}`);
mkdirSync(join(tempHome, ".gsd", "runtime", "remote-questions"), { recursive: true });
process.env.HOME = tempHome;
process.env.USERPROFILE = tempHome;
try {
await fn(tempHome);
} finally {
process.env.HOME = savedHome;
process.env.USERPROFILE = savedUserProfile;
rmSync(tempHome, { recursive: true, force: true });
}
};
}
test("getLatestPromptSummary returns latest stored prompt", withTempHome(() => {
const recordA = createPromptRecord({
id: "a-prompt",
channel: "slack",
@ -38,7 +51,49 @@ test("getLatestPromptSummary returns latest stored prompt", async () => {
const latest = getLatestPromptSummary();
assert.equal(latest?.id, "z-prompt");
assert.equal(latest?.status, "answered");
}));
process.env.HOME = home;
rmSync(tempHome, { recursive: true, force: true });
});
test("getLatestPromptSummary sorts by updatedAt, not filename", withTempHome(() => {
// Record with alphabetically-LAST id but OLDEST timestamp
const old = createPromptRecord({
id: "zzz-oldest",
channel: "slack",
createdAt: 1000,
timeoutAt: 9999,
pollIntervalMs: 5000,
questions: [],
});
old.updatedAt = 1000;
writePromptRecord(old);
// Record with alphabetically-FIRST id but NEWEST timestamp
const newest = createPromptRecord({
id: "aaa-newest",
channel: "discord",
createdAt: 3000,
timeoutAt: 9999,
pollIntervalMs: 5000,
questions: [],
});
newest.updatedAt = 3000;
newest.status = "answered";
writePromptRecord(newest);
// Record in between
const middle = createPromptRecord({
id: "mmm-middle",
channel: "slack",
createdAt: 2000,
timeoutAt: 9999,
pollIntervalMs: 5000,
questions: [],
});
middle.updatedAt = 2000;
writePromptRecord(middle);
const latest = getLatestPromptSummary();
// Should return "aaa-newest" (updatedAt=3000), NOT "zzz-oldest" (alphabetically last)
assert.equal(latest?.id, "aaa-newest", "should pick the most recently updated prompt, not the alphabetically last filename");
assert.equal(latest?.status, "answered");
assert.equal(latest?.updatedAt, 3000);
}));

View file

@ -16,8 +16,16 @@ export interface LatestPromptSummary {
export function getLatestPromptSummary(): LatestPromptSummary | null {
const runtimeDir = join(homedir(), ".gsd", "runtime", "remote-questions");
if (!existsSync(runtimeDir)) return null;
const files = readdirSync(runtimeDir).filter((f) => f.endsWith(".json")).sort().reverse();
const files = readdirSync(runtimeDir).filter((f) => f.endsWith(".json"));
if (files.length === 0) return null;
const record = readPromptRecord(files[0].replace(/\.json$/, ""));
return record ? { id: record.id, status: record.status, updatedAt: record.updatedAt } : null;
let latest: LatestPromptSummary | null = null;
for (const file of files) {
const record = readPromptRecord(file.replace(/\.json$/, ""));
if (!record) continue;
if (!latest || record.updatedAt > latest.updatedAt) {
latest = { id: record.id, status: record.status, updatedAt: record.updatedAt };
}
}
return latest;
}