// Activity audit log schemas (historyRoot/activity.jsonl). import { z } from "zod"; import { AgentOriginSchema } from "./agent.js"; // One provider-agnostic event per agent↔provider interaction, appended only by the daemon; the log lives outside /work. // It is not tamper-evident (an unfenced agent can reach /history); the hash-chained audit trail (audit.ts) is. export const ActivityEventSchema = z.object({ id: z.string().describe("The entry's own id."), // Epoch ms; also the paging cursor. at: z.number().describe("When it happened, in milliseconds. Also what you page by."), // "discord", …; absent on provider-less system events (a cron automation.run). provider: z.string().optional().describe("Which outside service, when one was involved. Absent for the sandbox's own events."), // Which provider account handled it; attribution key for per-account usage, absent on provider-less or // default-account turns. account: z .string() .optional() .describe("Which account handled it. Absent for the sandbox's own events and for work run on a provider's default."), direction: z.enum(["in", "out", "system"]).describe("Whether something arrived, something went out, or the sandbox did it to itself."), // in: message.received, voice_utterance.received, voice_transcript.received // out: message.send, reaction.add, messages.read, api.call (unclassified endpoint) // system: gateway.login_failed, dispatch.failed, voice.session_started, voice.session_ended, automation.run, // turn.started, turn.plan, turn.error, turn.completed, rule.held_work, deps.verify_green, deps.verify_red, // deps.breakage_routed, deps.breakage_fixup, deps.breakage_waiting, deps.breakage_held, deps.breakage_resolved, // deps.breakage_spent; rule.blocked_push and rule.continued_turn are retired and only appear in older logs type: z .string() .describe( "Exactly what happened: a message received or sent, a reaction, a turn starting or ending, a rule doing something. A rule that ran and passed says nothing here, because a feed of passes is one the eye learns to skip.", ), channelId: z.string().optional().describe("Which channel or thread it happened in."), // Inbound author display name. author: z.string().optional().describe("Who sent it, for something that arrived."), // Distinct from `author` (the relayed sender) and `account` (who served it); absent for an unasked wake. actor: z .string() .optional() .describe( "Who asked for the turn, as the sandbox verified it: a member's email, token: