import { randomUUID } from 'node:crypto'; import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { homedir } from 'node:os'; import { dirname, join } from 'node:path'; import type { NoteArtifactDoc } from '../modules/note-artifacts/types.js'; import type { NoteDoc } from '../modules/notes/types.js'; const DEFAULT_PHASE3_ROOT = join(homedir(), '.bytelyst', 'ecosystem', 'phase3'); type TrailReportArtifact = { id: string; title: string; summary: string; ownership: { userId: string; orgId?: string | null; }; provenance: { sessionId?: string | null; correlationId?: string | null; lineage: Array<{ stepType: string; productId: string; actorType: 'user' | 'agent' | 'system'; timestamp: string; }>; }; payload: { sourceProduct: 'claw-cowork'; sourceTaskId?: string | null; reportGeneratedAt: string; actionCount: number; toolCallCount: number; approvalCount: number; failureCount: number; safetySignalCount: number; actionBreakdown: Array<{ action: string; count: number; }>; entries: Array<{ timestamp: string; taskId: string | null; action: string; tool?: string | null; result?: string | null; approval?: string | null; inputSummary?: string | null; }>; }; }; type TrailReportCreatedEvent = { eventId: string; eventName: 'artifact.created'; trace: { correlationId: string | null; causationId: string | null; parentEventId: string | null; }; }; type NoteArtifactEnvelope = { id: string; artifactType: 'note'; schemaVersion: 1; productId: 'notelett'; sourceSurface: 'backend'; title: string; summary: string; createdAt: string; updatedAt: string; createdBy: { actorType: 'agent'; actorId: string; }; ownership: { userId: string; orgId?: string | null; }; visibility: { scope: 'private'; allowedProducts: ['learning_multimodal_memory_agents']; }; status: 'draft'; tags: string[]; links: Array<{ relation: 'summarizes'; targetArtifactId: string; }>; provenance: TrailReportArtifact['provenance'] & { runId: string; }; payload: { noteFormat: 'markdown'; body: string; excerpt: string; }; }; type EcosystemEvent = { eventId: string; eventName: 'artifact.created' | 'artifact.linked'; eventVersion: 1; occurredAt: string; productId: 'notelett'; sourceSurface: 'backend'; userId: string; orgId?: string | null; sessionId?: string | null; runId: string; artifactId: string; actor: { actorType: 'agent'; actorId: string; }; trace: { correlationId: string | null; causationId: string | null; parentEventId: string | null; }; payload: Record; }; export function getPhase3Root(): string { return process.env.BYTELYST_ECOSYSTEM_DIR ?? DEFAULT_PHASE3_ROOT; } export async function loadLatestTrailReportArtifact(root = getPhase3Root()): Promise { const raw = await readFile(join(root, 'indexes', 'latest-trail-report.json'), 'utf-8'); return JSON.parse(raw) as TrailReportArtifact; } export async function loadLatestTrailReportCreatedEvent( root = getPhase3Root() ): Promise { try { const raw = await readFile(join(root, 'indexes', 'latest-trail-report-created-event.json'), 'utf-8'); return JSON.parse(raw) as TrailReportCreatedEvent; } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') { return null; } throw error; } } export function buildPhase3TrailNoteImport(params: { trailReportArtifact: TrailReportArtifact; trailReportCreatedEvent?: TrailReportCreatedEvent | null; workspaceId: string; userId: string; root?: string; now?: string; }) { const now = params.now ?? new Date().toISOString(); const noteId = `note_phase3_${randomUUID().replace(/-/g, '').slice(0, 12)}`; const noteArtifactId = `art_note_${randomUUID().replace(/-/g, '').slice(0, 12)}`; const runId = `run_note_${randomUUID().replace(/-/g, '').slice(0, 10)}`; const title = params.trailReportArtifact.title || 'Imported audit note'; const breakdown = params.trailReportArtifact.payload.actionBreakdown .slice(0, 5) .map(item => `- ${item.action}: ${item.count}`) .join('\n'); const evidence = params.trailReportArtifact.payload.entries .slice(0, 3) .map( entry => `- ${entry.timestamp} | ${entry.action}${entry.tool ? ` (${entry.tool})` : ''}${entry.inputSummary ? ` — ${entry.inputSummary}` : ''}` ) .join('\n'); const body = [ `# ${title}`, '', params.trailReportArtifact.summary, '', `Source product: ${params.trailReportArtifact.payload.sourceProduct}`, `Source task: ${params.trailReportArtifact.payload.sourceTaskId ?? 'n/a'}`, `Action count: ${params.trailReportArtifact.payload.actionCount}`, `Safety signals: ${params.trailReportArtifact.payload.safetySignalCount}`, '', '## Action Breakdown', breakdown || '- none', '', '## Evidence', evidence || '- none', ].join('\n'); const excerpt = `${params.trailReportArtifact.payload.actionCount} audited actions imported from Cowork`; const note: NoteDoc = { id: noteId, productId: 'notelett', workspaceId: params.workspaceId, userId: params.userId, title, body, status: 'draft', tags: ['ecosystem', 'phase3', 'audit'], links: [params.trailReportArtifact.id], sourceType: 'ecosystem-trail-report', sourceUri: params.trailReportArtifact.id, createdAt: now, updatedAt: now, createdBy: params.userId, updatedBy: params.userId, agentId: 'phase3-trail-importer', }; const noteArtifactDoc: NoteArtifactDoc = { id: `na_${randomUUID().replace(/-/g, '').slice(0, 12)}`, productId: 'notelett', workspaceId: params.workspaceId, userId: params.userId, noteId, artifactType: 'summary', title: 'Imported trail report artifact', description: `Audit trail source ${params.trailReportArtifact.id}`, blobPath: join(params.root ?? getPhase3Root(), 'artifacts', 'note', `${noteArtifactId}.json`), contentType: 'application/json', createdAt: now, createdBy: params.userId, updatedAt: now, updatedBy: params.userId, }; const ecosystemNoteArtifact: NoteArtifactEnvelope = { id: noteArtifactId, artifactType: 'note', schemaVersion: 1, productId: 'notelett', sourceSurface: 'backend', title, summary: excerpt, createdAt: now, updatedAt: now, createdBy: { actorType: 'agent', actorId: 'phase3-trail-importer', }, ownership: { userId: params.userId, orgId: params.trailReportArtifact.ownership.orgId ?? null, }, visibility: { scope: 'private', allowedProducts: ['learning_multimodal_memory_agents'], }, status: 'draft', tags: ['ecosystem', 'phase3', 'audit'], links: [ { relation: 'summarizes', targetArtifactId: params.trailReportArtifact.id, }, ], provenance: { ...params.trailReportArtifact.provenance, runId, lineage: [ ...params.trailReportArtifact.provenance.lineage, { stepType: 'audit-note-created', productId: 'notelett', actorType: 'agent', timestamp: now, }, ], }, payload: { noteFormat: 'markdown', body, excerpt, }, }; const createdEvent: EcosystemEvent = { eventId: `evt_note_created_${randomUUID().replace(/-/g, '').slice(0, 12)}`, eventName: 'artifact.created', eventVersion: 1, occurredAt: now, productId: 'notelett', sourceSurface: 'backend', userId: params.userId, orgId: params.trailReportArtifact.ownership.orgId ?? null, sessionId: params.trailReportArtifact.provenance.sessionId ?? null, runId, artifactId: ecosystemNoteArtifact.id, actor: { actorType: 'agent', actorId: 'phase3-trail-importer', }, trace: { correlationId: params.trailReportArtifact.provenance.correlationId ?? null, causationId: params.trailReportCreatedEvent?.eventId ?? null, parentEventId: params.trailReportCreatedEvent?.eventId ?? null, }, payload: { artifactType: 'note', title, status: 'draft', }, }; const linkedEvent: EcosystemEvent = { eventId: `evt_note_linked_${randomUUID().replace(/-/g, '').slice(0, 12)}`, eventName: 'artifact.linked', eventVersion: 1, occurredAt: now, productId: 'notelett', sourceSurface: 'backend', userId: params.userId, orgId: params.trailReportArtifact.ownership.orgId ?? null, sessionId: params.trailReportArtifact.provenance.sessionId ?? null, runId, artifactId: ecosystemNoteArtifact.id, actor: { actorType: 'agent', actorId: 'phase3-trail-importer', }, trace: { correlationId: params.trailReportArtifact.provenance.correlationId ?? null, causationId: createdEvent.eventId, parentEventId: createdEvent.eventId, }, payload: { sourceArtifactId: ecosystemNoteArtifact.id, targetArtifactId: params.trailReportArtifact.id, relation: 'summarizes', }, }; return { note, noteArtifactDoc, ecosystemNoteArtifact, createdEvent, linkedEvent }; } export async function persistPhase3NoteOutputs(params: { ecosystemNoteArtifact: NoteArtifactEnvelope; createdEvent: EcosystemEvent; linkedEvent: EcosystemEvent; root?: string; }) { const root = params.root ?? getPhase3Root(); await writeJson(join(root, 'artifacts', 'note', `${params.ecosystemNoteArtifact.id}.json`), params.ecosystemNoteArtifact); 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) { await mkdir(dirname(path), { recursive: true }); await writeFile(path, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8'); }