| ... | @@ -812,6 +812,37 @@ it.effect("decodes thread pull request links with snapshot and stack", () => | ... | @@ -812,6 +812,37 @@ it.effect("decodes thread pull request links with snapshot and stack", () => |
| 812 | }), | 812 | }), |
| 813 | ); | 813 | ); |
| 814 | | 814 | |
| | 815 | // A stored event that fails to decode stops the event store read, and with it |
| | 816 | // server startup, so rows written before `turnId` existed must still load. |
| | 817 | it.effect("decodes a legacy message-sent event persisted without turnId", () => |
| | 818 | Effect.gen(function* () { |
| | 819 | const event = yield* decodeOrchestrationEvent({ |
| | 820 | sequence: 539, |
| | 821 | eventId: "event-message-legacy-1", |
| | 822 | aggregateKind: "thread", |
| | 823 | aggregateId: "thread-1", |
| | 824 | type: "thread.message-sent", |
| | 825 | occurredAt: "2026-01-01T00:00:00.000Z", |
| | 826 | commandId: "cmd-message-legacy-1", |
| | 827 | causationEventId: null, |
| | 828 | correlationId: "cmd-message-legacy-1", |
| | 829 | metadata: {}, |
| | 830 | payload: { |
| | 831 | threadId: "thread-1", |
| | 832 | messageId: "message-1", |
| | 833 | role: "user", |
| | 834 | text: "written before turn ids were recorded", |
| | 835 | streaming: false, |
| | 836 | createdAt: "2026-01-01T00:00:00.000Z", |
| | 837 | updatedAt: "2026-01-01T00:00:00.000Z", |
| | 838 | }, |
| | 839 | }); |
| | 840 | assert.strictEqual(event.type, "thread.message-sent"); |
| | 841 | if (event.type !== "thread.message-sent") return; |
| | 842 | assert.strictEqual(event.payload.turnId, null); |
| | 843 | }), |
| | 844 | ); |
| | 845 | |
| 815 | it.effect("decodes thread archived and unarchived events", () => | 846 | it.effect("decodes thread archived and unarchived events", () => |
| 816 | Effect.gen(function* () { | 847 | Effect.gen(function* () { |
| 817 | const archived = yield* decodeOrchestrationEvent({ | 848 | const archived = yield* decodeOrchestrationEvent({ |