feat(events): add phase3 trail report contracts
This commit is contained in:
parent
27c4879668
commit
e6b58b7187
@ -15,6 +15,7 @@ import {
|
|||||||
Phase1EcosystemEventSchema,
|
Phase1EcosystemEventSchema,
|
||||||
Phase1EcosystemEventSchemas,
|
Phase1EcosystemEventSchemas,
|
||||||
RoutineArtifactEnvelopeSchema,
|
RoutineArtifactEnvelopeSchema,
|
||||||
|
TrailReportArtifactEnvelopeSchema,
|
||||||
} from './ecosystem.js';
|
} from './ecosystem.js';
|
||||||
|
|
||||||
describe('phase1 ecosystem contracts', () => {
|
describe('phase1 ecosystem contracts', () => {
|
||||||
@ -290,3 +291,111 @@ describe('phase2 ecosystem contract extensions', () => {
|
|||||||
expect(linked.payload.relation).toBe('generated-habit');
|
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),
|
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({
|
export const TranscriptArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
||||||
artifactType: z.literal('transcript'),
|
artifactType: z.literal('transcript'),
|
||||||
payload: TranscriptPayloadSchema,
|
payload: TranscriptPayloadSchema,
|
||||||
@ -192,6 +223,11 @@ export const HabitArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
|||||||
payload: HabitPayloadSchema,
|
payload: HabitPayloadSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const TrailReportArtifactEnvelopeSchema = BaseArtifactEnvelopeSchema.extend({
|
||||||
|
artifactType: z.literal('trail-report'),
|
||||||
|
payload: TrailReportPayloadSchema,
|
||||||
|
});
|
||||||
|
|
||||||
export const Phase1ArtifactEnvelopeSchema = z.discriminatedUnion('artifactType', [
|
export const Phase1ArtifactEnvelopeSchema = z.discriminatedUnion('artifactType', [
|
||||||
TranscriptArtifactEnvelopeSchema,
|
TranscriptArtifactEnvelopeSchema,
|
||||||
NoteArtifactEnvelopeSchema,
|
NoteArtifactEnvelopeSchema,
|
||||||
@ -234,7 +270,15 @@ export const CaptureTranscriptCreatedPayloadSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const ArtifactCreatedPayloadSchema = 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(),
|
title: z.string().min(1).nullable(),
|
||||||
status: z.string().min(1),
|
status: z.string().min(1),
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user