402 lines
13 KiB
TypeScript
402 lines
13 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import transcriptArtifact from '../fixtures/ecosystem/phase1/transcript-artifact.json' with { type: 'json' };
|
|
import noteArtifact from '../fixtures/ecosystem/phase1/note-artifact.json' with { type: 'json' };
|
|
import memoryArtifact from '../fixtures/ecosystem/phase1/memory-artifact.json' with { type: 'json' };
|
|
import captureTranscriptCreatedEvent from '../fixtures/ecosystem/phase1/capture-transcript-created.event.json' with { type: 'json' };
|
|
import artifactCreatedEvent from '../fixtures/ecosystem/phase1/artifact-created.event.json' with { type: 'json' };
|
|
import artifactLinkedEvent from '../fixtures/ecosystem/phase1/artifact-linked.event.json' with { type: 'json' };
|
|
import memoryEntryCreatedEvent from '../fixtures/ecosystem/phase1/memory-entry-created.event.json' with { type: 'json' };
|
|
import {
|
|
ArtifactCreatedEventSchema,
|
|
ArtifactLinkedEventSchema,
|
|
HabitArtifactEnvelopeSchema,
|
|
PlanArtifactEnvelopeSchema,
|
|
Phase1ArtifactEnvelopeSchema,
|
|
Phase1EcosystemEventSchema,
|
|
Phase1EcosystemEventSchemas,
|
|
RoutineArtifactEnvelopeSchema,
|
|
TrailReportArtifactEnvelopeSchema,
|
|
} from './ecosystem.js';
|
|
|
|
describe('phase1 ecosystem contracts', () => {
|
|
it('validates canonical transcript, note, and memory artifacts', () => {
|
|
const transcript = Phase1ArtifactEnvelopeSchema.parse(transcriptArtifact);
|
|
const note = Phase1ArtifactEnvelopeSchema.parse(noteArtifact);
|
|
const memory = Phase1ArtifactEnvelopeSchema.parse(memoryArtifact);
|
|
|
|
expect(transcript.artifactType).toBe('transcript');
|
|
expect(note.links).toContainEqual({
|
|
relation: 'summarizes',
|
|
targetArtifactId: transcript.id,
|
|
});
|
|
expect(memory.links).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
relation: 'generated-memory',
|
|
targetArtifactId: note.id,
|
|
},
|
|
])
|
|
);
|
|
});
|
|
|
|
it('validates canonical phase1 events', () => {
|
|
const events = [
|
|
captureTranscriptCreatedEvent,
|
|
artifactCreatedEvent,
|
|
artifactLinkedEvent,
|
|
memoryEntryCreatedEvent,
|
|
].map(event => Phase1EcosystemEventSchema.parse(event));
|
|
|
|
expect(events.map(event => event.eventName)).toEqual([
|
|
'capture.transcript.created',
|
|
'artifact.created',
|
|
'artifact.linked',
|
|
'memory.entry.created',
|
|
]);
|
|
});
|
|
|
|
it('exposes event-specific schemas keyed by canonical event name', () => {
|
|
const created = Phase1EcosystemEventSchemas['artifact.created'].parse(artifactCreatedEvent);
|
|
const linked = Phase1EcosystemEventSchemas['artifact.linked'].parse(artifactLinkedEvent);
|
|
|
|
expect(created.payload.artifactType).toBe('note');
|
|
expect(linked.payload.relation).toBe('summarizes');
|
|
});
|
|
});
|
|
|
|
describe('phase2 ecosystem contract extensions', () => {
|
|
it('validates canonical plan, routine, and habit artifacts', () => {
|
|
const plan = PlanArtifactEnvelopeSchema.parse({
|
|
id: 'art_plan_demo',
|
|
artifactType: 'plan',
|
|
schemaVersion: 1,
|
|
productId: 'flowmonk',
|
|
sourceSurface: 'backend',
|
|
title: 'FlowMonk weekly plan',
|
|
summary: 'Three focused execution blocks',
|
|
createdAt: '2026-04-03T12:00:00.000Z',
|
|
updatedAt: '2026-04-03T12:00:00.000Z',
|
|
createdBy: { actorType: 'agent', actorId: 'phase2-plan-exporter' },
|
|
ownership: { userId: 'saravana', orgId: null },
|
|
visibility: {
|
|
scope: 'private',
|
|
allowedProducts: ['learning_ai_clock', 'learning_ai_efforise'],
|
|
},
|
|
status: 'draft',
|
|
tags: ['ecosystem', 'phase2', 'plan'],
|
|
links: [],
|
|
provenance: {
|
|
originProductId: 'flowmonk',
|
|
originActionId: 'plan_export_1',
|
|
sessionId: 'sess_phase2',
|
|
runId: 'run_phase2_plan',
|
|
approvalId: null,
|
|
correlationId: 'corr_phase2',
|
|
lineage: [
|
|
{
|
|
stepType: 'plan-exported',
|
|
productId: 'flowmonk',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:00:00.000Z',
|
|
},
|
|
],
|
|
},
|
|
payload: {
|
|
weekOf: '2026-04-07',
|
|
taskCount: 3,
|
|
scheduledEntryCount: 3,
|
|
totalScheduledMinutes: 165,
|
|
entries: [
|
|
{
|
|
taskTitle: 'Architecture review',
|
|
scheduledDate: '2026-04-07',
|
|
startTime: '08:00',
|
|
endTime: '09:00',
|
|
durationMinutes: 60,
|
|
flowName: 'Deep Work',
|
|
zoneName: 'Studio',
|
|
priority: 'high',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const routine = RoutineArtifactEnvelopeSchema.parse({
|
|
id: 'art_routine_demo',
|
|
artifactType: 'routine',
|
|
schemaVersion: 1,
|
|
productId: 'chronomind',
|
|
sourceSurface: 'backend',
|
|
title: 'Routine from FlowMonk weekly plan',
|
|
summary: 'Three-step execution routine',
|
|
createdAt: '2026-04-03T12:05:00.000Z',
|
|
updatedAt: '2026-04-03T12:05:00.000Z',
|
|
createdBy: { actorType: 'agent', actorId: 'phase2-routine-importer' },
|
|
ownership: { userId: 'saravana', orgId: null },
|
|
visibility: { scope: 'private' },
|
|
status: 'ready',
|
|
tags: ['ecosystem', 'phase2', 'routine'],
|
|
links: [{ relation: 'generated-routine', targetArtifactId: plan.id }],
|
|
provenance: {
|
|
originProductId: 'flowmonk',
|
|
originActionId: 'plan_export_1',
|
|
sessionId: 'sess_phase2',
|
|
runId: 'run_phase2_routine',
|
|
approvalId: null,
|
|
correlationId: 'corr_phase2',
|
|
lineage: [
|
|
{
|
|
stepType: 'plan-exported',
|
|
productId: 'flowmonk',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:00:00.000Z',
|
|
},
|
|
{
|
|
stepType: 'routine-created',
|
|
productId: 'chronomind',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:05:00.000Z',
|
|
},
|
|
],
|
|
},
|
|
payload: {
|
|
routineId: 'routine_demo',
|
|
stepCount: 3,
|
|
totalDurationMinutes: 165,
|
|
status: 'ready',
|
|
isTemplate: true,
|
|
category: 'phase2-import',
|
|
steps: [
|
|
{
|
|
label: 'Architecture review',
|
|
durationMinutes: 60,
|
|
transition: '5m_break',
|
|
status: 'pending',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const habit = HabitArtifactEnvelopeSchema.parse({
|
|
id: 'art_habit_demo',
|
|
artifactType: 'habit',
|
|
schemaVersion: 1,
|
|
productId: 'efforise',
|
|
sourceSurface: 'backend',
|
|
title: 'Habit from FlowMonk weekly plan',
|
|
summary: 'Practice the imported routine daily',
|
|
createdAt: '2026-04-03T12:10:00.000Z',
|
|
updatedAt: '2026-04-03T12:10:00.000Z',
|
|
createdBy: { actorType: 'agent', actorId: 'phase2-habit-importer' },
|
|
ownership: { userId: 'saravana', orgId: null },
|
|
visibility: { scope: 'private' },
|
|
status: 'active',
|
|
tags: ['ecosystem', 'phase2', 'habit'],
|
|
links: [{ relation: 'generated-habit', targetArtifactId: routine.id }],
|
|
provenance: {
|
|
originProductId: 'flowmonk',
|
|
originActionId: 'plan_export_1',
|
|
sessionId: 'sess_phase2',
|
|
runId: 'run_phase2_habit',
|
|
approvalId: null,
|
|
correlationId: 'corr_phase2',
|
|
lineage: [
|
|
{
|
|
stepType: 'plan-exported',
|
|
productId: 'flowmonk',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:00:00.000Z',
|
|
},
|
|
{
|
|
stepType: 'routine-created',
|
|
productId: 'chronomind',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:05:00.000Z',
|
|
},
|
|
{
|
|
stepType: 'habit-created',
|
|
productId: 'efforise',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T12:10:00.000Z',
|
|
},
|
|
],
|
|
},
|
|
payload: {
|
|
habitId: 'habit_demo',
|
|
identityId: 'identity_phase2',
|
|
frequency: 'daily',
|
|
targetCount: 1,
|
|
reminderTime: '08:00',
|
|
isActive: true,
|
|
sourceRoutineId: 'routine_demo',
|
|
},
|
|
});
|
|
|
|
expect(routine.links[0]?.targetArtifactId).toBe(plan.id);
|
|
expect(habit.links[0]?.targetArtifactId).toBe(routine.id);
|
|
});
|
|
|
|
it('accepts generic artifact.created and artifact.linked events for phase2 artifact types', () => {
|
|
const created = ArtifactCreatedEventSchema.parse({
|
|
eventId: 'evt_phase2_created',
|
|
eventName: 'artifact.created',
|
|
eventVersion: 1,
|
|
occurredAt: '2026-04-03T12:05:00.000Z',
|
|
productId: 'chronomind',
|
|
sourceSurface: 'backend',
|
|
userId: 'saravana',
|
|
orgId: null,
|
|
sessionId: 'sess_phase2',
|
|
runId: 'run_phase2_routine',
|
|
artifactId: 'art_routine_demo',
|
|
actor: { actorType: 'agent', actorId: 'phase2-routine-importer' },
|
|
trace: {
|
|
correlationId: 'corr_phase2',
|
|
causationId: 'evt_phase2_plan',
|
|
parentEventId: 'evt_phase2_plan',
|
|
},
|
|
payload: {
|
|
artifactType: 'routine',
|
|
title: 'Routine from FlowMonk weekly plan',
|
|
status: 'ready',
|
|
},
|
|
});
|
|
|
|
const linked = ArtifactLinkedEventSchema.parse({
|
|
eventId: 'evt_phase2_linked',
|
|
eventName: 'artifact.linked',
|
|
eventVersion: 1,
|
|
occurredAt: '2026-04-03T12:10:00.000Z',
|
|
productId: 'efforise',
|
|
sourceSurface: 'backend',
|
|
userId: 'saravana',
|
|
orgId: null,
|
|
sessionId: 'sess_phase2',
|
|
runId: 'run_phase2_habit',
|
|
artifactId: 'art_habit_demo',
|
|
actor: { actorType: 'agent', actorId: 'phase2-habit-importer' },
|
|
trace: {
|
|
correlationId: 'corr_phase2',
|
|
causationId: 'evt_phase2_created',
|
|
parentEventId: 'evt_phase2_created',
|
|
},
|
|
payload: {
|
|
sourceArtifactId: 'art_habit_demo',
|
|
targetArtifactId: 'art_routine_demo',
|
|
relation: 'generated-habit',
|
|
},
|
|
});
|
|
|
|
expect(created.payload.artifactType).toBe('routine');
|
|
expect(linked.payload.relation).toBe('generated-habit');
|
|
});
|
|
});
|
|
|
|
describe('phase3 ecosystem contract extensions', () => {
|
|
it('validates canonical trail-report artifacts', () => {
|
|
const trailReport = TrailReportArtifactEnvelopeSchema.parse({
|
|
id: 'art_trail_demo',
|
|
artifactType: 'trail-report',
|
|
schemaVersion: 1,
|
|
productId: 'actiontrail',
|
|
sourceSurface: 'backend',
|
|
title: 'Cowork audit report for task task-123',
|
|
summary: '4 audited actions with 1 safety signal',
|
|
createdAt: '2026-04-03T14:00:00.000Z',
|
|
updatedAt: '2026-04-03T14:00:00.000Z',
|
|
createdBy: { actorType: 'agent', actorId: 'phase3-audit-importer' },
|
|
ownership: { userId: 'saravana', orgId: null },
|
|
visibility: {
|
|
scope: 'private',
|
|
allowedProducts: ['learning_ai_notes', 'learning_multimodal_memory_agents'],
|
|
},
|
|
status: 'recorded',
|
|
tags: ['ecosystem', 'phase3', 'audit'],
|
|
links: [],
|
|
provenance: {
|
|
originProductId: 'claw-cowork',
|
|
originActionId: 'task-123',
|
|
sessionId: 'sess_phase3',
|
|
runId: 'run_phase3_trail',
|
|
approvalId: null,
|
|
correlationId: 'corr_phase3',
|
|
lineage: [
|
|
{
|
|
stepType: 'audit-exported',
|
|
productId: 'claw-cowork',
|
|
actorType: 'system',
|
|
timestamp: '2026-04-03T13:55:00.000Z',
|
|
},
|
|
{
|
|
stepType: 'trail-report-created',
|
|
productId: 'actiontrail',
|
|
actorType: 'agent',
|
|
timestamp: '2026-04-03T14:00:00.000Z',
|
|
},
|
|
],
|
|
},
|
|
payload: {
|
|
sourceProduct: 'claw-cowork',
|
|
sourceTaskId: 'task-123',
|
|
generatedFrom: 'audit-export-json',
|
|
reportGeneratedAt: '2026-04-03T14:00:00.000Z',
|
|
actionCount: 4,
|
|
toolCallCount: 2,
|
|
approvalCount: 1,
|
|
failureCount: 0,
|
|
safetySignalCount: 1,
|
|
tasks: ['task-123'],
|
|
actionBreakdown: [
|
|
{ action: 'TaskStarted', count: 1 },
|
|
{ action: 'ToolCall', count: 2 },
|
|
{ action: 'InjectionDetected', count: 1 },
|
|
],
|
|
entries: [
|
|
{
|
|
timestamp: '2026-04-03T13:55:00.000Z',
|
|
taskId: 'task-123',
|
|
action: 'TaskStarted',
|
|
tool: null,
|
|
result: 'Success',
|
|
approval: null,
|
|
inputSummary: 'Audit seed task',
|
|
metadata: { surface: 'desktop' },
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(trailReport.payload.sourceProduct).toBe('claw-cowork');
|
|
expect(trailReport.payload.safetySignalCount).toBe(1);
|
|
});
|
|
|
|
it('accepts generic artifact.created events for trail-report artifacts', () => {
|
|
const created = ArtifactCreatedEventSchema.parse({
|
|
eventId: 'evt_phase3_created',
|
|
eventName: 'artifact.created',
|
|
eventVersion: 1,
|
|
occurredAt: '2026-04-03T14:00:00.000Z',
|
|
productId: 'actiontrail',
|
|
sourceSurface: 'backend',
|
|
userId: 'saravana',
|
|
orgId: null,
|
|
sessionId: 'sess_phase3',
|
|
runId: 'run_phase3_trail',
|
|
artifactId: 'art_trail_demo',
|
|
actor: { actorType: 'agent', actorId: 'phase3-audit-importer' },
|
|
trace: {
|
|
correlationId: 'corr_phase3',
|
|
causationId: 'evt_cowork_export',
|
|
parentEventId: 'evt_cowork_export',
|
|
},
|
|
payload: {
|
|
artifactType: 'trail-report',
|
|
title: 'Cowork audit report for task task-123',
|
|
status: 'recorded',
|
|
},
|
|
});
|
|
|
|
expect(created.payload.artifactType).toBe('trail-report');
|
|
});
|
|
});
|