feat(FN-4219): complete Step 4 — add experiment executor runtime

Fusion-Task-Id: FN-4219
Fusion-Task-Lineage: 8d9a9ba6-6729-4376-b935-549e28a7fa35
This commit is contained in:
Fusion
2026-05-14 00:42:33 -07:00
committed by gsxdsm
parent a73cfc710b
commit 24bf18a233
5 changed files with 469 additions and 0 deletions

View File

@@ -158,6 +158,23 @@ describe("ExperimentSessionStore", () => {
expect(onRecord).not.toHaveBeenCalled();
});
it("updates run payload patch additively", () => {
const session = store.createSession({ name: "p", metric: { name: "x", direction: "maximize" } });
const run = store.appendRecord(session.id, {
type: "run",
payload: { primaryMetric: 9, secondaryMetrics: [], status: "keep" },
});
const updated = store.updateRecordPayload(run.id, { commit: "abc123" });
expect(updated.payload).toEqual({
primaryMetric: 9,
secondaryMetrics: [],
status: "keep",
commit: "abc123",
});
expect(store.getRecord(run.id)?.payload).toEqual(updated.payload);
});
it("recordKept is idempotent", () => {
const session = store.createSession({ name: "k", metric: { name: "x", direction: "maximize" } });
const run = store.appendRecord(session.id, {

View File

@@ -270,6 +270,28 @@ export class ExperimentSessionStore extends EventEmitter<ExperimentSessionStoreE
return this.updateSession(session.id, { bestRunId: runRecordId });
}
updateRecordPayload(recordId: string, patch: Partial<ExperimentSessionRecord["payload"]>): ExperimentSessionRecord {
const record = this.getRecord(recordId);
if (!record) throw new Error(`Experiment record not found: ${recordId}`);
const updated = {
...record,
payload: {
...record.payload,
...patch,
},
} as ExperimentSessionRecord;
this.db.prepare(`
UPDATE experiment_session_records
SET payload = ?
WHERE id = ?
`).run(toJson(updated.payload), recordId);
this.db.bumpLastModified();
return updated;
}
recordKept(sessionId: string, runRecordId: string): ExperimentSession {
const session = this.assertRunRecordOwnership(sessionId, runRecordId);
const keptRunIds = session.keptRunIds.includes(runRecordId)