fix(notes): preserve phase1 transcript event lineage
This commit is contained in:
parent
6ffc2f8755
commit
9ecc7c6bf5
@ -5,6 +5,7 @@ import { join } from 'node:path';
|
||||
import {
|
||||
buildPhase1NoteImport,
|
||||
loadLatestTranscriptArtifact,
|
||||
loadLatestTranscriptCaptureEvent,
|
||||
persistPhase1NoteOutputs,
|
||||
} from './ecosystem-phase1.js';
|
||||
|
||||
@ -55,10 +56,45 @@ describe('ecosystem phase1 note import', () => {
|
||||
`${JSON.stringify(transcriptArtifact, null, 2)}\n`,
|
||||
'utf-8'
|
||||
);
|
||||
await writeFile(
|
||||
join(root, 'indexes', 'latest-transcript-event.json'),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
eventId: 'evt_capture_123',
|
||||
eventName: 'capture.transcript.created',
|
||||
eventVersion: 1,
|
||||
occurredAt: '2026-04-03T18:15:00.000Z',
|
||||
productId: 'lysnrai',
|
||||
sourceSurface: 'desktop',
|
||||
userId: 'user_saravana',
|
||||
orgId: null,
|
||||
sessionId: 'sess_123',
|
||||
runId: null,
|
||||
artifactId: 'art_transcript_123',
|
||||
actor: { actorType: 'user', actorId: 'user_saravana' },
|
||||
trace: {
|
||||
correlationId: 'corr_123',
|
||||
causationId: null,
|
||||
parentEventId: null,
|
||||
},
|
||||
payload: {
|
||||
artifactId: 'art_transcript_123',
|
||||
durationMs: 1000,
|
||||
language: 'en',
|
||||
transcriptSource: 'microphone',
|
||||
},
|
||||
},
|
||||
null,
|
||||
2
|
||||
)}\n`,
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
const loaded = await loadLatestTranscriptArtifact(root);
|
||||
const transcriptCaptureEvent = await loadLatestTranscriptCaptureEvent(root);
|
||||
const generated = buildPhase1NoteImport({
|
||||
transcriptArtifact: loaded,
|
||||
transcriptCaptureEvent,
|
||||
workspaceId: 'ws_phase1',
|
||||
userId: 'user_saravana',
|
||||
now: '2026-04-03T18:17:00.000Z',
|
||||
@ -88,6 +124,18 @@ describe('ecosystem phase1 note import', () => {
|
||||
expect(savedNoteArtifact.payload.noteFormat).toBe('markdown');
|
||||
expect(savedLinkedEvent.payload.targetArtifactId).toBe('art_transcript_123');
|
||||
expect(savedLinkedEvent.payload.relation).toBe('summarizes');
|
||||
expect(generated.createdEvent.trace.causationId).toBe('evt_capture_123');
|
||||
expect(generated.createdEvent.trace.parentEventId).toBe('evt_capture_123');
|
||||
expect(savedLinkedEvent.trace.causationId).toBe(generated.createdEvent.eventId);
|
||||
|
||||
const savedCreatedEventIndex = JSON.parse(
|
||||
await readFile(join(root, 'indexes', 'latest-note-created-event.json'), 'utf-8')
|
||||
);
|
||||
const savedLinkedEventIndex = JSON.parse(
|
||||
await readFile(join(root, 'indexes', 'latest-note-linked-event.json'), 'utf-8')
|
||||
);
|
||||
expect(savedCreatedEventIndex.eventId).toBe(generated.createdEvent.eventId);
|
||||
expect(savedLinkedEventIndex.eventId).toBe(generated.linkedEvent.eventId);
|
||||
|
||||
await rm(root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
@ -64,6 +64,11 @@ type EcosystemEvent = {
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type TranscriptCaptureEvent = EcosystemEvent & {
|
||||
eventName: 'capture.transcript.created';
|
||||
artifactId: string;
|
||||
};
|
||||
|
||||
type NoteArtifactEnvelope = {
|
||||
id: string;
|
||||
artifactType: 'note';
|
||||
@ -108,8 +113,23 @@ export async function loadLatestTranscriptArtifact(root = getPhase1Root()): Prom
|
||||
return JSON.parse(raw) as TranscriptArtifact;
|
||||
}
|
||||
|
||||
export async function loadLatestTranscriptCaptureEvent(
|
||||
root = getPhase1Root()
|
||||
): Promise<TranscriptCaptureEvent | null> {
|
||||
try {
|
||||
const raw = await readFile(join(root, 'indexes', 'latest-transcript-event.json'), 'utf-8');
|
||||
return JSON.parse(raw) as TranscriptCaptureEvent;
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function buildPhase1NoteImport(params: {
|
||||
transcriptArtifact: TranscriptArtifact;
|
||||
transcriptCaptureEvent?: TranscriptCaptureEvent | null;
|
||||
workspaceId: string;
|
||||
userId: string;
|
||||
now?: string;
|
||||
@ -233,8 +253,8 @@ export function buildPhase1NoteImport(params: {
|
||||
},
|
||||
trace: {
|
||||
correlationId,
|
||||
causationId: null,
|
||||
parentEventId: null,
|
||||
causationId: params.transcriptCaptureEvent?.eventId ?? null,
|
||||
parentEventId: params.transcriptCaptureEvent?.eventId ?? null,
|
||||
},
|
||||
payload: {
|
||||
artifactType: 'note',
|
||||
@ -285,6 +305,8 @@ export async function persistPhase1NoteOutputs(params: {
|
||||
await writeJson(join(root, 'events', 'artifact.created', `${params.createdEvent.eventId}.json`), params.createdEvent);
|
||||
await writeJson(join(root, 'events', 'artifact.linked', `${params.linkedEvent.eventId}.json`), params.linkedEvent);
|
||||
await writeJson(join(root, 'indexes', 'latest-note.json'), params.ecosystemNoteArtifact);
|
||||
await writeJson(join(root, 'indexes', 'latest-note-created-event.json'), params.createdEvent);
|
||||
await writeJson(join(root, 'indexes', 'latest-note-linked-event.json'), params.linkedEvent);
|
||||
}
|
||||
|
||||
async function writeJson(path: string, payload: unknown): Promise<void> {
|
||||
|
||||
@ -7,6 +7,7 @@ import { createNoteArtifact } from '../note-artifacts/repository.js';
|
||||
import {
|
||||
buildPhase1NoteImport,
|
||||
loadLatestTranscriptArtifact,
|
||||
loadLatestTranscriptCaptureEvent,
|
||||
persistPhase1NoteOutputs,
|
||||
} from '../../lib/ecosystem-phase1.js';
|
||||
|
||||
@ -23,8 +24,10 @@ export async function ecosystemPhase1Routes(app: FastifyInstance) {
|
||||
}
|
||||
|
||||
const transcriptArtifact = await loadLatestTranscriptArtifact();
|
||||
const transcriptCaptureEvent = await loadLatestTranscriptCaptureEvent();
|
||||
const generated = buildPhase1NoteImport({
|
||||
transcriptArtifact,
|
||||
transcriptCaptureEvent,
|
||||
workspaceId: parsed.data.workspaceId,
|
||||
userId: auth.sub,
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user