feat(events): add phase3 trail report contracts
This commit is contained in:
parent
27c4879668
commit
e6b58b7187
@ -15,6 +15,7 @@ import {
|
||||
Phase1EcosystemEventSchema,
|
||||
Phase1EcosystemEventSchemas,
|
||||
RoutineArtifactEnvelopeSchema,
|
||||
TrailReportArtifactEnvelopeSchema,
|
||||
} from './ecosystem.js';
|
||||
|
||||
describe('phase1 ecosystem contracts', () => {
|
||||
@ -290,3 +291,111 @@ describe('phase2 ecosystem contract extensions', () => {
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
@ -162,6 +162,37 @@ export const HabitPayloadSchema = z.object({
|
||||
sourceRoutineId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const TrailReportPayloadSchema = z.object({
|
||||
sourceProduct: z.literal('claw-cowork'),
|
||||
sourceTaskId: z.string().min(1).nullable().optional(),
|
||||
generatedFrom: z.enum(['audit-export-json', 'audit-query-json']),
|
||||
reportGeneratedAt: z.string().datetime(),
|
||||
actionCount: z.number().int().nonnegative(),
|
||||
toolCallCount: z.number().int().nonnegative(),
|
||||
approvalCount: z.number().int().nonnegative(),
|
||||
failureCount: z.number().int().nonnegative(),
|
||||
safetySignalCount: z.number().int().nonnegative(),
|
||||
tasks: z.array(z.string().min(1)),
|
||||
actionBreakdown: z.array(
|
||||
z.object({
|
||||
action: z.string().min(1),
|
||||
count: z.number().int().positive(),
|
||||
})
|
||||
),
|
||||
entries: z.array(
|
||||
z.object({
|
||||
timestamp: z.string().datetime(),
|
||||
taskId: z.string().min(1).nullable(),
|
||||
action: z.string().min(1),
|
||||
tool: z.string().min(1).nullable().optional(),
|
||||
result: z.string().min(1).nullable().optional(),
|
||||
approval: z.string().min(1).nullable().optional(),
|
||||
inputSummary: z.string().min(1).nullable().optional(),
|
||||
metadata: z.record(z.unknown()).nullable().optional(),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export const TranscriptArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
||||
artifactType: z.literal('transcript'),
|
||||
payload: TranscriptPayloadSchema,
|
||||
@ -192,6 +223,11 @@ export const HabitArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
||||
payload: HabitPayloadSchema,
|
||||
});
|
||||
|
||||
export const TrailReportArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
||||
artifactType: z.literal('trail-report'),
|
||||
payload: TrailReportPayloadSchema,
|
||||
});
|
||||
|
||||
export const Phase1ArtifactEnvelopeSchema = z.discriminatedUnion('artifactType', [
|
||||
TranscriptArtifactEnvelopeSchema,
|
||||
NoteArtifactEnvelopeSchema,
|
||||
@ -234,7 +270,15 @@ export const CaptureTranscriptCreatedPayloadSchema = z.object({
|
||||
});
|
||||
|
||||
export const ArtifactCreatedPayloadSchema = z.object({
|
||||
artifactType: z.enum(['transcript', 'note', 'memory', 'plan', 'routine', 'habit']),
|
||||
artifactType: z.enum([
|
||||
'transcript',
|
||||
'note',
|
||||
'memory',
|
||||
'plan',
|
||||
'routine',
|
||||
'habit',
|
||||
'trail-report',
|
||||
]),
|
||||
title: z.string().min(1).nullable(),
|
||||
status: z.string().min(1),
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user