@dispatch-foo/protocol 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-Ds8ZFZLh.js","names":["code: MessagingErrorCode","field?: string","MEMORY_GATE_ACTIONS: readonly string[]","PACKAGE_GATE_TYPES: ReadonlySet<string>","ASKING_KINDS: ReadonlySet<string>","LOCAL_ONLY_MARKERS: readonly string[]","carried: string[]","lastRandom: number[]","DEFAULT_LIMITS: EngineLimits","SYSTEM_SENDER: Sender","LOCAL: Placement","LOCAL_ONLY_TEXT: Record<LocalOnlyReason, string>","REMOTE_RANK: Record<RemoteState, number>","LOCAL_RANK: Record<DeliveryState, number>","message: Message","deliveries: Delivery[]","remotes: RemoteDelivery[]","settled: Delivery[]","p: Placement","out: Target[]","out: Delivery[]","next: Delivery","answer: Message","moved: Delivery[]","out: { bound: Delivery; message: Message }[]","bound: Delivery","out","sender: Sender","storedMessage: Message","changed: string[]","planned: Delivery","held: Delivery","plain: ArrivalSettle","events: EngineEvent[]","notices: { to: Address; about: Message; body: string }[]","state: RemoteState","state: DeliveryState","record: Settlement","retired: string[]","d: Delivery","row: RemoteDelivery","request: PolicyRequest","result: WakeResult","close: Message","input: SendInput","t: Partial<Record<keyof RemoteTarget, unknown>>","REMOTE_STATES: readonly RemoteState[]","SETTLED_AS: readonly SettledAs[]","db: SqliteDatabase","message: Message","where: string[]","params: SqlValue[]"],"sources":["../src/errors.ts","../src/address.ts","../src/lines.ts","../src/envelope.ts","../src/localOnly.ts","../src/render.ts","../src/ulid.ts","../src/engine.ts","../src/store.ts","../src/sqliteStore.ts","../src/version.ts"],"sourcesContent":["import type { ERROR_CODES } from './constants.js';\n\nexport type MessagingErrorCode = keyof typeof ERROR_CODES;\n\n// One error type for every protocol failure; hosts map `code` to the status\n// ERROR_CODES gives it.\nexport class MessagingError extends Error {\n constructor(\n readonly code: MessagingErrorCode,\n message: string,\n readonly field?: string\n ) {\n super(message);\n this.name = 'MessagingError';\n }\n}\n","import {\n ActorRefError,\n parseActorRef,\n TASK_ID_PATTERN,\n} from '@dispatch-foo/core';\n\nimport {\n MAX_ADDRESS_BYTES,\n MAX_SEGMENT_BYTES,\n SYSTEM_ADDRESS,\n} from './constants.js';\nimport { MessagingError } from './errors.js';\n\nexport { SYSTEM_ADDRESS };\n\nexport type Address = string;\n\nexport type ParsedAddress =\n | { kind: 'human'; handle: string; address: Address }\n | { kind: 'agent'; handle: string; operator: string | null; address: Address }\n | { kind: 'task'; id: string; address: Address }\n | { kind: 'run'; id: string; address: Address }\n | { kind: 'channel'; name: string; address: Address }\n | { kind: 'a2a'; alias: string; address: Address };\n\n/** An outbound A2A peer's alias: the handle grammar, at most 40 characters. */\nexport const PEER_ALIAS_PATTERN = /^[a-z0-9][a-z0-9._-]{0,39}$/;\n\nconst RUN_ID = /^r-[0-9a-f]{6,12}$/;\nconst CHANNEL_NAME = /^[a-z0-9][a-z0-9._-]*(\\/[a-z0-9][a-z0-9._-]*)*$/;\n\nconst utf8Length = (s: string): number =>\n new TextEncoder().encode(s).byteLength;\n\n// Parses one address string; `field` names the input slot in the error so an\n// agent can see exactly which recipient it got wrong.\nexport function parseAddress(raw: string, field = 'to'): ParsedAddress {\n // A JSON body can hold anything where an address belongs.\n if (typeof raw !== 'string')\n throw new MessagingError('invalid', 'expected an address string', field);\n const bad = (why: string): never => {\n throw new MessagingError(\n 'invalid',\n `invalid address ${JSON.stringify(raw.slice(0, 80))}: ${why}`,\n field\n );\n };\n // One ceiling for every host, A2A peer and federation receiver.\n if (utf8Length(raw) > MAX_ADDRESS_BYTES)\n return bad(`at most ${MAX_ADDRESS_BYTES} bytes`);\n const segment = (value: string, what: string): void => {\n if (utf8Length(value) > MAX_SEGMENT_BYTES)\n bad(`${what} is over ${MAX_SEGMENT_BYTES} bytes`);\n };\n const colon = raw.indexOf(':');\n if (colon <= 0) return bad('expected <kind>:<id>');\n const scheme = raw.slice(0, colon);\n const rest = raw.slice(colon + 1);\n switch (scheme) {\n case 'human':\n case 'agent': {\n let ref;\n try {\n ref = parseActorRef(raw);\n } catch (err) {\n if (err instanceof ActorRefError) return bad(err.message);\n throw err;\n }\n if (ref === null || ref.handle === null)\n return bad('actor needs a handle');\n segment(ref.handle, 'handle');\n if (ref.operator !== null) segment(ref.operator, 'operator');\n return ref.kind === 'human'\n ? { kind: 'human', handle: ref.handle, address: raw }\n : {\n kind: 'agent',\n handle: ref.handle,\n operator: ref.operator,\n address: raw,\n };\n }\n case 'task':\n segment(rest, 'id');\n return TASK_ID_PATTERN.test(rest)\n ? { kind: 'task', id: rest, address: raw }\n : bad('not a task id');\n case 'run':\n segment(rest, 'id');\n return RUN_ID.test(rest)\n ? { kind: 'run', id: rest, address: raw }\n : bad('not a run id');\n case 'channel':\n for (const part of rest.split('/')) segment(part, 'channel segment');\n return CHANNEL_NAME.test(rest)\n ? { kind: 'channel', name: rest, address: raw }\n : bad('not a channel name');\n case 'a2a':\n segment(rest, 'alias');\n return PEER_ALIAS_PATTERN.test(rest)\n ? { kind: 'a2a', alias: rest, address: raw }\n : bad('not an A2A peer alias (a-z, 0-9, \".\", \"_\", \"-\"; at most 40)');\n default:\n return bad(`unknown kind ${JSON.stringify(scheme)}`);\n }\n}\n\n/** An outbound A2A peer (`a2a:<alias>`); every message it sends is recorded by the daemon. */\nexport function isPeerAddress(address: Address): boolean {\n return address.startsWith('a2a:');\n}\n\n/** True for senders the ping-pong breaker counts: runs, agents and A2A peers, not the system. */\nexport function isAgentAuthored(address: Address): boolean {\n if (address === SYSTEM_ADDRESS) return false;\n return (\n address.startsWith('run:') ||\n address.startsWith('agent:') ||\n isPeerAddress(address)\n );\n}\n","// Every sequence a reader may treat as a line break: CRLF, LF, CR, VT, FF,\n// NEL and the Unicode line and paragraph separators.\nexport const LINE_BREAK = /\\r\\n|[\\n\\v\\f\\r\\u0085\\u2028\\u2029]/;\n","import { parseAddress, SYSTEM_ADDRESS } from './address.js';\nimport type { Address } from './address.js';\nimport {\n BUILT_IN_KINDS,\n GATE_TYPES,\n gateTypeOf,\n hasGateData,\n MAX_SEGMENT_BYTES,\n raiserOf,\n REF_TYPES,\n} from './constants.js';\nimport { MessagingError } from './errors.js';\nimport { LINE_BREAK } from './lines.js';\n\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nexport { GATE_TYPES };\n\nexport type BuiltInKind = (typeof BUILT_IN_KINDS)[number];\nexport type MessageKind = BuiltInKind | `x-${string}`;\n\n/** A ref type the registry lists; a received ref may carry any other identifier. */\nexport type RefType = (typeof REF_TYPES)[number];\n\nexport interface Ref {\n /** A registered ref type, or any identifier on a ref received from a peer (§4.4). */\n type: RefType | (string & {});\n id: string;\n /** A commit sha for `file` refs; a section anchor for `doc` refs. */\n at?: string;\n}\n\nexport interface Message {\n id: string;\n thread: string;\n replyTo: string | null;\n from: Address;\n session?: string;\n to: Address[];\n kind: MessageKind;\n body: string;\n refs: Ref[];\n data?: JsonValue;\n urgent: boolean;\n blocking: boolean;\n choices?: string[];\n choice?: string;\n wake: 'none' | 'request';\n createdAt: string;\n /** The replica that created a remote message; absent when created here. */\n origin?: string;\n /** The origin's hybrid clock at send; threads order by it. */\n hlc?: string;\n}\n\nexport interface SendInput {\n to: Address[];\n kind: MessageKind;\n body: string;\n refs?: Ref[];\n data?: JsonValue;\n urgent?: boolean;\n blocking?: boolean;\n choices?: string[];\n choice?: string;\n replyTo?: string | null;\n wake?: 'none' | 'request';\n session?: string;\n /** The sender's own dedupe key; a repeat returns the first message (A2A §3.3.1). */\n idempotencyKey?: string;\n}\n\n// The kinds a memory gate may name; @dispatch/memory pins its MEMORY_KINDS to\n// this list.\nexport const MEMORY_GATE_KINDS = [\n 'preference',\n 'convention',\n 'constraint',\n 'hazard',\n 'decision',\n 'fact',\n 'reference',\n] as const;\nconst MEMORY_GATE_ACTIONS: readonly string[] = ['add', 'supersede', 'retire'];\nconst PROPOSAL_ID = /^mp-[0-9A-HJKMNP-TV-Z]{26}$/;\n\nexport type GateData =\n | {\n type: 'tool-approval';\n requestId: string;\n runId?: string;\n conversation?: string;\n tool: string;\n input: JsonValue; // at most an 8 KiB preview; the executor holds the real input\n truncated?: true; // set when `input` was cut to fit\n floor: boolean; // the irreversibility floor holds the call, judged on its full input\n }\n | { type: 'scope'; paths: string[]; reason: string }\n | { type: 'wake'; target: Address; message: string }\n | {\n type: 'agent-registration';\n agent: Address;\n client: string;\n // The human who asked; the agent registers under their handle.\n requestedBy?: Address;\n // The registration this card decides (a prefix of its token hash); an\n // answer for any other, after a re-key, changes nothing.\n key?: string;\n }\n | {\n type: 'overseer-action';\n conversation: string;\n actionId: string;\n summary: string;\n }\n | {\n type: 'memory';\n proposalId: string; // mp-<ulid>; the content stays in memory.db\n action: 'add' | 'supersede' | 'retire';\n scope: 'project' | 'team';\n kind: (typeof MEMORY_GATE_KINDS)[number];\n }\n | {\n type: 'task-proposal';\n // The draft an A2A client handed off, and who proposed it (system-only gate).\n task: string;\n proposedBy: Address;\n message: string;\n }\n | {\n type: 'doc';\n // A proposed edit to an accepted doc; the text stays in docs.db (system-only gate).\n doc: string; // doc-<ulid>\n proposal: string; // rev-<ulid>\n taskId?: string;\n runId?: string;\n };\n\n/** How validateSendInput judges gates, refs and a missing reply target. */\nexport interface ValidateOptions {\n /** The gate types the host implements; default every GATE_TYPES entry. */\n gateTypes?: ReadonlySet<string>;\n /** `received` for a message that arrived through a binding: it keeps unknown ref types. */\n origin?: 'local' | 'received';\n /** A federated receive: a reply whose target is not stored skips the checks that need it. */\n parentOptional?: boolean;\n}\n\nconst PACKAGE_GATE_TYPES: ReadonlySet<string> = new Set(GATE_TYPES);\n\nconst X_KIND = /^x-[a-z0-9][a-z0-9-]*$/;\n// §1.4's identifier grammar; an identifier's cap is the segment cap.\nconst IDENTIFIER = /^[a-z0-9][a-z0-9._-]*$/;\nconst ASKING_KINDS: ReadonlySet<string> = new Set(['question', 'handoff']);\n\n// Caps on one send, so no message can flood a recipient's session or the store.\nconst MAX_BODY_BYTES = 64 * 1024;\nconst MAX_DATA_BYTES = 64 * 1024;\nconst MAX_RECIPIENTS = 50;\nconst MAX_REFS = 50;\nconst MAX_CHOICES = 20;\n// Caps on one-line fields, in UTF-8 bytes.\nconst MAX_REF_BYTES = 512;\nconst MAX_LABEL_BYTES = 200;\n\n/** The gate payload a message carries, or null when `data` is not a gate. */\nexport function gateOf(message: { data?: JsonValue }): GateData | null {\n const data = message.data;\n if (data === null || typeof data !== 'object' || Array.isArray(data))\n return null;\n const type = (data as { [key: string]: JsonValue })['type'];\n return typeof type === 'string' &&\n (GATE_TYPES as readonly string[]).includes(type)\n ? (data as unknown as GateData)\n : null;\n}\n\n// True only for this daemon's own marker: a client, peer, human or another\n// replica's system cannot forge one.\nexport function isSystemMarker(\n message: Pick<Message, 'from' | 'data' | 'origin'>,\n type: 'x-closed' | 'x-breaker'\n): boolean {\n const data = message.data;\n return (\n message.from === SYSTEM_ADDRESS &&\n message.origin === undefined &&\n typeof data === 'object' &&\n data !== null &&\n !Array.isArray(data) &&\n (data as { [key: string]: JsonValue })['type'] === type\n );\n}\n\nfunction invalid(field: string, why: string): never {\n throw new MessagingError('invalid', `${field}: ${why}`, field);\n}\n\n/** §1.4's identifier: lowercase, no line breaks, at most one segment's bytes. */\nexport function isIdentifier(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n IDENTIFIER.test(value) &&\n value.length <= MAX_SEGMENT_BYTES\n );\n}\n\n// True when `text` is over `max` UTF-8 bytes. A UTF-16 code unit encodes to\n// 1–3 bytes, so only lengths between max/3 and max need the encoder.\nfunction overBytes(text: string, max: number): boolean {\n if (text.length > max) return true;\n if (text.length * 3 <= max) return false;\n return new TextEncoder().encode(text).byteLength > max;\n}\n\n// Rendered one-line fields must stay short and unbroken, or they could flood\n// or start a fake message header in the recipient's session.\nfunction singleLine(\n value: string | undefined,\n field: string,\n maxBytes: number\n): void {\n if (typeof value !== 'string') return;\n if (LINE_BREAK.test(value)) invalid(field, 'must not contain line breaks');\n if (overBytes(value, maxBytes))\n invalid(field, `at most ${maxBytes} bytes (UTF-8)`);\n}\n\n// A sender-chosen dedupe key: one line, 1..200 UTF-8 bytes, like `session`.\nexport function checkIdempotencyKey(key: string): void {\n if (key === '') invalid('idempotencyKey', 'must not be empty');\n singleLine(key, 'idempotencyKey', MAX_LABEL_BYTES);\n}\n\n// Gate data travels only on questions and handoffs, only for a type this host\n// implements, and only from the raiser the type allows.\nfunction validateGate(\n input: SendInput,\n sender: Address,\n canDecide: boolean,\n known: ReadonlySet<string>\n): void {\n const type = (input.data as { type: string }).type;\n if (!ASKING_KINDS.has(input.kind))\n invalid(\n 'data.type',\n 'gate data travels only on questions and handoffs; private payloads use an x- type'\n );\n if (!known.has(type))\n invalid(\n 'data.type',\n `unregistered or unimplemented gate type ${type}; private payloads use an x- type`\n );\n if (type === 'memory') validateMemoryShape(input);\n if (type === 'doc') validateDocShape(input);\n const raiser = raiserOf(type);\n if (raiser === 'session' && !sender.startsWith('run:')) {\n throw new MessagingError(\n 'forbidden',\n `only runs may request ${type}`,\n 'data'\n );\n }\n if (raiser === 'system' && sender !== SYSTEM_ADDRESS) {\n throw new MessagingError(\n 'forbidden',\n `only Dispatch may raise ${type} gates`,\n 'data'\n );\n }\n if (\n raiser === 'system-or-decider' &&\n sender !== SYSTEM_ADDRESS &&\n !(canDecide && sender.startsWith('human:'))\n ) {\n throw new MessagingError(\n 'forbidden',\n `only Dispatch may raise ${type} gates, or a deciding human`,\n 'data'\n );\n }\n if (type === 'scope') validateScopeShape(input);\n}\n\n// A scope request names its paths and reason and has one fixed question shape.\nfunction validateScopeShape(input: SendInput): void {\n const gate = input.data as unknown as Extract<GateData, { type: 'scope' }>;\n if (\n !Array.isArray(gate.paths) ||\n gate.paths.length === 0 ||\n !gate.paths.every((p) => typeof p === 'string' && p !== '')\n ) {\n invalid('data.paths', 'expected a non-empty list of paths');\n }\n if (typeof gate.reason !== 'string' || gate.reason.trim() === '')\n invalid('data.reason', 'required');\n if (\n input.kind !== 'question' ||\n input.blocking !== true ||\n JSON.stringify(input.choices) !== '[\"grant\",\"deny\"]'\n ) {\n invalid(\n 'data',\n 'a scope request is { kind: \"question\", blocking: true, choices: [\"grant\", \"deny\"], data: { type: \"scope\", paths, reason } }'\n );\n }\n}\n\n// A memory gate names its proposal, never its content, and has one fixed\n// question shape.\nfunction validateMemoryShape(input: SendInput): void {\n const gate = input.data as unknown as Extract<GateData, { type: 'memory' }>;\n if (typeof gate.proposalId !== 'string' || !PROPOSAL_ID.test(gate.proposalId))\n invalid('data.proposalId', 'expected a proposal id like mp-01K…');\n if (!MEMORY_GATE_ACTIONS.includes(gate.action))\n invalid('data.action', `expected ${MEMORY_GATE_ACTIONS.join('|')}`);\n if (gate.scope !== 'project' && gate.scope !== 'team')\n invalid('data.scope', 'expected project|team');\n if (!(MEMORY_GATE_KINDS as readonly string[]).includes(gate.kind))\n invalid('data.kind', `expected ${MEMORY_GATE_KINDS.join('|')}`);\n if (\n input.kind !== 'question' ||\n input.blocking !== true ||\n JSON.stringify(input.choices) !== '[\"approve\",\"reject\"]'\n ) {\n invalid(\n 'data',\n 'a memory gate is { kind: \"question\", blocking: true, choices: [\"approve\", \"reject\"], data: { type: \"memory\", proposalId, action, scope, kind } }'\n );\n }\n}\n\n// A doc gate names the doc and its proposed revision, never the text, and has\n// one fixed question shape.\nfunction validateDocShape(input: SendInput): void {\n const gate = input.data as unknown as Extract<GateData, { type: 'doc' }>;\n if (typeof gate.doc !== 'string' || !gate.doc.startsWith('doc-'))\n invalid('data.doc', 'expected a doc- id');\n if (typeof gate.proposal !== 'string' || !gate.proposal.startsWith('rev-'))\n invalid('data.proposal', 'expected a rev- id');\n if (\n input.kind !== 'question' ||\n input.blocking !== true ||\n JSON.stringify(input.choices) !== '[\"approve\",\"reject\"]'\n ) {\n invalid(\n 'data',\n 'a doc gate is { kind: \"question\", blocking: true, choices: [\"approve\", \"reject\"], data: { type: \"doc\", doc, proposal } }'\n );\n }\n}\n\n// Rejects any envelope the engine must not store. `replyTarget` is the message\n// named by `replyTo` (null when absent or unknown); errors name the bad field.\nexport function validateSendInput(\n input: SendInput,\n sender: Address,\n canDecide: boolean,\n replyTarget: Message | null,\n options: ValidateOptions = {}\n): void {\n const known = options.gateTypes ?? PACKAGE_GATE_TYPES;\n // A JSON body can hold any shape: check the containers before reading them.\n if (typeof input !== 'object' || input === null || Array.isArray(input))\n invalid('input', 'expected an object');\n if (input.refs !== undefined && !Array.isArray(input.refs))\n invalid('refs', 'expected a list');\n if (\n input.choices !== undefined &&\n (!Array.isArray(input.choices) ||\n input.choices.some((c) => typeof c !== 'string'))\n )\n invalid('choices', 'expected a list of strings');\n if (\n input.replyTo !== undefined &&\n input.replyTo !== null &&\n typeof input.replyTo !== 'string'\n )\n invalid('replyTo', 'expected a message id or null');\n if (!Array.isArray(input.to) || input.to.length === 0)\n invalid('to', 'at least one recipient');\n if (input.to.length > MAX_RECIPIENTS)\n invalid('to', `at most ${MAX_RECIPIENTS} recipients`);\n input.to.forEach((addr, i) => parseAddress(addr, `to[${i}]`));\n\n const kind = input.kind;\n if (typeof kind !== 'string') invalid('kind', 'expected a string');\n if (\n !(BUILT_IN_KINDS as readonly string[]).includes(kind) &&\n !X_KIND.test(kind)\n ) {\n invalid('kind', `unknown kind ${JSON.stringify(kind)}`);\n }\n const hasChoice = typeof input.choice === 'string';\n if (\n typeof input.body !== 'string' ||\n (input.body.trim() === '' && !(kind === 'answer' && hasChoice))\n ) {\n invalid('body', 'required');\n }\n if (overBytes(input.body, MAX_BODY_BYTES))\n invalid('body', `at most ${MAX_BODY_BYTES} bytes (UTF-8)`);\n if (\n input.data !== undefined &&\n overBytes(JSON.stringify(input.data), MAX_DATA_BYTES)\n )\n invalid('data', `at most ${MAX_DATA_BYTES} bytes as JSON`);\n singleLine(input.session, 'session', MAX_LABEL_BYTES);\n if (input.idempotencyKey !== undefined)\n checkIdempotencyKey(input.idempotencyKey);\n\n const refs = input.refs ?? [];\n if (refs.length > MAX_REFS) invalid('refs', `at most ${MAX_REFS} refs`);\n refs.forEach((ref, i) => {\n if (typeof ref !== 'object' || ref === null)\n invalid(`refs[${i}]`, 'expected { type, id }');\n const registered = (REF_TYPES as readonly string[]).includes(ref.type);\n // A peer's newer ref type is kept, not refused, so a minor version can add one.\n const receivedOk = options.origin === 'received' && isIdentifier(ref.type);\n if (!registered && !receivedOk)\n invalid(`refs[${i}].type`, 'unknown ref type');\n if (typeof ref.id !== 'string' || ref.id === '')\n invalid(`refs[${i}].id`, 'required');\n singleLine(ref.id, `refs[${i}].id`, MAX_REF_BYTES);\n singleLine(ref.at, `refs[${i}].at`, MAX_REF_BYTES);\n });\n\n const asking = ASKING_KINDS.has(kind);\n if (input.blocking === true && !asking)\n invalid('blocking', 'only questions and handoffs block');\n if (input.choices !== undefined) {\n if (!asking)\n invalid('choices', 'only questions and handoffs carry choices');\n const choices = input.choices;\n if (choices.length > MAX_CHOICES)\n invalid('choices', `at most ${MAX_CHOICES} choices`);\n choices.forEach((c, i) => singleLine(c, `choices[${i}]`, MAX_LABEL_BYTES));\n if (\n choices.length === 0 ||\n new Set(choices).size !== choices.length ||\n choices.some((c) => c.trim() === '')\n ) {\n invalid('choices', 'expected distinct, non-empty choices');\n }\n }\n if (hasChoice && kind !== 'answer')\n invalid('choice', 'only answers carry a choice');\n singleLine(input.choice, 'choice', MAX_LABEL_BYTES);\n\n const replyTo = input.replyTo ?? null;\n if (kind === 'answer' && replyTo === null)\n invalid('replyTo', 'an answer needs the question id');\n if (replyTo !== null) {\n // A received reply may name a parent that never reached this replica.\n if (replyTarget === null) {\n if (options.parentOptional !== true)\n throw new MessagingError(\n 'not-found',\n `no message ${replyTo}`,\n 'replyTo'\n );\n } else if (kind === 'answer') {\n if (!ASKING_KINDS.has(replyTarget.kind))\n invalid('replyTo', 'only questions and handoffs take answers');\n const isGate = gateTypeOf(replyTarget, known) !== null;\n if (isGate && !canDecide) {\n throw new MessagingError(\n 'forbidden',\n 'answering this gate needs the decide tier',\n 'replyTo'\n );\n }\n // A gate or handoff answer carries one of its choices when it has any,\n // and none when it has none (a choiceless answer needs a body, above).\n const choices = replyTarget.choices ?? [];\n if (\n (isGate || replyTarget.kind === 'handoff') &&\n choices.length > 0 &&\n !hasChoice\n )\n invalid('choice', `choose one of ${choices.join(', ')}`);\n if (hasChoice && !choices.includes(input.choice!))\n invalid('choice', `choose one of ${choices.join(', ')}`);\n }\n }\n\n if (hasGateData(input)) validateGate(input, sender, canDecide, known);\n}\n","import type { Address } from './address.js';\nimport { hasGateData, MARKERS } from './constants.js';\nimport type { Message } from './envelope.js';\n\n/** Markers that never leave the machine: the registry's plus the policy engine's. */\nexport const LOCAL_ONLY_MARKERS: readonly string[] = [\n ...new Set<string>([...MARKERS, 'x-policy', 'x-expired']),\n];\n\nconst OVERSEER = /^agent:[^/]+\\/overseer$/;\nconst A2A_AGENT = /^agent:[^/]+\\/a2a\\./;\n\n/** Overseer and A2A identities: never federated, never in channel or agent ops. */\nexport function isFederationLocalAddress(address: Address): boolean {\n return (\n address.startsWith('a2a:') ||\n OVERSEER.test(address) ||\n A2A_AGENT.test(address)\n );\n}\n\nexport type LocalOnlyReason = 'gate' | 'marker' | 'participant' | 'root';\n\nfunction dataType(message: Message): string | null {\n const data = message.data;\n if (\n data === null ||\n data === undefined ||\n typeof data !== 'object' ||\n Array.isArray(data)\n )\n return null;\n const type = (data as { type?: unknown }).type;\n return typeof type === 'string' ? type : null;\n}\n\n// Why a message must stay on this machine, or null: gate data on it or its\n// reply target, a system marker, an overseer or A2A participant, or a local-only root.\nexport function localOnlyReason(\n message: Message,\n replyTarget: Message | null,\n root: Message | null\n): LocalOnlyReason | null {\n if (\n hasGateData(message) ||\n (replyTarget !== null && hasGateData(replyTarget))\n )\n return 'gate';\n const type = dataType(message);\n if (type !== null && LOCAL_ONLY_MARKERS.includes(type)) return 'marker';\n if ([message.from, ...message.to].some(isFederationLocalAddress))\n return 'participant';\n if (\n root !== null &&\n root.id !== message.id &&\n localOnlyReason(root, null, null) !== null\n )\n return 'root';\n return null;\n}\n","import type { Message } from './envelope.js';\nimport { LINE_BREAK } from './lines.js';\n\nconst DIGEST_WIDTH = 80;\n\nfunction refText(m: Message): string | null {\n if (m.refs.length === 0) return null;\n return `refs: ${m.refs.map((r) => `${r.type}:${r.id}${r.at ? `@${r.at}` : ''}`).join(', ')}`;\n}\n\n// The sender as a header names it: a teammate's replica by its handle, an\n// external sender marked as such.\nfunction senderLabel(m: Message, external: boolean, remote?: string): string {\n if (remote !== undefined) return `${m.from} (remote: ${remote})`;\n return external ? `${m.from} (external)` : m.from;\n}\n\n// The text a pushed message becomes inside an agent's session: a labelled\n// header, then the body quoted line by line so it can never pass for a header.\n// An external or remote sender's carried lines (choices, choice, refs) are quoted too.\nexport function renderForAgent(\n m: Message,\n external = false,\n remote?: string\n): string {\n const quote = (line: string) => `│ ${line}`;\n const tags = [m.kind, ...(m.urgent ? ['urgent'] : []), m.id].join(' · ');\n const lines = [\n `[message from ${senderLabel(m, external, remote)} · ${tags}]`,\n ...m.body.split(LINE_BREAK).map(quote),\n ];\n if (m.replyTo !== null) lines.push(`(in reply to ${m.replyTo})`);\n const carried: string[] = [];\n if (m.choices !== undefined)\n carried.push(`choices: ${m.choices.join(' | ')}`);\n if (m.choice !== undefined) carried.push(`choice: ${m.choice}`);\n const refs = refText(m);\n if (refs !== null) carried.push(refs);\n const quoteCarried = external || remote !== undefined;\n lines.push(...(quoteCarried ? carried.map(quote) : carried));\n if (m.blocking)\n lines.push(\n `The sender is waiting. Answer with msg_reply(messageId: \"${m.id}\").`\n );\n return lines.join('\\n');\n}\n\n// A body's first line, cut to the digest width in code points, for one-line summaries.\nexport function firstLine(body: string): string {\n const first = body.split(LINE_BREAK, 1)[0] ?? '';\n const chars = Array.from(first);\n return chars.length > DIGEST_WIDTH\n ? `${chars.slice(0, DIGEST_WIDTH - 1).join('')}…`\n : first;\n}\n\n// One line for a pulled (channel) message: where, who, the first line, the id.\nexport function renderDigestLine(\n m: Message,\n external = false,\n remote?: string\n): string {\n const channel = m.to.find((a) => a.startsWith('channel:'));\n const where =\n channel === undefined ? '' : ` #${channel.slice('channel:'.length)} ·`;\n return `📬${where} ${m.kind} from ${senderLabel(m, external, remote)}: ${firstLine(m.body)} (${m.id})`;\n}\n","const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst MAX_TIME = 2 ** 48 - 1;\n\nfunction defaultRandom(n: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(n));\n}\n\nfunction encodeTime(ms: number): string {\n let out = '';\n let t = ms;\n for (let i = 0; i < 10; i++) {\n out = ALPHABET[t % 32] + out;\n t = Math.floor(t / 32);\n }\n return out;\n}\n\nfunction increment(digits: number[]): void {\n for (let i = digits.length - 1; i >= 0; i--) {\n if (digits[i] < 31) {\n digits[i] += 1;\n return;\n }\n digits[i] = 0;\n }\n throw new Error('ulid random component overflowed within one millisecond');\n}\n\n// Returns a ULID generator: 48-bit ms time + 80 random bits, strictly\n// increasing even for same-millisecond calls or a clock that steps back.\nexport function createUlidFactory(\n randomBytes: (n: number) => Uint8Array = defaultRandom\n): (nowMs: number) => string {\n let lastTime = -1;\n let lastRandom: number[] = [];\n return (nowMs: number): string => {\n if (!Number.isInteger(nowMs) || nowMs < 0 || nowMs > MAX_TIME) {\n throw new RangeError(`ulid time out of range: ${nowMs}`);\n }\n if (nowMs <= lastTime) {\n increment(lastRandom);\n } else {\n lastTime = nowMs;\n // 256 is a multiple of 32, so byte % 32 stays uniform.\n lastRandom = Array.from(randomBytes(16), (b) => b % 32);\n }\n return encodeTime(lastTime) + lastRandom.map((d) => ALPHABET[d]).join('');\n };\n}\n","import {\n isAgentAuthored,\n isPeerAddress,\n parseAddress,\n SYSTEM_ADDRESS,\n} from './address.js';\nimport type { Address } from './address.js';\nimport { gateTypeOf, hasGateData, isDecidingAuthor } from './constants.js';\nimport {\n checkIdempotencyKey,\n gateOf,\n isIdentifier,\n isSystemMarker,\n validateSendInput,\n} from './envelope.js';\nimport type {\n JsonValue,\n Message,\n MessageKind,\n Ref,\n SendInput,\n} from './envelope.js';\nimport { MessagingError } from './errors.js';\nimport type {\n DeliveryEntry,\n FederationHooks,\n MessagingHost,\n Placement,\n PolicyRequest,\n RefusedEntry,\n RemoteOrigin,\n RemoteTarget,\n SettleEntry,\n StateEntry,\n WakeResult,\n} from './host.js';\nimport { isFederationLocalAddress, localOnlyReason } from './localOnly.js';\nimport type { LocalOnlyReason } from './localOnly.js';\nimport { firstLine, renderDigestLine, renderForAgent } from './render.js';\nimport type {\n Delivery,\n DeliveryState,\n DeliveryVia,\n MessageStore,\n RemoteDelivery,\n RemoteState,\n SettledAs,\n Settlement,\n} from './store.js';\nimport { createUlidFactory } from './ulid.js';\n\nexport interface EngineLimits {\n urgentPerHour: number;\n agentTurnsPerThreadPerHour: number;\n /** New threads an agent-authored sender may start among agents and\n * sessions (no human recipient) per hour. A host's own guardrail beyond\n * the spec's breaker, which counts replies only; off by default. */\n agentThreadsPerHour: number;\n /** Open wake gates one target may have at once; a further ask is merged\n * into the open gate, its message held as before. Off by default. */\n openWakeGatesPerTarget: number;\n}\n\nexport const DEFAULT_LIMITS: EngineLimits = {\n urgentPerHour: 10,\n agentTurnsPerThreadPerHour: 20,\n agentThreadsPerHour: Number.POSITIVE_INFINITY,\n openWakeGatesPerTarget: Number.POSITIVE_INFINITY,\n};\n\n/** Who is sending, as the host authenticated them. */\nexport interface Sender {\n address: Address;\n canDecide: boolean;\n}\n\n/** How a send reached the engine: `received` when a binding delivered it. */\nexport interface SendOptions {\n origin?: 'local' | 'received';\n}\n\nexport interface SendResult {\n message: Message;\n deliveries: Delivery[];\n /** True when `urgent` was dropped because the sender hit its quota. */\n downgraded: boolean;\n /** Set when `idempotencyKey` matched an earlier send from the same sender. */\n replayed?: true;\n}\n\nexport type EngineEvent =\n | { type: 'message'; message: Message }\n | { type: 'delivery'; delivery: Delivery }\n | { type: 'membership'; channel: string; member: Address; joined: boolean }\n | { type: 'remote'; messageId: string; recipient: Address };\n\n/** What receive did: stored it (`applied`) or already held it (`duplicate`). */\nexport interface ReceiveResult {\n status: 'applied' | 'duplicate';\n /** The local deliveries this call made, after their push or notify. */\n deliveries: Delivery[];\n}\n\ninterface Target {\n recipient: Address;\n via: DeliveryVia;\n}\n\n// How an arriving answer is stored against its question's settlement.\ninterface ArrivalSettle {\n kind: MessageKind;\n settledAs?: SettledAs;\n /** The question whose local deliveries become answered, or null. */\n markAnswered: string | null;\n /** This replica settles the question and records this answer as accepted. */\n recordSettlement: boolean;\n /** Demote the question's other answers before storing this one. */\n swapFirst: boolean;\n /** The accepted answer's sender, when this answer lost at the settler. */\n supersededBy: Address | null;\n}\n\nconst HOUR_MS = 60 * 60 * 1000;\n/** Superseded-answer notices one question sends at most (FW-R33). */\nconst MAX_SUPERSEDED_NOTICES = 5;\n\nconst SYSTEM_SENDER: Sender = { address: SYSTEM_ADDRESS, canDecide: true };\n\nconst LOCAL: Placement = { kind: 'local' };\n\nconst LOCAL_ONLY_TEXT: Record<LocalOnlyReason, string> = {\n gate: 'gates never leave the machine whose runs they guard',\n marker: 'system markers never travel between machines',\n participant: 'overseer and A2A conversations stay on their machine',\n root: 'this thread stays on the machine it started on',\n};\n\n// A remote row's order: pushed and notified tie, and refused sits below every report.\nconst REMOTE_RANK: Record<RemoteState, number> = {\n refused: -1,\n forwarded: 0,\n held: 1,\n pushed: 2,\n notified: 2,\n read: 3,\n answered: 4,\n};\n\n// A local delivery's order, for catching a human's device up to another's report.\nconst LOCAL_RANK: Record<DeliveryState, number> = {\n held: 0,\n sending: 1,\n pushed: 2,\n notified: 2,\n read: 3,\n answered: 4,\n};\n\nexport class DeliveryEngine {\n private readonly store: MessageStore;\n private readonly host: MessagingHost;\n private readonly limits: EngineLimits;\n private readonly ulid: (nowMs: number) => string;\n private readonly gateTypes: ReadonlySet<string>;\n private readonly listeners = new Set<(e: EngineEvent) => void>();\n\n // `gateTypes` are the gate types the host implements; any other is refused.\n constructor(opts: {\n store: MessageStore;\n host: MessagingHost;\n limits?: Partial<EngineLimits>;\n newUlid?: (nowMs: number) => string;\n gateTypes?: readonly string[];\n }) {\n this.store = opts.store;\n this.host = opts.host;\n this.limits = { ...DEFAULT_LIMITS, ...opts.limits };\n this.ulid = opts.newUlid ?? createUlidFactory();\n this.gateTypes = new Set(opts.gateTypes ?? ['wake']);\n }\n\n subscribe(listener: (e: EngineEvent) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** How many listeners are subscribed right now, so a test can check that a\n * subscriber's cleanup unsubscribed it. */\n get listenerCount(): number {\n return this.listeners.size;\n }\n\n // Runs every subscriber for one event, in isolation: a throwing listener\n // must never fail (or half-run) the send that produced the event.\n private emit(e: EngineEvent): void {\n for (const l of this.listeners) {\n try {\n l(e);\n } catch (err) {\n console.error('messaging listener failed', err);\n }\n }\n }\n\n private id(prefix: 'm' | 'd'): string {\n return `${prefix}-${this.ulid(this.host.now().getTime()).toLowerCase()}`;\n }\n\n private nowIso(): string {\n return this.host.now().toISOString();\n }\n\n private hourAgoIso(): string {\n return new Date(this.host.now().getTime() - HOUR_MS).toISOString();\n }\n\n // Approved agents, humans, runs and the system may send; pending or revoked\n // agents may not. Humans and runs were authenticated by the host already.\n private authorize(sender: Sender): { muted: boolean } {\n // Only humans the host authorized and the system decide.\n if (\n sender.canDecide &&\n sender.address !== SYSTEM_ADDRESS &&\n !sender.address.startsWith('human:')\n ) {\n throw new MessagingError(\n 'forbidden',\n `${sender.address} cannot decide; only humans and the system do`,\n 'from'\n );\n }\n const parsed = parseAddress(sender.address, 'from');\n if (parsed.kind !== 'agent' || sender.address === SYSTEM_ADDRESS)\n return { muted: false };\n const agent = this.store.getAgent(sender.address);\n if (agent === null || agent.status !== 'approved') {\n throw new MessagingError(\n 'forbidden',\n `${sender.address} is not an approved agent`,\n 'from'\n );\n }\n return { muted: agent.muted };\n }\n\n // Expands channels, de-duplicates (direct beats channel) and drops the sender\n // itself, including a run's own task; errors name the caller's `to` entry.\n private resolveTargets(\n to: Address[],\n sender: Address,\n fields: Map<Address, string>\n ): Target[] {\n const senderTask = sender.startsWith('run:')\n ? this.host.taskOfRun(sender.slice(4))\n : null;\n const isSelf = (addr: Address) =>\n addr === sender || (senderTask !== null && addr === `task:${senderTask}`);\n const byRecipient = new Map<Address, Target>();\n // The system address (agent:dispatch) is a valid `to` — e.g. an answer\n // replying to one of its gates — but it has no run/inbox to deliver to.\n const add = (recipient: Address, via: DeliveryVia) => {\n if (isSelf(recipient) || recipient === SYSTEM_ADDRESS) return;\n const existing = byRecipient.get(recipient);\n if (\n existing === undefined ||\n (existing.via === 'channel' && via === 'direct')\n )\n byRecipient.set(recipient, { recipient, via });\n };\n for (const addr of to) {\n const field = fields.get(addr) ?? 'to';\n const parsed = parseAddress(addr, field);\n if (parsed.kind !== 'channel') {\n add(addr, 'direct');\n continue;\n }\n const explicit = this.store.members(parsed.name);\n const implicit = this.host.implicitMembers(parsed.name);\n const known = this.store.channels().some((c) => c.name === parsed.name);\n if (!known && implicit.length === 0)\n throw new MessagingError(\n 'not-found',\n `no channel ${parsed.name}`,\n field\n );\n // A channel is never a member, so a stored or implicit one is skipped.\n for (const member of [...explicit, ...implicit])\n if (!member.startsWith('channel:')) add(member, 'channel');\n }\n return [...byRecipient.values()];\n }\n\n // A target's initial delivery; null drops an ended run only a channel reached.\n // `heldIfEnded` holds mail to an ended run instead of refusing it.\n private plan(\n target: Target,\n muted: boolean,\n field: string,\n heldIfEnded: boolean\n ): Delivery | null {\n const base = {\n id: this.id('d'),\n messageId: '',\n recipient: target.recipient,\n via: target.via,\n updatedAt: this.nowIso(),\n };\n if (muted) return { ...base, runId: null, state: 'read' };\n const parsed = parseAddress(target.recipient, field);\n switch (parsed.kind) {\n case 'human':\n return { ...base, runId: null, state: 'notified' };\n case 'agent':\n case 'channel':\n case 'a2a':\n return { ...base, runId: null, state: 'held' };\n case 'task': {\n const run = this.host.liveRunFor(parsed.id);\n return run === null\n ? { ...base, runId: null, state: 'held' }\n : { ...base, runId: run, state: 'sending' };\n }\n case 'run':\n if (!this.host.isLiveRun(parsed.id)) {\n if (target.via === 'channel') return null;\n if (heldIfEnded) return { ...base, runId: null, state: 'held' };\n throw new MessagingError(\n 'invalid',\n `run ${parsed.id} is not live`,\n field\n );\n }\n return { ...base, runId: parsed.id, state: 'sending' };\n }\n }\n\n async send(\n input: SendInput,\n sender: Sender,\n options: SendOptions = {}\n ): Promise<SendResult> {\n const { muted } = this.authorize(sender);\n // A repeated key replays before any other check, so a retried answer or a\n // retry after the breaker trips gets the first result.\n const key = input.idempotencyKey;\n if (key !== undefined) {\n checkIdempotencyKey(key);\n const prior = this.replay(sender.address, key);\n if (prior !== null) return prior;\n }\n const replyTo = input.replyTo ?? null;\n const replyTarget =\n replyTo === null ? null : this.store.getMessage(replyTo);\n // A non-participant cannot tell an existing message from an absent one;\n // an empty replyTo names no message and fails the same way.\n if (\n replyTo !== null &&\n (replyTarget === null || !this.participates(replyTarget, sender))\n ) {\n throw new MessagingError('not-found', `no message ${replyTo}`, 'replyTo');\n }\n validateSendInput(input, sender.address, sender.canDecide, replyTarget, {\n gateTypes: this.gateTypes,\n origin: options.origin ?? 'local',\n });\n await this.checkBreaker(replyTarget, sender);\n this.checkNewThreads(input, replyTarget, sender);\n // The breaker await lets a duplicate commit first, so look again before the\n // answered check: a raced retry replays rather than meeting conflict.\n const raced = key === undefined ? null : this.replay(sender.address, key);\n if (raced !== null) return raced;\n if (\n input.kind === 'answer' &&\n replyTarget !== null &&\n this.store.answersTo(replyTarget.id).length > 0\n ) {\n throw alreadyAnswered(replyTarget.id);\n }\n\n let urgent = input.urgent === true;\n let downgraded = false;\n if (\n urgent &&\n !sender.address.startsWith('human:') &&\n sender.address !== SYSTEM_ADDRESS\n ) {\n const since = this.hourAgoIso();\n const group = this.host.quotaGroup?.(sender.address) ?? [sender.address];\n const sent = group.reduce(\n (n, address) => n + this.store.countFrom(address, since, true),\n 0\n );\n if (sent >= this.limits.urgentPerHour) {\n urgent = false;\n downgraded = true;\n }\n }\n\n const id = this.id('m');\n const message: Message = {\n id,\n thread: replyTarget?.thread ?? id,\n replyTo: input.replyTo ?? null,\n from: sender.address,\n to: this.replyRecipients(input.to, replyTarget),\n kind: input.kind,\n body: input.body,\n refs: input.refs ?? [],\n urgent,\n blocking: input.blocking === true,\n wake: input.wake ?? 'none',\n createdAt: this.nowIso(),\n };\n if (input.session !== undefined) message.session = input.session;\n if (input.data !== undefined) message.data = input.data;\n if (input.choices !== undefined) message.choices = input.choices;\n else if (input.kind === 'handoff') message.choices = ['accept', 'decline'];\n if (input.choice !== undefined) message.choice = input.choice;\n\n const fields = this.recipientFields(input.to, replyTarget);\n const { targets: placedTargets, placed } = this.place(\n this.resolveTargets(message.to, sender.address, fields),\n fields,\n replyTarget,\n message\n );\n const targets = this.admitExternal(\n placedTargets,\n fields,\n sender,\n replyTarget,\n message\n );\n const fed = this.host.federation;\n if (fed !== undefined) message.hlc = fed.hlc();\n const wakesRuns = wakesEndedRuns(message);\n const deliveries: Delivery[] = [];\n const remotes: RemoteDelivery[] = [];\n const skipWake = new Set<Address>();\n for (const t of targets) {\n const p = placed.get(t.recipient) ?? LOCAL;\n if (p.kind === 'remote') {\n remotes.push({\n messageId: id,\n recipient: t.recipient,\n via: t.via,\n state: 'forwarded',\n homes: p.homes,\n wakeAt: p.wakeAt ?? null,\n refusedBy: [],\n updatedAt: this.nowIso(),\n });\n // Exactly one replica wakes a task: the one placement named.\n if (\n p.wakeAt !== undefined &&\n fed !== undefined &&\n p.wakeAt !== fed.replica\n )\n skipWake.add(t.recipient);\n if (!p.alsoLocal) continue;\n }\n const planned = this.plan(\n t,\n muted,\n fields.get(t.recipient) ?? 'to',\n t.recipient === replyTarget?.from ||\n (wakesRuns && this.hasTask(t.recipient))\n );\n if (planned !== null) deliveries.push({ ...planned, messageId: id });\n }\n\n const question = message.kind === 'answer' ? replyTarget : null;\n const settledAs =\n question === null || fed === undefined\n ? null\n : this.localAnswerSettledAs(question);\n const written = this.store.transaction((): Delivery[] | SendResult => {\n // Re-checked inside the write for a writer on another connection; the\n // unique index is the last backstop.\n const prior = key === undefined ? null : this.replay(sender.address, key);\n if (prior !== null) return prior;\n if (question !== null && this.store.answersTo(question.id).length > 0)\n throw alreadyAnswered(question.id);\n this.store.insertMessage(\n message,\n key,\n settledAs === null ? undefined : { settledAs }\n );\n for (const d of deliveries) this.store.insertDelivery(d);\n for (const r of remotes) this.store.insertRemote(r);\n if (question !== null && settledAs === 'accepted' && fed !== undefined)\n this.store.putSettlement({\n questionId: question.id,\n answerId: id,\n closedReason: null,\n settler: fed.replica,\n at: this.nowIso(),\n });\n return question === null ? [] : this.markAnswered(question.id);\n });\n if (!Array.isArray(written)) return written;\n const answered = written;\n // A gate's effect lands before anyone hears of the answer; a system close\n // has none. Effects need a type this host implements and a deciding author.\n const gateType =\n question === null ? null : gateTypeOf(question, this.gateTypes);\n if (\n question !== null &&\n gateType !== null &&\n this.gateTypes.has(gateType) &&\n !isSystemMarker(message, 'x-closed') &&\n isDecidingAuthor(message.from)\n )\n await this.applyGate(question, message);\n this.emit({ type: 'message', message });\n for (const d of answered) this.emit({ type: 'delivery', delivery: d });\n for (const r of remotes)\n this.emit({ type: 'remote', messageId: id, recipient: r.recipient });\n\n const settled: Delivery[] = [];\n for (const d of deliveries)\n settled.push((await this.dispatch(d, message)).delivery);\n\n if (message.wake === 'request') {\n try {\n await this.runWake(message, settled, skipWake);\n } catch (err) {\n // The message is committed; a failing wake path must not fail the send.\n console.error('messaging wake failed', err);\n }\n }\n\n return { message, deliveries: settled, downgraded };\n }\n\n // A local answer in a federated thread: pending until another replica's\n // settle, or accepted and settled here when this replica asked; else unset.\n private localAnswerSettledAs(question: Message): SettledAs | null {\n if (question.origin !== undefined) return 'pending';\n return this.store.remoteDeliveries({ messageId: question.id }).length > 0\n ? 'accepted'\n : null;\n }\n\n // Whether `address` is a run the host places under a task: held mail to a run\n // is delivered only through its task, so a wake may hold nothing for any other.\n private hasTask(address: Address): boolean {\n return (\n address.startsWith('run:') &&\n this.host.taskOfRun(address.slice('run:'.length)) !== null\n );\n }\n\n // Places each non-external target and runs the one local-only check before\n // any hook admits anything; refused channel members are dropped, not errors.\n private place(\n targets: Target[],\n fields: Map<Address, string>,\n replyTarget: Message | null,\n message: Message\n ): { targets: Target[]; placed: Map<Address, Placement> } {\n const fed = this.host.federation;\n const gateData =\n hasGateData(message) ||\n (replyTarget !== null && hasGateData(replyTarget));\n const placed = new Map<Address, Placement>();\n let external = false;\n for (const t of targets) {\n if (this.isExternal(t.recipient)) {\n external = true;\n continue;\n }\n let p: Placement =\n fed === undefined ? LOCAL : fed.placement(t, message, replyTarget);\n // Gate data never goes remote, whatever the hook says: it stays local\n // where this replica is a home and is refused where it is not.\n if (gateData && p.kind === 'remote')\n p = p.alsoLocal ? LOCAL : { kind: 'refuse', reason: 'local-only' };\n placed.set(t.recipient, p);\n }\n const refused = targets.filter(\n (t) => placed.get(t.recipient)?.kind === 'refuse'\n );\n if (gateData && (external || refused.length > 0))\n throw new MessagingError(\n 'forbidden',\n 'gates never leave this machine',\n 'data'\n );\n for (const t of refused) {\n if (t.via === 'direct')\n throw new MessagingError(\n 'forbidden',\n 'overseer and A2A conversations stay on this machine',\n fields.get(t.recipient) ?? 'to'\n );\n }\n return {\n targets: targets.filter(\n (t) => placed.get(t.recipient)?.kind !== 'refuse'\n ),\n placed,\n };\n }\n\n // Admits or drops A2A clients and peers before storing (place() has already\n // refused gate data); a refused channel member is skipped.\n private admitExternal(\n targets: Target[],\n fields: Map<Address, string>,\n sender: Sender,\n replyTarget: Message | null,\n message: Message\n ): Target[] {\n const external = (t: Target) => this.isExternal(t.recipient);\n if (!targets.some(external)) return targets;\n const out: Target[] = [];\n for (const t of targets) {\n if (!external(t)) {\n out.push(t);\n continue;\n }\n const target = {\n recipient: t.recipient,\n via: t.via,\n field: fields.get(t.recipient) ?? 'to',\n };\n try {\n const admission =\n this.host.admitExternal?.(target, sender, replyTarget, message) ??\n 'deliver';\n if (admission === 'deliver') out.push(t);\n } catch (err) {\n if (t.via === 'channel' && err instanceof MessagingError) continue;\n throw err;\n }\n }\n return out;\n }\n\n private isExternal(address: Address): boolean {\n return (this.host.external?.(address) ?? null) !== null;\n }\n\n // The first send under (from, key) as send() would return it now, or null.\n private replay(from: Address, key: string): SendResult | null {\n const message = this.store.byIdemKey(from, key);\n if (message === null) return null;\n return {\n message,\n deliveries: this.store.deliveries({ messageId: message.id }),\n downgraded: false,\n replayed: true,\n };\n }\n\n // The address a reply actually goes to: a party to the target that is an\n // ended run is reached through its task (see deliverableAddress).\n private rewriteForReply(address: Address, target: Message | null): Address {\n return target !== null &&\n (address === target.from || target.to.includes(address))\n ? this.deliverableAddress(address)\n : address;\n }\n\n // A reply's recipients, with the target's sender and recipients rewritten by\n // deliverableAddress so an ended run's task (and live successor) hears it.\n private replyRecipients(to: Address[], target: Message | null): Address[] {\n if (target === null) return [...to];\n return [...new Set(to.map((a) => this.rewriteForReply(a, target)))];\n }\n\n // Each resolved recipient's first `to[i]` as the caller wrote it, for errors.\n private recipientFields(\n to: Address[],\n target: Message | null\n ): Map<Address, string> {\n const fields = new Map<Address, string>();\n to.forEach((address, i) => {\n const resolved = this.rewriteForReply(address, target);\n if (!fields.has(resolved)) fields.set(resolved, `to[${i}]`);\n });\n return fields;\n }\n\n // Participants may reply and read: the target's sender or recipients, where a\n // run also stands for its task, that task's other runs and deliveries bound to it.\n private participates(target: Message, sender: Sender): boolean {\n if (decides(sender)) return true;\n const senderRunId = sender.address.startsWith('run:')\n ? sender.address.slice(4)\n : null;\n const senderTask =\n senderRunId !== null ? this.host.taskOfRun(senderRunId) : null;\n const actsFor = (address: Address) =>\n address === sender.address ||\n (senderTask !== null &&\n (address === `task:${senderTask}` ||\n (address.startsWith('run:') &&\n this.host.taskOfRun(address.slice(4)) === senderTask)));\n if (actsFor(target.from)) return true;\n return this.store\n .deliveries({ messageId: target.id })\n .some(\n (d) =>\n actsFor(d.recipient) ||\n (senderRunId !== null && d.runId === senderRunId)\n );\n }\n\n // The read rule: the system, a deciding human, or a participant; an absent\n // id reads as unreadable, never as forbidden.\n canRead(messageId: string, sender: Sender): boolean {\n const message = this.store.getMessage(messageId);\n return message !== null && this.participates(message, sender);\n }\n\n // A thread is readable when any of its messages is, and then all of it is;\n // an absent thread has no messages, so no one reads it.\n canReadThread(threadId: string, sender: Sender): boolean {\n return this.store\n .thread(threadId)\n .some((m) => this.participates(m, sender));\n }\n\n // Runs the gate hook and marks it applied; a failure at either step is left\n // for recover() to replay, which is safe because onAnswered is idempotent.\n private async applyGate(\n question: Message,\n answer: Message\n ): Promise<boolean> {\n if (!isDecidingAuthor(answer.from)) return false;\n try {\n await this.host.onAnswered(question, answer);\n } catch (err) {\n console.error('messaging hook failed', err);\n return false;\n }\n try {\n this.store.markGateApplied(question.id, this.nowIso());\n } catch (err) {\n console.error('messaging markGateApplied failed', err);\n return false;\n }\n return true;\n }\n\n // Pushes or notifies one stored delivery (held again if its run went away); `won`\n // is false when another writer moved it first. `urgent` overrides a demoted flag.\n private async dispatch(\n d: Delivery,\n message: Message,\n opts: { remote?: string; urgent?: boolean } = {}\n ): Promise<{ delivery: Delivery; won: boolean }> {\n let next = d;\n if (d.state === 'sending' && d.runId !== null) {\n const push = d.via === 'direct' || (opts.urgent ?? message.urgent);\n const external = this.isExternal(message.from);\n const remote = opts.remote ?? this.remoteLabel(message);\n try {\n if (push)\n await this.host.push(\n d.runId,\n renderForAgent(message, external, remote),\n message\n );\n else\n await this.host.notify(\n d.runId,\n renderDigestLine(message, external, remote),\n message\n );\n next = {\n ...d,\n state: push ? 'pushed' : 'notified',\n updatedAt: this.nowIso(),\n };\n } catch {\n next = { ...d, state: 'held', runId: null, updatedAt: this.nowIso() };\n }\n const moved = this.store.setDelivery(\n next.id,\n next.state,\n next.runId,\n next.updatedAt,\n 'sending'\n );\n if (!moved)\n return { delivery: this.store.getDelivery(d.id) ?? d, won: false };\n } else if (d.state === 'notified') {\n try {\n this.host.notifyHuman(d.recipient, message);\n } catch {\n // A failed desktop notification must not fail the send; the message is stored.\n }\n }\n this.emit({ type: 'delivery', delivery: next });\n return { delivery: next, won: true };\n }\n\n // The handle a remote message's origin renders as, or undefined for local mail;\n // held mail delivered later still names its replica.\n private remoteLabel(message: Message): string | undefined {\n if (message.origin === undefined) return undefined;\n return this.host.federation?.label(message.origin) ?? message.origin;\n }\n\n // Finishes work a crash left: re-sends or holds `sending` deliveries, replays\n // unapplied gate effects, and voids gate answers no deciding principal gave.\n async recover(): Promise<{\n retried: number;\n reverted: number;\n replayed: number;\n voided: number;\n }> {\n let retried = 0;\n let reverted = 0;\n let replayed = 0;\n let voided = 0;\n for (const d of this.store.deliveries({ states: ['sending'] })) {\n const message = this.store.getMessage(d.messageId);\n if (\n d.runId !== null &&\n message !== null &&\n this.host.isLiveRun(d.runId)\n ) {\n const { won } = await this.dispatch(d, message);\n if (won) retried++;\n } else {\n if (\n this.store.setDelivery(d.id, 'held', null, this.nowIso(), 'sending')\n )\n reverted++;\n }\n }\n for (const { question, answer } of this.store.unappliedAnsweredGates()) {\n const type = gateTypeOf(question, this.gateTypes);\n // Unknown to this build: leave it unapplied, so a build that knows it replays it.\n if (type === null || !this.gateTypes.has(type)) continue;\n if (!isDecidingAuthor(answer.from)) {\n if (await this.voidAndReopen(question, answer)) voided++;\n continue;\n }\n if (await this.applyGate(question, answer)) replayed++;\n }\n return { retried, reverted, replayed, voided };\n }\n\n // Sets an answer from anyone but a deciding human or the system aside and\n // reopens its gate; handlers key on the question id, so the question stays.\n private async voidAndReopen(\n question: Message,\n answer: Message\n ): Promise<boolean> {\n const muted = this.store.getAgent(question.from)?.muted === true;\n const reopened = this.store.transaction((): Delivery[] | null => {\n if (!this.store.voidAnswer(answer.id, question.id, this.nowIso()))\n return null;\n const out: Delivery[] = [];\n for (const d of this.store.deliveries({ messageId: question.id })) {\n if (d.state !== 'answered') continue;\n const { state, runId } = this.reopenState(d, muted);\n const next: Delivery = { ...d, state, runId, updatedAt: this.nowIso() };\n if (\n this.store.setDelivery(d.id, state, runId, next.updatedAt, 'answered')\n )\n out.push(next);\n }\n return out;\n });\n if (reopened === null) return false;\n const voidedRow = this.store.getMessage(answer.id);\n if (voidedRow !== null) this.emit({ type: 'message', message: voidedRow });\n for (const d of reopened) await this.dispatch(d, question);\n try {\n await this.send(\n {\n to: [this.host.owner(answer.from)],\n kind: 'notice',\n replyTo: question.id,\n refs: [{ type: 'message', id: answer.id }],\n body: `An answer from ${answer.from} to gate ${question.id} was set aside; only deciding humans answer gates. The gate is open again.`,\n },\n SYSTEM_SENDER\n );\n } catch (err) {\n console.error('messaging void notice failed', err);\n }\n return true;\n }\n\n // The state plan() would give a reopened delivery now; never throws.\n private reopenState(\n d: Delivery,\n muted: boolean\n ): { state: DeliveryState; runId: string | null } {\n try {\n const planned = this.plan(\n { recipient: d.recipient, via: d.via },\n muted,\n 'to',\n true\n );\n return planned === null\n ? { state: 'held', runId: null }\n : { state: planned.state, runId: planned.runId };\n } catch {\n return { state: 'held', runId: null };\n }\n }\n\n getMessage(id: string): Message | null {\n return this.store.getMessage(id);\n }\n\n /** What `address` sent at or after `sinceIso`, oldest first, optionally only these kinds. */\n messagesFrom(\n address: Address,\n sinceIso: string,\n kinds?: MessageKind[]\n ): Message[] {\n return this.store.messagesFrom(address, sinceIso, kinds);\n }\n\n answerOf(questionId: string): Message | null {\n return this.store.answersTo(questionId)[0] ?? null;\n }\n\n openBlocking(): Message[] {\n return this.store.openBlocking();\n }\n\n /** One message's local deliveries; recipients homed elsewhere are not among them. */\n deliveriesOf(messageId: string): Delivery[] {\n return this.store.deliveries({ messageId });\n }\n\n thread(threadId: string): { messages: Message[]; deliveries: Delivery[] } {\n const messages = this.store.thread(threadId);\n return {\n messages,\n deliveries: messages.flatMap((m) =>\n this.store.deliveries({ messageId: m.id })\n ),\n };\n }\n\n inbox(\n recipient: Address,\n states?: DeliveryState[]\n ): { delivery: Delivery; message: Message }[] {\n return this.store.deliveries({ recipient, states }).flatMap((delivery) => {\n const message = this.store.getMessage(delivery.messageId);\n return message === null ? [] : [{ delivery, message }];\n });\n }\n\n markRead(deliveryId: string): Delivery {\n const d = this.store.getDelivery(deliveryId);\n if (d === null)\n throw new MessagingError(\n 'not-found',\n `no delivery ${deliveryId}`,\n 'deliveryId'\n );\n if (d.state === 'answered' || d.state === 'read') return d;\n const next: Delivery = { ...d, state: 'read', updatedAt: this.nowIso() };\n if (\n !this.store.setDelivery(\n next.id,\n next.state,\n next.runId,\n next.updatedAt,\n d.state\n )\n )\n return this.store.getDelivery(d.id) ?? d;\n this.emit({ type: 'delivery', delivery: next });\n return next;\n }\n\n // The outbound worker handed a held peer delivery to the peer: held → pushed,\n // once. Null when it is not a held peer delivery (already relayed, or gone).\n markRelayed(deliveryId: string): Delivery | null {\n const d = this.store.getDelivery(deliveryId);\n if (d === null || d.state !== 'held' || !isPeerAddress(d.recipient))\n return null;\n const next: Delivery = { ...d, state: 'pushed', updatedAt: this.nowIso() };\n if (\n !this.store.setDelivery(\n next.id,\n next.state,\n next.runId,\n next.updatedAt,\n 'held'\n )\n )\n return null;\n this.emit({ type: 'delivery', delivery: next });\n return next;\n }\n\n // Channels hold tasks and actors, not runs or channels: membership must\n // outlive a run, and no channel is ever a recipient.\n join(channel: string, member: Address): void {\n parseAddress(`channel:${channel}`, 'channel');\n const parsed = parseAddress(member, 'member');\n if (parsed.kind === 'run') {\n throw new MessagingError(\n 'invalid',\n 'channels hold tasks and actors, not runs — join as task:<id>',\n 'member'\n );\n }\n if (parsed.kind === 'channel') {\n throw new MessagingError(\n 'invalid',\n 'channels hold tasks and actors, not channels',\n 'member'\n );\n }\n const added = this.store.transaction(() => {\n this.store.ensureChannel(channel, this.nowIso(), false);\n return this.store.addMember(channel, member, this.nowIso());\n });\n if (added) this.emit({ type: 'membership', channel, member, joined: true });\n }\n\n leave(channel: string, member: Address): boolean {\n const removed = this.store.removeMember(channel, member);\n if (removed)\n this.emit({ type: 'membership', channel, member, joined: false });\n return removed;\n }\n\n // Where a reply or notice for `address` goes: a run not live here is reached\n // through its task, whichever replica runs it; other addresses are as given.\n deliverableAddress(address: Address): Address {\n if (!address.startsWith('run:')) return address;\n const runId = address.slice('run:'.length);\n if (this.host.isLiveRun(runId)) return address;\n const task = this.host.taskOfRun(runId);\n if (task !== null) return `task:${task}`;\n const remote = this.host.federation?.remoteRunTask(runId) ?? null;\n return remote === null ? address : `task:${remote}`;\n }\n\n async reply(\n messageId: string,\n input: {\n body: string;\n choice?: string;\n refs?: Ref[];\n data?: JsonValue;\n session?: string;\n },\n sender: Sender\n ): Promise<SendResult> {\n // Authorize before the lookup, so a refused sender cannot probe for ids.\n this.authorize(sender);\n const target = this.store.getMessage(messageId);\n if (target === null)\n throw new MessagingError(\n 'not-found',\n `no message ${messageId}`,\n 'replyTo'\n );\n const asking = target.kind === 'question' || target.kind === 'handoff';\n return this.send(\n {\n ...input,\n to: [target.from],\n kind: asking ? 'answer' : 'message',\n replyTo: messageId,\n },\n sender\n );\n }\n\n // A system answer that skips validation and placement — used when the host\n // itself is closing out a question (e.g. the asking run ended).\n close(questionId: string, reason: string): Message {\n const target = this.store.getMessage(questionId);\n if (target === null)\n throw new MessagingError(\n 'not-found',\n `no message ${questionId}`,\n 'replyTo'\n );\n if (target.kind !== 'question' && target.kind !== 'handoff')\n throw new MessagingError(\n 'invalid',\n `${questionId} is a ${target.kind}, not a question or handoff`,\n 'replyTo'\n );\n if (this.answerOf(questionId) !== null) throw alreadyAnswered(questionId);\n const id = this.id('m');\n const answer: Message = {\n id,\n thread: target.thread,\n replyTo: questionId,\n from: SYSTEM_ADDRESS,\n to: [target.from],\n kind: 'answer',\n body: `Closed: ${reason}`,\n refs: [],\n data: { type: 'x-closed', reason },\n urgent: false,\n blocking: false,\n wake: 'none',\n createdAt: this.nowIso(),\n };\n // Clocked like a send, so the close sorts after its question in the thread.\n const fed = this.host.federation;\n if (fed !== undefined) answer.hlc = fed.hlc();\n const answered = this.store.transaction(() => {\n this.store.insertMessage(answer);\n return this.markAnswered(questionId);\n });\n this.emit({ type: 'message', message: answer });\n for (const d of answered) this.emit({ type: 'delivery', delivery: d });\n return answer;\n }\n\n // Moves a question's deliveries to answered and returns the moved rows, so\n // the caller can emit them once its transaction has committed.\n private markAnswered(questionId: string): Delivery[] {\n const moved: Delivery[] = [];\n for (const d of this.store.deliveries({ messageId: questionId })) {\n if (d.state === 'answered') continue;\n const next: Delivery = {\n ...d,\n state: 'answered',\n updatedAt: this.nowIso(),\n };\n if (\n this.store.setDelivery(\n next.id,\n next.state,\n next.runId,\n next.updatedAt,\n d.state\n )\n )\n moved.push(next);\n }\n return moved;\n }\n\n // Re-binds held deliveries for a task — addressed to the task or stranded on\n // one of its earlier runs — to its new run, and pushes or notifies them.\n async deliverHeld(runId: string, taskId: string): Promise<Delivery[]> {\n const claimed = this.store.transaction(() => {\n const held = [\n ...this.store.deliveries({\n recipient: `task:${taskId}`,\n states: ['held'],\n }),\n ...this.store\n .deliveries({ recipientPrefix: 'run:', states: ['held'] })\n .filter((d) => this.host.taskOfRun(d.recipient.slice(4)) === taskId),\n ];\n const out: { bound: Delivery; message: Message }[] = [];\n for (const d of held) {\n const message = this.store.getMessage(d.messageId);\n if (message === null) continue;\n const bound: Delivery = {\n ...d,\n state: 'sending',\n runId,\n updatedAt: this.nowIso(),\n };\n const won = this.store.setDelivery(\n bound.id,\n bound.state,\n bound.runId,\n bound.updatedAt,\n 'held'\n );\n if (won) out.push({ bound, message });\n }\n return out;\n });\n const out: Delivery[] = [];\n for (const { bound, message } of claimed)\n out.push((await this.dispatch(bound, message)).delivery);\n return out;\n }\n\n private requireFederation(): FederationHooks {\n const fed = this.host.federation;\n if (fed === undefined) throw new Error('this host does not federate');\n return fed;\n }\n\n // send()'s counterpart for a message another replica created (the router has\n // verified it): applies the engine's rules and delivers what is homed here.\n async receive(\n message: Message,\n origin: RemoteOrigin\n ): Promise<ReceiveResult> {\n const fed = this.requireFederation();\n checkReceivedEnvelope(message);\n // Before the duplicate path too, so a forward never reaches such a target.\n checkReceivedTargets(origin);\n const stored = this.store.getMessage(message.id);\n if (stored !== null) {\n if (!sameSignedContent(stored, this.store.settledAs(stored.id), message))\n throw new MessagingError(\n 'conflict',\n `message id ${message.id} was reused with other content`,\n 'id'\n );\n return {\n status: 'duplicate',\n deliveries: await this.applyForward(stored, origin),\n };\n }\n const replyTarget =\n message.replyTo === null ? null : this.store.getMessage(message.replyTo);\n const root =\n message.thread === message.id\n ? null\n : this.store.getMessage(message.thread);\n checkReceivedThread(message, replyTarget, root);\n const local = localOnlyReason(message, replyTarget, root);\n if (local !== null)\n throw new MessagingError(\n 'forbidden',\n LOCAL_ONLY_TEXT[local],\n local === 'gate' ? 'data' : 'to'\n );\n const { muted } = this.authorizeRemote(message, origin.replica);\n // With the parent missing here, a stored root stands in for participation\n // and the breaker, so a reply joins only a thread its sender is in.\n const joined = replyTarget ?? root;\n if (\n joined !== null &&\n !this.remoteParticipant(joined, message.from, origin.replica, fed)\n )\n throw new MessagingError(\n 'forbidden',\n `${message.from} is not a participant of ${joined.id}`,\n joined === replyTarget ? 'replyTo' : 'thread'\n );\n // Received mode keeps a peer's newer ref types; a missing parent skips\n // only the checks that need it.\n validateSendInput(toSendInput(message), message.from, false, replyTarget, {\n gateTypes: this.gateTypes,\n origin: 'received',\n parentOptional: true,\n });\n const sender: Sender = { address: message.from, canDecide: false };\n await this.checkBreaker(joined, sender, true);\n // Per origin, so a remote agent:dispatch never shares the local system's count.\n const demote =\n message.urgent &&\n !message.from.startsWith('human:') &&\n this.store.countFrom(\n message.from,\n this.hourAgoIso(),\n true,\n origin.replica\n ) >= this.limits.urgentPerHour;\n const answer = this.settleOnArrival(message, replyTarget);\n // Settles that arrived before this question: only its origin's counts.\n const asking = message.kind === 'question' || message.kind === 'handoff';\n const early = this.store.earlySettlements(message.id);\n const valid = asking\n ? (early.find((s) => s.settler === origin.replica) ?? null)\n : null;\n const refused = early.filter((s) => s !== valid);\n const closeHlc =\n valid !== null && valid.closedReason !== null ? fed.hlc() : undefined;\n\n const deliveries: Delivery[] = [];\n const remotes: RemoteDelivery[] = [];\n const seen = new Set<Address>();\n for (const t of origin.targets) {\n if (t.recipient === SYSTEM_ADDRESS || seen.has(t.recipient)) continue;\n seen.add(t.recipient);\n const mine =\n t.homes.includes(fed.replica) || origin.forwardTarget === t.recipient;\n if (!mine) {\n remotes.push(remoteRow(message.id, t, this.nowIso()));\n continue;\n }\n const planned = this.planRemote(t, muted);\n if (deliveries.some((d) => d.recipient === planned.recipient)) continue;\n deliveries.push({ ...planned, messageId: message.id });\n }\n const storedMessage: Message = {\n ...message,\n kind: answer.kind,\n origin: origin.replica,\n };\n const changed: string[] = [];\n const answered = this.store.transaction((): Delivery[] | null => {\n if (this.store.getMessage(message.id) !== null) return null; // a concurrent receive won\n if (answer.swapFirst && message.replyTo !== null)\n changed.push(...this.swapSettled(message.replyTo, message.id));\n this.store.insertMessage(storedMessage, undefined, {\n receivedAt: this.nowIso(),\n ...(answer.settledAs === undefined\n ? {}\n : { settledAs: answer.settledAs }),\n });\n for (const d of deliveries) this.store.insertDelivery(d);\n for (const r of remotes) this.store.insertRemote(r);\n if (answer.recordSettlement && message.replyTo !== null)\n this.store.putSettlement({\n questionId: message.replyTo,\n answerId: message.id,\n closedReason: null,\n settler: fed.replica,\n at: this.nowIso(),\n });\n if (early.length > 0) this.store.clearEarlySettlements(message.id);\n const honoured =\n valid === null\n ? []\n : this.honourSettlement(storedMessage, valid, changed, closeHlc);\n const answeredFirst = asking\n ? this.answerEarly(storedMessage, fed, changed)\n : [];\n return [\n ...honoured,\n ...answeredFirst,\n ...(answer.markAnswered === null\n ? []\n : this.markAnswered(answer.markAnswered)),\n ];\n });\n if (answered === null) return { status: 'duplicate', deliveries: [] };\n this.emit({ type: 'message', message: storedMessage });\n this.emitChanged(changed, message.id);\n for (const d of answered) this.emit({ type: 'delivery', delivery: d });\n for (const r of remotes)\n this.emit({\n type: 'remote',\n messageId: r.messageId,\n recipient: r.recipient,\n });\n\n // A delivery the transaction already moved to answered is not dispatched.\n const moved = new Map(answered.map((d) => [d.id, d]));\n const label = fed.label(origin.replica);\n const settled: Delivery[] = [];\n for (const d of deliveries) {\n const done = moved.get(d.id);\n settled.push(\n done ??\n (\n await this.dispatch(d, storedMessage, {\n remote: label,\n urgent: !demote && message.urgent,\n })\n ).delivery\n );\n }\n try {\n for (const s of refused)\n fed.problem(\n `message:${message.id}`,\n `${s.settler} sent a settle for ${message.id}; only the question's origin settles it`\n );\n // FW-R33: at most a few such notices per question, however many answer.\n if (\n answer.supersededBy !== null &&\n message.replyTo !== null &&\n this.mayNoteSuperseded(message.replyTo, message.id)\n )\n await this.noticeTo(\n message.from,\n message,\n `${message.id} was already answered by ${answer.supersededBy}; yours was kept as a reply.`\n );\n if (storedMessage.wake === 'request') {\n // Exactly one replica wakes a task: the one the origin named in wakeAt.\n const wakeHere = new Set(\n origin.targets\n .filter((t) => t.wakeAt === fed.replica)\n .map((t) => t.recipient)\n );\n const skip = new Set(\n settled.map((d) => d.recipient).filter((r) => !wakeHere.has(r))\n );\n await this.runWake(storedMessage, settled, skip);\n }\n } catch (err) {\n // The message is committed; a failing notice or wake must not fail receive.\n console.error('messaging receive follow-up failed', err);\n }\n return { status: 'applied', deliveries: settled };\n }\n\n // A forward of a message already stored here: delivers its one target here,\n // once, and only in place of its remote row, which the same write retires.\n private async applyForward(\n stored: Message,\n origin: RemoteOrigin\n ): Promise<Delivery[]> {\n if (origin.forwardTarget === undefined) return [];\n const target = origin.targets.find(\n (t) => t.recipient === origin.forwardTarget\n );\n if (target === undefined) return [];\n const muted = this.store.getAgent(stored.from)?.muted === true;\n const planned: Delivery = {\n ...this.planRemote(target, muted),\n messageId: stored.id,\n };\n const inserted = this.store.transaction(() => {\n const existing = this.store.deliveries({\n messageId: stored.id,\n recipient: planned.recipient,\n });\n if (existing.length > 0) return false;\n if (!this.store.deleteRemote(stored.id, target.recipient)) return false;\n this.store.insertDelivery(planned);\n return true;\n });\n if (!inserted) return [];\n this.emit({\n type: 'remote',\n messageId: stored.id,\n recipient: target.recipient,\n });\n return [(await this.dispatch(planned, stored)).delivery];\n }\n\n // A remote agent must be approved here; another replica's system may send\n // only notices about mail it exchanged with this one.\n private authorizeRemote(\n message: Message,\n replica: string\n ): { muted: boolean } {\n const parsed = parseAddress(message.from, 'from');\n if (message.from === SYSTEM_ADDRESS) {\n const about =\n message.kind === 'notice' &&\n message.data === undefined &&\n message.refs.length > 0 &&\n message.refs.every(\n (r) => r.type === 'message' && this.exchangedWith(r.id, replica)\n );\n if (!about)\n throw new MessagingError(\n 'forbidden',\n `${SYSTEM_ADDRESS} from another machine may only send notices about messages exchanged with it`,\n 'from'\n );\n return { muted: false };\n }\n if (parsed.kind === 'task' || parsed.kind === 'channel')\n throw new MessagingError(\n 'forbidden',\n `${message.from} cannot send`,\n 'from'\n );\n if (parsed.kind !== 'agent') return { muted: false };\n const agent = this.store.getAgent(message.from);\n if (agent === null || agent.status !== 'approved')\n throw new MessagingError(\n 'forbidden',\n `${message.from} is not an approved agent`,\n 'from'\n );\n return { muted: agent.muted };\n }\n\n // Whether `replica` created the message, or homes one of its recipients.\n private exchangedWith(messageId: string, replica: string): boolean {\n const m = this.store.getMessage(messageId);\n if (m === null) return false;\n return (\n m.origin === replica ||\n this.store\n .remoteDeliveries({ messageId })\n .some((r) => r.homes.includes(replica))\n );\n }\n\n // Whether a sender on `replica` acts for `target`'s sender or a recipient (here\n // or remote), or is a human whose replica homes one; never for this system.\n private remoteParticipant(\n target: Message,\n from: Address,\n replica: string,\n fed: FederationHooks\n ): boolean {\n const taskOf = (runId: string) =>\n this.host.taskOfRun(runId) ?? fed.remoteRunTask(runId);\n const fromTask = from.startsWith('run:')\n ? taskOf(from.slice('run:'.length))\n : null;\n const actsFor = (address: Address): boolean => {\n if (address === SYSTEM_ADDRESS)\n return from === SYSTEM_ADDRESS && target.origin === replica;\n if (address === from) return true;\n if (fromTask === null) return false;\n return (\n address === `task:${fromTask}` ||\n (address.startsWith('run:') &&\n taskOf(address.slice('run:'.length)) === fromTask)\n );\n };\n const remoteRows = this.store.remoteDeliveries({ messageId: target.id });\n return (\n actsFor(target.from) ||\n target.to.some(actsFor) ||\n this.store\n .deliveries({ messageId: target.id })\n .some((d) => actsFor(d.recipient)) ||\n remoteRows.some((r) => actsFor(r.recipient)) ||\n (from.startsWith('human:') &&\n remoteRows.some((r) => r.homes.includes(replica)))\n );\n }\n\n // Answers that reached this replica before their question, checked against\n // it now: the first that holds up answers it, the rest wait as candidates.\n private answerEarly(\n question: Message,\n fed: FederationHooks,\n changed: string[]\n ): Delivery[] {\n // A settle from the question's origin already chose; honour it as is.\n if (this.store.settlement(question.id) !== null)\n return this.store.answersTo(question.id).length > 0\n ? this.markAnswered(question.id)\n : [];\n const early = this.store\n .answerCandidates(question.id)\n .filter((c) => c.settledAs === 'pending' || c.settledAs === 'candidate');\n const first =\n early.find((c) => this.earlyAnswerHolds(question, c.message, fed)) ??\n null;\n // Demote before promoting, as the one-answer index needs.\n for (const c of early) {\n if (c === first || c.settledAs === 'candidate') continue;\n this.store.setSettled(c.message.id, 'message', 'candidate');\n changed.push(c.message.id);\n }\n if (first === null) return [];\n if (first.settledAs !== 'pending') {\n this.store.setSettled(first.message.id, 'answer', 'pending');\n changed.push(first.message.id);\n }\n return this.markAnswered(question.id);\n }\n\n // Whether an answer stored before its question would have been accepted had\n // the question been here: participation and the checks that need the parent.\n private earlyAnswerHolds(\n question: Message,\n answer: Message,\n fed: FederationHooks\n ): boolean {\n if (\n answer.origin === undefined ||\n !this.remoteParticipant(question, answer.from, answer.origin, fed)\n )\n return false;\n try {\n validateSendInput(\n toSendInput({ ...answer, kind: 'answer' }),\n answer.from,\n false,\n question,\n { gateTypes: this.gateTypes, origin: 'received' }\n );\n return true;\n } catch (err) {\n if (err instanceof MessagingError) return false;\n throw err;\n }\n }\n\n // A received target's first delivery, as plan() gives it, except that a run\n // not live here is reached through its task or else held; never throws.\n private planRemote(t: RemoteTarget, muted: boolean): Delivery {\n const recipient = this.deliverableAddress(t.recipient);\n const held: Delivery = {\n id: this.id('d'),\n messageId: '',\n recipient,\n runId: null,\n via: t.via,\n state: 'held',\n updatedAt: this.nowIso(),\n };\n if (muted) return { ...held, state: 'read' };\n if (recipient.startsWith('run:')) {\n const runId = recipient.slice('run:'.length);\n return this.host.isLiveRun(runId)\n ? { ...held, runId, state: 'sending' }\n : held;\n }\n try {\n return this.plan({ recipient, via: t.via }, false, 'to', true) ?? held;\n } catch {\n return held;\n }\n }\n\n // At the settler the first answer is accepted and later ones superseded;\n // elsewhere the first is pending and the rest candidates, unless already settled.\n private settleOnArrival(\n message: Message,\n question: Message | null\n ): ArrivalSettle {\n const plain: ArrivalSettle = {\n kind: message.kind,\n markAnswered: null,\n recordSettlement: false,\n swapFirst: false,\n supersededBy: null,\n };\n if (message.kind !== 'answer' || message.replyTo === null) return plain;\n const first = this.store.answersTo(message.replyTo)[0] ?? null;\n if (question !== null && question.origin === undefined) {\n if (first === null)\n return {\n ...plain,\n settledAs: 'accepted',\n markAnswered: question.id,\n recordSettlement: true,\n };\n return {\n ...plain,\n kind: 'message',\n settledAs: 'superseded',\n supersededBy: first.from,\n };\n }\n const settlement =\n question === null ? null : this.store.settlement(question.id);\n if (question !== null && settlement !== null) {\n if (settlement.answerId === message.id)\n return {\n ...plain,\n settledAs: 'accepted',\n markAnswered: question.id,\n swapFirst: true,\n };\n return { ...plain, kind: 'message', settledAs: 'superseded' };\n }\n if (first === null)\n return {\n ...plain,\n settledAs: 'pending',\n markAnswered: question?.id ?? null,\n };\n return { ...plain, kind: 'message', settledAs: 'candidate' };\n }\n\n // Merges reports from other homes: remote rows take the maximum, a human's\n // other devices catch up to read or answered, and a task's other homes retire.\n applyState(entries: StateEntry[], publisher: string): void {\n const fed = this.requireFederation();\n const events: EngineEvent[] = [];\n const notices: { to: Address; about: Message; body: string }[] = [];\n this.store.transaction(() => {\n for (const e of entries) {\n if (e.t === 'delivery') this.mergeDelivery(e, publisher, events);\n else this.mergeRefused(e, publisher, fed, events, notices);\n }\n });\n for (const e of events) this.emit(e);\n for (const n of notices)\n void this.noticeTo(n.to, n.about, n.body).catch((err: unknown) =>\n console.error('messaging refusal notice failed', err)\n );\n }\n\n // One home's delivery report: its remote row moves up, a local human\n // delivery catches up, and a local held task copy retires to a remote row.\n private mergeDelivery(\n e: DeliveryEntry,\n publisher: string,\n events: EngineEvent[]\n ): void {\n const now = this.nowIso();\n const where = { messageId: e.message, recipient: e.recipient };\n for (const row of this.store.remoteDeliveries(where)) {\n if (!row.homes.includes(publisher)) continue;\n const state = maxRemote(row.state, e.state);\n if (state === row.state) continue;\n const patch =\n row.state === 'refused' ? { state, refusedBy: [] } : { state };\n if (\n this.store.setRemote(\n row.messageId,\n row.recipient,\n patch,\n now,\n row.state\n )\n )\n events.push({ type: 'remote', ...where });\n }\n for (const d of this.store.deliveries(where)) {\n if (d.recipient.startsWith('human:')) {\n if (e.state !== 'read' && e.state !== 'answered') continue;\n if (LOCAL_RANK[e.state] <= LOCAL_RANK[d.state]) continue;\n if (this.store.setDelivery(d.id, e.state, d.runId, now, d.state))\n events.push({\n type: 'delivery',\n delivery: { ...d, state: e.state, updatedAt: now },\n });\n } else if (\n d.recipient.startsWith('task:') &&\n d.state === 'held' &&\n REMOTE_RANK[e.state] >= REMOTE_RANK.pushed\n ) {\n this.store.deleteDelivery(d.id);\n this.putRemote(d, [publisher], e.state, now);\n events.push({ type: 'remote', ...where });\n }\n }\n }\n\n // One home refused a message sent here: once every home of a recipient has,\n // its row is refused and the sender told; a pending local answer reopens.\n private mergeRefused(\n e: RefusedEntry,\n publisher: string,\n fed: FederationHooks,\n events: EngineEvent[],\n notices: { to: Address; about: Message; body: string }[]\n ): void {\n const message = this.store.getMessage(e.message);\n if (message === null || message.origin !== undefined) return;\n const now = this.nowIso();\n let newlyRefused = false;\n for (const row of this.store.remoteDeliveries({ messageId: message.id })) {\n if (!row.homes.includes(publisher) || row.refusedBy.includes(publisher))\n continue;\n const refusedBy = [...row.refusedBy, publisher];\n const all = row.homes.every((h) => refusedBy.includes(h));\n const state: RemoteState = all ? 'refused' : row.state;\n if (\n !this.store.setRemote(\n row.messageId,\n row.recipient,\n { state, refusedBy },\n now,\n row.state\n )\n )\n continue;\n events.push({\n type: 'remote',\n messageId: row.messageId,\n recipient: row.recipient,\n });\n if (all && row.state !== 'refused') newlyRefused = true;\n }\n if (newlyRefused && message.from !== SYSTEM_ADDRESS)\n notices.push({\n to: message.from,\n about: message,\n body: `${message.id} was refused by ${fed.label(publisher)}'s machine: ${e.reason}.`,\n });\n // Only the question's settler can refuse an answer as already answered.\n const question =\n message.replyTo === null ? null : this.store.getMessage(message.replyTo);\n if (\n question === null ||\n question.origin !== publisher ||\n this.store.settledAs(message.id) !== 'pending'\n )\n return;\n this.store.setSettled(message.id, 'message', null);\n events.push({ type: 'message', message: { ...message, kind: 'message' } });\n for (const d of this.store.deliveries({\n messageId: question.id,\n states: ['answered'],\n })) {\n const state: DeliveryState = d.recipient.startsWith('human:')\n ? 'notified'\n : 'held';\n if (this.store.setDelivery(d.id, state, null, now, 'answered'))\n events.push({\n type: 'delivery',\n delivery: { ...d, state, runId: null, updatedAt: now },\n });\n }\n }\n\n // Only the settler is believed; a settle for a question not stored yet waits,\n // per publisher, until the question arrives and names its origin.\n applySettlement(entry: SettleEntry, publisher: string): void {\n const fed = this.requireFederation();\n const record: Settlement = {\n questionId: entry.question,\n answerId: entry.answer,\n closedReason: entry.closed ?? null,\n settler: publisher,\n at: entry.at,\n };\n const q = this.store.getMessage(entry.question);\n if (q === null) {\n this.store.putEarlySettlement(record);\n return;\n }\n if ((q.origin ?? fed.replica) !== publisher)\n throw new MessagingError(\n 'forbidden',\n `${publisher} did not ask ${entry.question}`,\n 'question'\n );\n const closeHlc = entry.closed === undefined ? undefined : fed.hlc();\n const changed: string[] = [];\n const moved = this.store.transaction(() =>\n this.honourSettlement(q, record, changed, closeHlc)\n );\n this.emitChanged(changed);\n for (const d of moved) this.emit({ type: 'delivery', delivery: d });\n }\n\n // Records a settler's outcome for a stored question and applies it: swaps in\n // its answer, or writes its close; an answer not here yet waits to land.\n private honourSettlement(\n q: Message,\n s: Settlement,\n changed: string[],\n closeHlc: string | undefined\n ): Delivery[] {\n const answer =\n s.answerId === null ? null : this.store.getMessage(s.answerId);\n // A stored message that was never an answer to q cannot settle it.\n if (\n answer !== null &&\n !this.store.answerCandidates(q.id).some((c) => c.message.id === answer.id)\n )\n return [];\n this.store.putSettlement(s);\n if (s.answerId === null) return [];\n if (answer !== null) {\n changed.push(...this.swapSettled(q.id, s.answerId));\n return this.markAnswered(q.id);\n }\n // FW-R33: an answer that has not arrived supersedes nothing yet.\n if (s.closedReason === null) return [];\n changed.push(...this.demoteOtherAnswers(q.id, s.answerId));\n this.store.insertMessage(\n closeCopy(\n q,\n s.answerId,\n s.closedReason,\n s.settler,\n this.nowIso(),\n closeHlc\n ),\n undefined,\n { receivedAt: this.nowIso(), settledAs: 'accepted' }\n );\n changed.push(s.answerId);\n return this.markAnswered(q.id);\n }\n\n // 1. every other answer row → message/superseded; 2. the accepted row →\n // answer/accepted, in the order the one-answer index needs. Returns the ids changed.\n private swapSettled(questionId: string, answerId: string): string[] {\n const changed = this.demoteOtherAnswers(questionId, answerId);\n this.store.setSettled(answerId, 'answer', 'accepted');\n return [...changed, answerId];\n }\n\n // Every answer or answer candidate of a question but `keep` becomes a superseded reply.\n private demoteOtherAnswers(questionId: string, keep: string): string[] {\n const changed: string[] = [];\n for (const c of this.store.answerCandidates(questionId)) {\n if (c.message.id === keep) continue;\n if (c.message.kind !== 'answer' && c.settledAs === 'superseded') continue;\n this.store.setSettled(c.message.id, 'message', 'superseded');\n changed.push(c.message.id);\n }\n return changed;\n }\n\n // Emits each rewritten message once, as it is stored now.\n private emitChanged(ids: string[], skip?: string): void {\n for (const id of new Set(ids)) {\n if (id === skip) continue;\n const m = this.store.getMessage(id);\n if (m !== null) this.emit({ type: 'message', message: m });\n }\n }\n\n // Turns this replica's forwarded or held remote rows for a task into local\n // held deliveries, so a run starting here receives what waited elsewhere.\n claimRemote(taskId: string): Delivery[] {\n const recipient = `task:${taskId}`;\n const now = this.nowIso();\n const retired: string[] = [];\n const claimed = this.store.transaction(() => {\n const out: Delivery[] = [];\n for (const row of this.store.remoteDeliveries({\n recipient,\n states: ['forwarded', 'held'],\n })) {\n if (this.store.getMessage(row.messageId) === null) continue;\n if (this.store.deleteRemote(row.messageId, recipient))\n retired.push(row.messageId);\n const existing = this.store.deliveries({\n messageId: row.messageId,\n recipient,\n });\n if (existing.length > 0) continue;\n const d: Delivery = {\n id: this.id('d'),\n messageId: row.messageId,\n recipient,\n runId: null,\n via: row.via,\n state: 'held',\n updatedAt: now,\n };\n this.store.insertDelivery(d);\n out.push(d);\n }\n return out;\n });\n for (const messageId of retired)\n this.emit({ type: 'remote', messageId, recipient });\n for (const d of claimed) this.emit({ type: 'delivery', delivery: d });\n return claimed;\n }\n\n // Moves this replica's own delivery of a message to a remote row once other\n // homes hold it, so it is never delivered twice; the row starts at `state`.\n moveToRemote(\n messageId: string,\n recipient: Address,\n homes: string[],\n state: RemoteState = 'forwarded'\n ): void {\n const now = this.nowIso();\n const moved = this.store.transaction(() => {\n const local = this.store.deliveries({ messageId, recipient });\n const [first] = local;\n if (first === undefined) return false;\n for (const d of local) this.store.deleteDelivery(d.id);\n this.putRemote(first, homes, state, now);\n return true;\n });\n if (moved) this.emit({ type: 'remote', messageId, recipient });\n }\n\n // Adds a remote row for a delivery leaving this replica, or merges its\n // homes and state into the row already there.\n private putRemote(\n d: Delivery,\n homes: string[],\n state: RemoteState,\n now: string\n ): void {\n const row: RemoteDelivery = {\n messageId: d.messageId,\n recipient: d.recipient,\n via: d.via,\n state,\n homes,\n wakeAt: null,\n refusedBy: [],\n updatedAt: now,\n };\n if (this.store.insertRemote(row)) return;\n const [existing] = this.store.remoteDeliveries({\n messageId: d.messageId,\n recipient: d.recipient,\n });\n if (existing === undefined) return;\n this.store.setRemote(\n d.messageId,\n d.recipient,\n {\n state: maxRemote(existing.state, state),\n homes: [...new Set([...existing.homes, ...homes])],\n },\n now\n );\n }\n\n // Tells a sender something went sideways, as a system notice in its thread;\n // a sender run that has ended hears it through its task.\n // Whether `answerId`'s superseded notice is within the question's cap.\n // Counted from the store (one notice per earlier superseded answer), so a\n // restart keeps the count.\n private mayNoteSuperseded(questionId: string, answerId: string): boolean {\n const earlier = this.store\n .answerCandidates(questionId)\n .filter(\n (c) => c.settledAs === 'superseded' && c.message.id !== answerId\n ).length;\n return earlier < MAX_SUPERSEDED_NOTICES;\n }\n\n private async noticeTo(\n recipient: Address,\n about: Message,\n body: string\n ): Promise<void> {\n await this.send(\n {\n to: [this.deliverableAddress(recipient)],\n kind: 'notice',\n body,\n refs: [{ type: 'message', id: about.id }],\n },\n SYSTEM_SENDER\n );\n }\n\n // After a wake-requesting send, asks the host to wake (or gate or deny) each\n // held task recipient, except those in `skip`, which another replica wakes.\n private async runWake(\n message: Message,\n settled: Delivery[],\n skip: ReadonlySet<Address>\n ): Promise<void> {\n const wakesRuns = wakesEndedRuns(message);\n for (const d of settled) {\n if (d.state !== 'held' || skip.has(d.recipient)) continue;\n if (\n !d.recipient.startsWith('task:') &&\n !(wakesRuns && d.recipient.startsWith('run:'))\n )\n continue;\n const request: PolicyRequest = {\n type: 'wake',\n target: d.recipient,\n message,\n };\n if (message.origin !== undefined) request.origin = message.origin;\n const ruling = this.host.decide(request);\n if (ruling === 'allow') {\n let result: WakeResult;\n try {\n result = await this.host.wake(d.recipient, message);\n } catch (err) {\n console.error('messaging hook failed', err);\n result = {\n ok: false,\n reason: err instanceof Error ? err.message : String(err),\n };\n }\n if (!result.ok)\n await this.noticeTo(\n message.from,\n message,\n `Could not wake ${d.recipient}: ${result.reason}. Your message is waiting for it.`\n );\n } else if (ruling === 'deny') {\n await this.noticeTo(\n message.from,\n message,\n `Waking ${d.recipient} was not allowed. Your message is waiting for it.`\n );\n } else {\n // Merged into an open gate for the same target: approving it wakes the\n // target, and this message is already held for it.\n if (\n this.openWakeGates(d.recipient) >= this.limits.openWakeGatesPerTarget\n )\n continue;\n const label = this.remoteLabel(message);\n const who =\n label === undefined\n ? message.from\n : `${message.from} (remote: ${label})`;\n await this.send(\n {\n to: [this.host.owner(d.recipient, message.from)],\n kind: 'question',\n blocking: true,\n choices: ['approve', 'deny'],\n body: `${who} wants to wake ${d.recipient}:\\n\\n> ${firstLine(message.body)}`,\n data: { type: 'wake', target: d.recipient, message: message.id },\n refs: [{ type: 'message', id: message.id }],\n },\n SYSTEM_SENDER\n );\n }\n }\n }\n\n // Rejects a new agent-to-agent thread past the sender's hourly allowance,\n // so starting fresh threads cannot sidestep the reply breaker. Only roots\n // that name an agent, run or task and no human count: channels and A2A\n // peers have limits of their own.\n private checkNewThreads(\n input: SendInput,\n replyTarget: Message | null,\n sender: Sender\n ): void {\n if (\n replyTarget !== null ||\n !isAgentAuthored(sender.address) ||\n !isAgentThread(input.to)\n )\n return;\n const started = this.store.countAgentThreadsFrom(\n sender.address,\n this.hourAgoIso()\n );\n if (started < this.limits.agentThreadsPerHour) return;\n throw new MessagingError(\n 'limited',\n `${sender.address} started ${started} new threads with other agents this hour; message a human or wait`,\n 'to'\n );\n }\n\n // How many wake gates for `target` are still open.\n private openWakeGates(target: Address): number {\n return this.openBlocking().filter((m) => {\n const gate = gateOf(m);\n return gate?.type === 'wake' && gate.target === target;\n }).length;\n }\n\n // Rejects an agent reply past the thread's hourly agent turns, flagging the owner\n // once; a `remote` agent:dispatch counts as an ordinary agent.\n private async checkBreaker(\n replyTarget: Message | null,\n sender: Sender,\n remote = false\n ): Promise<void> {\n const agentAuthored =\n isAgentAuthored(sender.address) ||\n (remote && sender.address === SYSTEM_ADDRESS);\n if (replyTarget === null || !agentAuthored) return;\n const since = this.hourAgoIso();\n const count = this.store.countAgentAuthored(\n replyTarget.thread,\n since,\n SYSTEM_ADDRESS\n );\n if (count < this.limits.agentTurnsPerThreadPerHour) return;\n const flagged = this.store\n .thread(replyTarget.thread)\n .some((m) => isSystemMarker(m, 'x-breaker') && m.createdAt >= since);\n if (!flagged) {\n await this.send(\n {\n to: [this.host.owner(sender.address)],\n kind: 'notice',\n replyTo: replyTarget.id,\n body: `Agents have sent ${count} messages in thread ${replyTarget.thread} this hour; further agent replies are paused.`,\n data: { type: 'x-breaker', thread: replyTarget.thread },\n },\n SYSTEM_SENDER\n );\n }\n throw new MessagingError(\n 'limited',\n `thread ${replyTarget.thread} hit the agent turn limit; a human has been asked to step in`,\n 'replyTo'\n );\n }\n}\n\nfunction alreadyAnswered(questionId: string): MessagingError {\n return new MessagingError(\n 'conflict',\n `${questionId} is already answered`,\n 'replyTo'\n );\n}\n\n// A deciding principal: the system, or a human the host lets decide.\nfunction decides(sender: Sender): boolean {\n return (\n sender.address === SYSTEM_ADDRESS ||\n (sender.canDecide && sender.address.startsWith('human:'))\n );\n}\n\n// The higher of a remote row's state and a home's report: any report replaces\n// refused, and between pushed and notified the row keeps what it holds.\nfunction maxRemote(current: RemoteState, reported: RemoteState): RemoteState {\n if (current === 'refused') return reported;\n return REMOTE_RANK[reported] > REMOTE_RANK[current] ? reported : current;\n}\n\n// A received target homed on other replicas, waiting for their reports.\nfunction remoteRow(\n messageId: string,\n t: RemoteTarget,\n now: string\n): RemoteDelivery {\n return {\n messageId,\n recipient: t.recipient,\n via: t.via,\n state: 'forwarded',\n homes: t.homes,\n wakeAt: t.wakeAt ?? null,\n refusedBy: [],\n updatedAt: now,\n };\n}\n\n// A settler's close as a non-settler stores it: under the settler's answer id,\n// from the system address with the settler as origin, so never a local marker.\nfunction closeCopy(\n q: Message,\n id: string,\n reason: string,\n settler: string,\n now: string,\n hlc: string | undefined\n): Message {\n const close: Message = {\n id,\n thread: q.thread,\n replyTo: q.id,\n from: SYSTEM_ADDRESS,\n to: [q.from],\n kind: 'answer',\n body: `Closed: ${reason}`,\n refs: [],\n data: { type: 'x-closed', reason },\n urgent: false,\n blocking: false,\n wake: 'none',\n createdAt: now,\n origin: settler,\n };\n // Clocked here, so the close sorts after its question in the thread.\n if (hlc !== undefined) close.hlc = hlc;\n return close;\n}\n\n// The send input a received message stands for, so validation judges it as\n// it would a local send.\nfunction toSendInput(m: Message): SendInput {\n const input: SendInput = {\n to: m.to,\n kind: m.kind,\n body: m.body,\n refs: m.refs,\n urgent: m.urgent,\n blocking: m.blocking,\n replyTo: m.replyTo,\n wake: m.wake,\n };\n if (m.data !== undefined) input.data = m.data;\n if (m.choices !== undefined) input.choices = m.choices;\n if (m.choice !== undefined) input.choice = m.choice;\n if (m.session !== undefined) input.session = m.session;\n return input;\n}\n\nfunction malformed(field: string, why: string): never {\n throw new MessagingError('invalid', `${field}: ${why}`, field);\n}\n\n// A received message's shape, checked before any rule reads it: its ids are\n// identifiers, so none can break a rendered line, and every field has its type.\nfunction checkReceivedEnvelope(m: Message): void {\n if (!isIdentifier(m.id)) malformed('id', 'expected a message id');\n if (!isIdentifier(m.thread)) malformed('thread', 'expected a message id');\n if (m.replyTo !== null && !isIdentifier(m.replyTo))\n malformed('replyTo', 'expected a message id or null');\n for (const field of ['from', 'kind', 'body', 'createdAt'] as const)\n if (typeof m[field] !== 'string') malformed(field, 'expected a string');\n for (const field of ['session', 'hlc', 'choice'] as const)\n if (m[field] !== undefined && typeof m[field] !== 'string')\n malformed(field, 'expected a string');\n if (!Array.isArray(m.to)) malformed('to', 'expected a list');\n checkStrings(m.to, 'to');\n if (m.choices !== undefined) {\n if (!Array.isArray(m.choices)) malformed('choices', 'expected a list');\n checkStrings(m.choices, 'choices');\n }\n if (\n !Array.isArray(m.refs) ||\n !m.refs.every((r) => typeof r === 'object' && r !== null)\n )\n malformed('refs', 'expected a list of refs');\n m.refs.forEach((r, i) => {\n if (typeof r.type !== 'string')\n malformed(`refs[${i}].type`, 'expected a string');\n if (typeof r.id !== 'string')\n malformed(`refs[${i}].id`, 'expected a string');\n if (r.at !== undefined && typeof r.at !== 'string')\n malformed(`refs[${i}].at`, 'expected a string');\n });\n if (typeof m.urgent !== 'boolean') malformed('urgent', 'expected a boolean');\n if (typeof m.blocking !== 'boolean')\n malformed('blocking', 'expected a boolean');\n if (m.wake !== 'none' && m.wake !== 'request')\n malformed('wake', 'expected none or request');\n}\n\n// Refuses the first element of a received list that is not a string.\nfunction checkStrings(list: readonly unknown[], field: string): void {\n list.forEach((v, i) => {\n if (typeof v !== 'string') malformed(`${field}[${i}]`, 'expected a string');\n });\n}\n\n// The origin's resolution, shaped as RemoteTarget, may name only addresses\n// that parse and may leave their machine; any failure refuses the message.\nfunction checkReceivedTargets(origin: RemoteOrigin): void {\n if (!Array.isArray(origin.targets)) malformed('targets', 'expected a list');\n if (\n origin.forwardTarget !== undefined &&\n typeof origin.forwardTarget !== 'string'\n )\n malformed('forwardTarget', 'expected an address');\n origin.targets.forEach((raw: unknown, i) => {\n const at = `targets[${i}]`;\n const t: Partial<Record<keyof RemoteTarget, unknown>> =\n typeof raw === 'object' && raw !== null ? raw : {};\n if (typeof t.recipient !== 'string')\n malformed(`${at}.recipient`, 'expected an address');\n if (t.via !== 'direct' && t.via !== 'channel')\n malformed(`${at}.via`, 'expected direct or channel');\n if (!Array.isArray(t.homes)) malformed(`${at}.homes`, 'expected a list');\n checkStrings(t.homes, `${at}.homes`);\n if (t.wakeAt !== undefined && typeof t.wakeAt !== 'string')\n malformed(`${at}.wakeAt`, 'expected a replica id');\n if (isFederationLocalAddress(t.recipient))\n throw new MessagingError('forbidden', LOCAL_ONLY_TEXT.participant, 'to');\n parseAddress(t.recipient, at);\n });\n}\n\n// Refuses what no honest sender files: a root is its own thread, a reply\n// joins its target's and never names itself, and a thread names a root.\nfunction checkReceivedThread(\n m: Message,\n replyTarget: Message | null,\n root: Message | null\n): void {\n if (m.replyTo === m.id)\n malformed('replyTo', 'a message cannot reply to itself');\n if (root !== null && root.thread !== root.id)\n malformed('thread', `${root.id} is a reply, not a thread's first message`);\n if (m.replyTo === null && m.thread !== m.id)\n malformed(\n 'thread',\n 'a message that replies to nothing starts its own thread'\n );\n if (replyTarget !== null && m.thread !== replyTarget.thread)\n malformed(\n 'thread',\n `expected ${replyTarget.thread}, the thread of ${replyTarget.id}`\n );\n}\n\n// The fields an origin signs; `origin` is this replica's own record of it.\nconst SIGNED_FIELDS = [\n 'id',\n 'thread',\n 'replyTo',\n 'from',\n 'session',\n 'to',\n 'kind',\n 'body',\n 'refs',\n 'data',\n 'urgent',\n 'blocking',\n 'choices',\n 'choice',\n 'wake',\n 'createdAt',\n 'hlc',\n] as const;\n\n// Whether an incoming copy carries the stored message's signed content; a\n// superseded or candidate row is stored as a reply but was signed as an answer.\nfunction sameSignedContent(\n stored: Message,\n settledAs: SettledAs | null,\n incoming: Message\n): boolean {\n const storedKind =\n settledAs === 'superseded' || settledAs === 'candidate'\n ? 'answer'\n : stored.kind;\n const signed = (m: Message, kind: MessageKind) =>\n canonical(\n Object.fromEntries(\n SIGNED_FIELDS.map((f) => [f, f === 'kind' ? kind : m[f]])\n )\n );\n return signed(stored, storedKind) === signed(incoming, incoming.kind);\n}\n\n// JSON with object keys sorted and undefined members dropped, so two copies of\n// one message compare equal whatever order their fields arrived in.\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record)\n .filter((k) => record[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(record[k])}`).join(',')}}`;\n }\n const text: string | undefined = JSON.stringify(value);\n return text ?? 'null';\n}\n\n// Only a local human's wake may name an ended run: it asks to continue exactly\n// that run. A message from another replica never continues one.\nfunction wakesEndedRuns(message: Message): boolean {\n return (\n message.wake === 'request' &&\n message.origin === undefined &&\n message.from.startsWith('human:')\n );\n}\n\n// A root among agents: it names an agent, run or task, and no human.\nfunction isAgentThread(to: readonly Address[]): boolean {\n return (\n !to.some((a) => a.startsWith('human:')) &&\n to.some(\n (a) =>\n a.startsWith('agent:') || a.startsWith('run:') || a.startsWith('task:')\n )\n );\n}\n","import type { Address } from './address.js';\nimport { DELIVERY_STATES } from './constants.js';\nimport type { Message, MessageKind } from './envelope.js';\n\nexport { DELIVERY_STATES };\nexport type DeliveryState = (typeof DELIVERY_STATES)[number];\n\nexport type DeliveryVia = 'direct' | 'channel';\n\n/** How a federated thread settled an answer; superseded and candidate rows are stored as `message`. */\nexport type SettledAs = 'pending' | 'accepted' | 'superseded' | 'candidate';\n\n/** A recipient homed on another replica: the furthest state its homes report. */\nexport type RemoteState =\n | 'forwarded'\n | 'held'\n | 'pushed'\n | 'notified'\n | 'read'\n | 'answered'\n | 'refused';\nexport const REMOTE_STATES: readonly RemoteState[] = [\n 'forwarded',\n 'held',\n 'pushed',\n 'notified',\n 'read',\n 'answered',\n 'refused',\n];\n\nexport interface RemoteDelivery {\n messageId: string;\n recipient: Address;\n via: DeliveryVia;\n state: RemoteState;\n /** The replicas placement chose for this recipient. */\n homes: string[];\n /** The one home that runs a wake request for a task recipient. */\n wakeAt: string | null;\n refusedBy: string[];\n updatedAt: string;\n}\n\n/** A question's outcome as its settler recorded it: an answer or a close reason. */\nexport interface Settlement {\n questionId: string;\n answerId: string | null;\n closedReason: string | null;\n settler: string;\n at: string;\n}\n\n/** Per-row facts that are not part of the message itself. */\nexport interface StoredMeta {\n /** Local arrival time of a remote message; quotas count by it. */\n receivedAt?: string;\n settledAs?: SettledAs;\n}\n\nexport interface Delivery {\n id: string;\n messageId: string;\n recipient: Address;\n runId: string | null;\n via: DeliveryVia;\n state: DeliveryState;\n updatedAt: string;\n}\n\nexport type AgentStatus = 'pending' | 'approved' | 'revoked';\n\nexport interface AgentRecord {\n address: Address;\n displayName: string;\n client: string;\n tokenHash: string;\n status: AgentStatus;\n muted: boolean;\n approvedBy: string | null;\n createdAt: string;\n}\n\nexport interface ChannelRecord {\n name: string;\n createdAt: string;\n auto: boolean;\n}\n\n/** One thread's most recent state: its opening message, its latest message\n * (the same one when a thread has only one message), and how many it holds. */\nexport interface ThreadSummary {\n thread: string;\n root: Message;\n last: Message;\n count: number;\n}\n\nexport interface DeliveryFilter {\n recipient?: Address;\n states?: DeliveryState[];\n runId?: string;\n messageId?: string;\n /** Matches recipients starting with this prefix, e.g. `run:`. */\n recipientPrefix?: string;\n}\n\nexport interface MessageStore {\n transaction<T>(fn: () => T): T;\n /** `idemKey` is the sender's dedupe key, unique per sender when set. */\n insertMessage(message: Message, idemKey?: string, meta?: StoredMeta): void;\n insertDelivery(delivery: Delivery): void;\n /** Removes one local delivery row; returns whether it existed. */\n deleteDelivery(id: string): boolean;\n getMessage(id: string): Message | null;\n /** The message `from` sent under `key`, or null. */\n byIdemKey(from: Address, key: string): Message | null;\n /** Each given message's dedupe key; keyless and unknown ids are left out. */\n idemKeysFor(messageIds: string[]): Map<string, string>;\n /** What `address` sent at or after `sinceIso`, oldest first, optionally only these kinds. */\n messagesFrom(\n address: Address,\n sinceIso: string,\n kinds?: MessageKind[]\n ): Message[];\n thread(threadId: string): Message[];\n answersTo(messageId: string): Message[];\n openBlocking(): Message[];\n getDelivery(id: string): Delivery | null;\n deliveries(filter: DeliveryFilter): Delivery[];\n /** With `expected`, updates only if the row is still in that state; returns whether it changed. */\n setDelivery(\n id: string,\n state: DeliveryState,\n runId: string | null,\n at: string,\n expected?: DeliveryState\n ): boolean;\n markGateApplied(questionId: string, at: string): void;\n /** Turns an answer back into a message and records it voided, which reopens its question. */\n voidAnswer(answerId: string, questionId: string, at: string): boolean;\n /** Answered gate questions (closes excluded) whose host effect is not yet recorded. */\n unappliedAnsweredGates(): { question: Message; answer: Message }[];\n /** Messages from `from` that arrived at or after `sinceIso`, and not after\n * `untilIso` when given; `origin` narrows to one replica's. */\n countFrom(\n from: Address,\n sinceIso: string,\n urgentOnly: boolean,\n origin?: string,\n untilIso?: string\n ): number;\n /** Messages created in [sinceIso, untilIso] with a delivery to `recipient`; the per-peer quota. */\n countDeliveredTo(\n recipient: Address,\n sinceIso: string,\n untilIso?: string\n ): number;\n /** Threads `from` started since `sinceIso` that name an agent, run or task and reach no human. */\n countAgentThreadsFrom(from: Address, sinceIso: string): number;\n /** Agent-authored messages in a thread by arrival; a remote `exclude` still counts. */\n countAgentAuthored(\n threadId: string,\n sinceIso: string,\n exclude: Address\n ): number;\n /** The row's settled state, or null when unset or the message is unknown. */\n settledAs(messageId: string): SettledAs | null;\n /** Rewrites a reply's stored kind and settled state together. */\n setSettled(\n messageId: string,\n kind: 'answer' | 'message',\n settledAs: SettledAs | null\n ): void;\n /** Replies to a question that are or were answers, in arrival order. */\n answerCandidates(\n questionId: string\n ): { message: Message; settledAs: SettledAs | null }[];\n /** Adds a remote recipient's row; returns false when one already exists. */\n insertRemote(row: RemoteDelivery): boolean;\n /** Remote recipient rows matching every given field. */\n remoteDeliveries(filter: {\n messageId?: string;\n recipient?: Address;\n states?: RemoteState[];\n }): RemoteDelivery[];\n /** With `expected`, updates only if the row is still in that state; returns whether it changed. */\n setRemote(\n messageId: string,\n recipient: Address,\n patch: { state?: RemoteState; refusedBy?: string[]; homes?: string[] },\n at: string,\n expected?: RemoteState\n ): boolean;\n /** Removes a remote recipient's row; returns whether it existed. */\n deleteRemote(messageId: string, recipient: Address): boolean;\n /** A question's recorded settlement, or null. */\n settlement(questionId: string): Settlement | null;\n /** Records or replaces a question's settlement. */\n putSettlement(settlement: Settlement): void;\n /** Keeps a settle for a question not stored yet, one per publisher; never read as a settlement. */\n putEarlySettlement(settlement: Settlement): void;\n /** The early settles kept for a question, one per publisher. */\n earlySettlements(questionId: string): Settlement[];\n /** Drops a question's early settles once it has been stored. */\n clearEarlySettlements(questionId: string): void;\n /** Messages created here after `rowid`, oldest first; remote rows are skipped. */\n messagesAfter(\n rowid: number,\n limit: number\n ): { rowid: number; message: Message }[];\n /** The highest message rowid, or 0 for an empty store. */\n maxRowid(): number;\n ensureChannel(name: string, at: string, auto: boolean): void;\n channels(): ChannelRecord[];\n /** Adds a member; false when it was already in the channel. */\n addMember(channel: string, member: Address, at: string): boolean;\n removeMember(channel: string, member: Address): boolean;\n members(channel: string): Address[];\n channelsOf(member: Address): string[];\n putAgent(agent: AgentRecord): void;\n getAgent(address: Address): AgentRecord | null;\n agentByTokenHash(hash: string): AgentRecord | null;\n agents(): AgentRecord[];\n}\n","import {\n dbVersion,\n openSqliteDb,\n queryAll,\n queryOne,\n} from '@dispatch-foo/core';\nimport type { SqliteDatabase, SqlValue } from '@dispatch-foo/core';\n\nimport type { Address } from './address.js';\nimport { hasGateData } from './constants.js';\nimport { isSystemMarker } from './envelope.js';\nimport type { JsonValue, Message, MessageKind, Ref } from './envelope.js';\nimport { DELIVERY_STATES, REMOTE_STATES } from './store.js';\nimport type {\n AgentRecord,\n AgentStatus,\n ChannelRecord,\n Delivery,\n DeliveryFilter,\n DeliveryState,\n DeliveryVia,\n MessageStore,\n RemoteDelivery,\n RemoteState,\n SettledAs,\n Settlement,\n StoredMeta,\n ThreadSummary,\n} from './store.js';\n\nexport const MESSAGES_DB_VERSION = 1;\n\nconst DDL = `\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY, thread TEXT NOT NULL, reply_to TEXT, from_addr TEXT NOT NULL,\n session TEXT, kind TEXT NOT NULL, body TEXT NOT NULL, refs_json TEXT NOT NULL,\n data_json TEXT, urgent INTEGER NOT NULL, blocking INTEGER NOT NULL,\n choices_json TEXT, choice TEXT, wake TEXT NOT NULL, created_at TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS messages_thread ON messages (thread, id);\nCREATE INDEX IF NOT EXISTS messages_reply ON messages (reply_to);\nCREATE INDEX IF NOT EXISTS messages_from ON messages (from_addr, created_at);\nCREATE UNIQUE INDEX IF NOT EXISTS messages_one_answer ON messages (reply_to) WHERE kind = 'answer';\nCREATE TABLE IF NOT EXISTS recipients (\n message_id TEXT NOT NULL, position INTEGER NOT NULL, addr TEXT NOT NULL,\n PRIMARY KEY (message_id, position)\n);\nCREATE INDEX IF NOT EXISTS recipients_addr ON recipients (addr);\nCREATE TABLE IF NOT EXISTS deliveries (\n id TEXT PRIMARY KEY, message_id TEXT NOT NULL, recipient TEXT NOT NULL,\n run_id TEXT, via TEXT NOT NULL, state TEXT NOT NULL, updated_at TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS deliveries_recipient ON deliveries (recipient, state);\nCREATE INDEX IF NOT EXISTS deliveries_message ON deliveries (message_id);\nCREATE INDEX IF NOT EXISTS deliveries_run ON deliveries (run_id);\nCREATE TABLE IF NOT EXISTS channels (\n name TEXT PRIMARY KEY, created_at TEXT NOT NULL, auto INTEGER NOT NULL\n);\nCREATE TABLE IF NOT EXISTS members (\n channel TEXT NOT NULL, addr TEXT NOT NULL, joined_at TEXT NOT NULL,\n PRIMARY KEY (channel, addr)\n);\nCREATE TABLE IF NOT EXISTS agents (\n addr TEXT PRIMARY KEY, display_name TEXT NOT NULL, client TEXT NOT NULL,\n token_hash TEXT NOT NULL UNIQUE, status TEXT NOT NULL, muted INTEGER NOT NULL,\n approved_by TEXT, created_at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS gate_effects (\n question_id TEXT PRIMARY KEY, applied_at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS voided_answers (\n answer_id TEXT PRIMARY KEY, question_id TEXT NOT NULL, at TEXT NOT NULL\n);\n`;\n\n// Opens (creating if needed) a messages database and applies its schema;\n// refuses a file stamped by a newer build rather than downgrading it.\nexport function openMessagesDb(path: string): SqliteDatabase {\n const db = openSqliteDb(path);\n const existing = dbVersion(db);\n if (existing > MESSAGES_DB_VERSION) {\n db.close();\n throw new Error(\n `messages database at ${path} was written by a newer schema (version ${existing}, this build understands ${MESSAGES_DB_VERSION})`\n );\n }\n db.exec(DDL);\n addIdemKey(db);\n addFederationSchema(db);\n addMessageRefs(db);\n db.exec(`PRAGMA user_version = ${MESSAGES_DB_VERSION}`);\n return db;\n}\n\n// Additive, so an older build still opens and writes the file: its insert names\n// its columns and leaves idem_key NULL, which the partial index ignores.\nexport function addIdemKey(db: SqliteDatabase): void {\n if (!hasIdemKey(db)) {\n try {\n db.exec('ALTER TABLE messages ADD COLUMN idem_key TEXT');\n } catch (err) {\n // A daemon opening the same file at once may have added it first.\n if (!hasIdemKey(db)) throw err;\n }\n }\n db.exec(\n 'CREATE UNIQUE INDEX IF NOT EXISTS messages_idem ON messages (from_addr, idem_key) WHERE idem_key IS NOT NULL'\n );\n}\n\nfunction hasIdemKey(db: SqliteDatabase): boolean {\n return messageColumns(db).has('idem_key');\n}\n\nfunction messageColumns(db: SqliteDatabase): Set<string> {\n return new Set(\n queryAll<{ name: string }>(db, 'PRAGMA table_info(messages)').map(\n (c) => c.name\n )\n );\n}\n\nconst FEDERATION_DDL = `\nCREATE TABLE IF NOT EXISTS remote_deliveries (\n message_id TEXT NOT NULL, recipient TEXT NOT NULL, via TEXT NOT NULL,\n state TEXT NOT NULL, homes_json TEXT NOT NULL, wake_at TEXT, refused_by TEXT,\n updated_at TEXT NOT NULL, PRIMARY KEY (message_id, recipient)\n);\nCREATE INDEX IF NOT EXISTS remote_recipient ON remote_deliveries (recipient, state);\nCREATE TABLE IF NOT EXISTS settlements (\n question_id TEXT PRIMARY KEY, answer_id TEXT, closed_reason TEXT,\n settler TEXT NOT NULL, at TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS early_settlements (\n question_id TEXT NOT NULL, settler TEXT NOT NULL, answer_id TEXT,\n closed_reason TEXT, at TEXT NOT NULL, PRIMARY KEY (question_id, settler)\n);\n`;\nconst FEDERATION_COLUMNS = [\n 'origin',\n 'hlc',\n 'received_at',\n 'settled_as',\n] as const;\nconst SETTLED_AS: readonly SettledAs[] = [\n 'pending',\n 'accepted',\n 'superseded',\n 'candidate',\n];\n\n// Additive, like addIdemKey: an older build names its columns on insert and\n// never reads these, so it keeps opening and writing the file.\nfunction addFederationSchema(db: SqliteDatabase): void {\n const have = messageColumns(db);\n for (const column of FEDERATION_COLUMNS) {\n if (have.has(column)) continue;\n try {\n db.exec(`ALTER TABLE messages ADD COLUMN ${column} TEXT`);\n } catch (err) {\n // A daemon opening the same file at once may have added it first.\n if (!messageColumns(db).has(column)) throw err;\n }\n }\n db.exec(\n 'CREATE INDEX IF NOT EXISTS messages_thread_hlc ON messages (thread, hlc, id)'\n );\n db.exec(FEDERATION_DDL);\n}\n\n// Additive: refs by (type, id), so a doc's or task's talk is one indexed read.\n// Created with a one-time backfill from refs_json; an older build's inserts\n// skip it, which a later open does not repair.\nfunction addMessageRefs(db: SqliteDatabase): void {\n const existed =\n queryOne<{ name: string }>(\n db,\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'message_refs'\"\n ) !== undefined;\n db.exec(`CREATE TABLE IF NOT EXISTS message_refs (\n message_id TEXT NOT NULL, type TEXT NOT NULL, ref_id TEXT NOT NULL,\n PRIMARY KEY (message_id, type, ref_id)\n);\nCREATE INDEX IF NOT EXISTS message_refs_target ON message_refs (type, ref_id);`);\n if (existed) return;\n db.exec(`INSERT OR IGNORE INTO message_refs (message_id, type, ref_id)\n SELECT m.id, json_extract(j.value, '$.type'), json_extract(j.value, '$.id')\n FROM messages m, json_each(m.refs_json) j\n WHERE json_extract(j.value, '$.type') IS NOT NULL\n AND json_extract(j.value, '$.id') IS NOT NULL`);\n}\n\n/** Which messages a conversation read matches: both parties of a pair, every\n * thread an address took part in, or every thread referencing a ref. */\nexport type ConversationMatch =\n | { kind: 'pair'; a: Address; b: Address }\n | { kind: 'about'; addresses: readonly Address[] }\n | { kind: 'ref'; type: string; id: string };\n\nexport interface ConversationPage {\n /** Only ids below this one (ulid order). */\n before?: string;\n limit?: number;\n /** Only thread roots. */\n rootsOnly?: boolean;\n}\n\ninterface MessageRow {\n id: string;\n thread: string;\n reply_to: string | null;\n from_addr: string;\n session: string | null;\n kind: string;\n body: string;\n refs_json: string;\n data_json: string | null;\n urgent: number;\n blocking: number;\n choices_json: string | null;\n choice: string | null;\n wake: string;\n created_at: string;\n origin: string | null;\n hlc: string | null;\n received_at: string | null;\n settled_as: string | null;\n}\ninterface DeliveryRow {\n id: string;\n message_id: string;\n recipient: string;\n run_id: string | null;\n via: string;\n state: string;\n updated_at: string;\n}\ninterface RemoteRow {\n message_id: string;\n recipient: string;\n via: string;\n state: string;\n homes_json: string;\n wake_at: string | null;\n refused_by: string | null;\n updated_at: string;\n}\ninterface SettlementRow {\n question_id: string;\n answer_id: string | null;\n closed_reason: string | null;\n settler: string;\n at: string;\n}\ninterface AgentRow {\n addr: string;\n display_name: string;\n client: string;\n token_hash: string;\n status: string;\n muted: number;\n approved_by: string | null;\n created_at: string;\n}\n\nfunction oneOf<T extends string>(\n value: string,\n allowed: readonly T[],\n what: string\n): T {\n if (!(allowed as readonly string[]).includes(value))\n throw new Error(`messages.db: bad ${what} ${JSON.stringify(value)}`);\n return value as T;\n}\n\nexport class SqliteMessageStore implements MessageStore {\n private depth = 0;\n\n constructor(private readonly db: SqliteDatabase) {}\n\n // Re-entrant: only the outermost call issues BEGIN/COMMIT.\n transaction<T>(fn: () => T): T {\n if (this.depth > 0) return fn();\n this.db.exec('BEGIN');\n this.depth++;\n try {\n const out = fn();\n this.db.exec('COMMIT');\n return out;\n } catch (err) {\n this.db.exec('ROLLBACK');\n throw err;\n } finally {\n this.depth--;\n }\n }\n\n insertMessage(m: Message, idemKey?: string, meta?: StoredMeta): void {\n this.transaction(() => {\n this.db\n .prepare(\n `INSERT INTO messages (id, thread, reply_to, from_addr, session, kind, body, refs_json, data_json, urgent, blocking, choices_json, choice, wake, created_at, idem_key, origin, hlc, received_at, settled_as) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`\n )\n .run(\n m.id,\n m.thread,\n m.replyTo,\n m.from,\n m.session ?? null,\n m.kind,\n m.body,\n JSON.stringify(m.refs),\n m.data === undefined ? null : JSON.stringify(m.data),\n m.urgent ? 1 : 0,\n m.blocking ? 1 : 0,\n m.choices === undefined ? null : JSON.stringify(m.choices),\n m.choice ?? null,\n m.wake,\n m.createdAt,\n idemKey ?? null,\n m.origin ?? null,\n m.hlc ?? null,\n meta?.receivedAt ?? null,\n meta?.settledAs ?? null\n );\n const insert = this.db.prepare(\n 'INSERT INTO recipients (message_id, position, addr) VALUES (?,?,?)'\n );\n m.to.forEach((addr, i) => insert.run(m.id, i, addr));\n const ref = this.db.prepare(\n 'INSERT OR IGNORE INTO message_refs (message_id, type, ref_id) VALUES (?,?,?)'\n );\n for (const r of m.refs) ref.run(m.id, r.type, r.id);\n });\n }\n\n private toMessage(row: MessageRow): Message {\n const to = queryAll<{ addr: string }>(\n this.db,\n 'SELECT addr FROM recipients WHERE message_id = ? ORDER BY position',\n [row.id]\n ).map((r) => r.addr);\n const message: Message = {\n id: row.id,\n thread: row.thread,\n replyTo: row.reply_to,\n from: row.from_addr,\n to,\n kind: row.kind as Message['kind'],\n body: row.body,\n refs: JSON.parse(row.refs_json) as Ref[],\n urgent: row.urgent === 1,\n blocking: row.blocking === 1,\n wake: oneOf(row.wake, ['none', 'request'] as const, 'wake'),\n createdAt: row.created_at,\n };\n if (row.session !== null) message.session = row.session;\n if (row.data_json !== null)\n message.data = JSON.parse(row.data_json) as JsonValue;\n if (row.choices_json !== null)\n message.choices = JSON.parse(row.choices_json) as string[];\n if (row.choice !== null) message.choice = row.choice;\n if (row.origin !== null) message.origin = row.origin;\n if (row.hlc !== null) message.hlc = row.hlc;\n return message;\n }\n\n getMessage(id: string): Message | null {\n const row = queryOne<MessageRow>(\n this.db,\n 'SELECT * FROM messages WHERE id = ?',\n [id]\n );\n return row === undefined ? null : this.toMessage(row);\n }\n\n byIdemKey(from: Address, key: string): Message | null {\n const row = queryOne<MessageRow>(\n this.db,\n 'SELECT * FROM messages WHERE from_addr = ? AND idem_key = ?',\n [from, key]\n );\n return row === undefined ? null : this.toMessage(row);\n }\n\n // Chunked so a long history never exceeds SQLite's bound-parameter limit.\n idemKeysFor(messageIds: string[]): Map<string, string> {\n const out = new Map<string, string>();\n for (let i = 0; i < messageIds.length; i += 500) {\n const chunk = messageIds.slice(i, i + 500);\n const rows = queryAll<{ id: string; idem_key: string }>(\n this.db,\n `SELECT id, idem_key FROM messages WHERE idem_key IS NOT NULL AND id IN (${chunk.map(() => '?').join(',')})`,\n chunk\n );\n for (const r of rows) out.set(r.id, r.idem_key);\n }\n return out;\n }\n\n messagesFrom(\n address: Address,\n sinceIso: string,\n kinds?: MessageKind[]\n ): Message[] {\n const byKind =\n kinds === undefined\n ? ''\n : ` AND kind IN (${kinds.map(() => '?').join(',')})`;\n return queryAll<MessageRow>(\n this.db,\n `SELECT * FROM messages WHERE from_addr = ? AND created_at >= ?${byKind} ORDER BY id`,\n [address, sinceIso, ...(kinds ?? [])]\n ).map((r) => this.toMessage(r));\n }\n\n // Pre-federation rows have no clock and sort first; after that a reply\n // always follows its question, whatever the machines' wall clocks say.\n thread(threadId: string): Message[] {\n return queryAll<MessageRow>(\n this.db,\n 'SELECT * FROM messages WHERE thread = ? ORDER BY (hlc IS NOT NULL), hlc, id',\n [threadId]\n ).map((r) => this.toMessage(r));\n }\n\n answersTo(messageId: string): Message[] {\n return queryAll<MessageRow>(\n this.db,\n \"SELECT * FROM messages WHERE reply_to = ? AND kind = 'answer' ORDER BY id\",\n [messageId]\n ).map((r) => this.toMessage(r));\n }\n\n openBlocking(): Message[] {\n return queryAll<MessageRow>(\n this.db,\n \"SELECT m.* FROM messages m WHERE m.blocking = 1 AND NOT EXISTS (SELECT 1 FROM messages a WHERE a.reply_to = m.id AND a.kind = 'answer') ORDER BY m.id\"\n ).map((r) => this.toMessage(r));\n }\n\n insertDelivery(d: Delivery): void {\n this.db\n .prepare(\n 'INSERT INTO deliveries (id, message_id, recipient, run_id, via, state, updated_at) VALUES (?,?,?,?,?,?,?)'\n )\n .run(\n d.id,\n d.messageId,\n d.recipient,\n d.runId,\n d.via,\n d.state,\n d.updatedAt\n );\n }\n\n deleteDelivery(id: string): boolean {\n return (\n Number(\n this.db.prepare('DELETE FROM deliveries WHERE id = ?').run(id).changes\n ) > 0\n );\n }\n\n private toDelivery(r: DeliveryRow): Delivery {\n return {\n id: r.id,\n messageId: r.message_id,\n recipient: r.recipient,\n runId: r.run_id,\n via: oneOf<DeliveryVia>(r.via, ['direct', 'channel'], 'via'),\n state: oneOf<DeliveryState>(r.state, DELIVERY_STATES, 'state'),\n updatedAt: r.updated_at,\n };\n }\n\n getDelivery(id: string): Delivery | null {\n const row = queryOne<DeliveryRow>(\n this.db,\n 'SELECT * FROM deliveries WHERE id = ?',\n [id]\n );\n return row === undefined ? null : this.toDelivery(row);\n }\n\n deliveries(filter: DeliveryFilter): Delivery[] {\n const where: string[] = [];\n const params: SqlValue[] = [];\n if (filter.recipient !== undefined) {\n where.push('recipient = ?');\n params.push(filter.recipient);\n }\n if (filter.runId !== undefined) {\n where.push('run_id = ?');\n params.push(filter.runId);\n }\n if (filter.recipientPrefix !== undefined) {\n where.push(\"recipient LIKE ? ESCAPE '\\\\'\");\n params.push(`${filter.recipientPrefix.replace(/[\\\\%_]/g, '\\\\$&')}%`);\n }\n if (filter.messageId !== undefined) {\n where.push('message_id = ?');\n params.push(filter.messageId);\n }\n if (filter.states !== undefined) {\n const placeholders = filter.states.map(() => '?').join(',');\n where.push(`state IN (${placeholders.length > 0 ? placeholders : \"''\"})`);\n params.push(...filter.states);\n }\n const sql = `SELECT * FROM deliveries${where.length > 0 ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY id`;\n return queryAll<DeliveryRow>(this.db, sql, params).map((r) =>\n this.toDelivery(r)\n );\n }\n\n setDelivery(\n id: string,\n state: DeliveryState,\n runId: string | null,\n at: string,\n expected?: DeliveryState\n ): boolean {\n const result =\n expected === undefined\n ? this.db\n .prepare(\n 'UPDATE deliveries SET state = ?, run_id = ?, updated_at = ? WHERE id = ?'\n )\n .run(state, runId, at, id)\n : this.db\n .prepare(\n 'UPDATE deliveries SET state = ?, run_id = ?, updated_at = ? WHERE id = ? AND state = ?'\n )\n .run(state, runId, at, id, expected);\n return Number(result.changes) > 0;\n }\n\n markGateApplied(questionId: string, at: string): void {\n this.db\n .prepare(\n 'INSERT INTO gate_effects (question_id, applied_at) VALUES (?,?) ON CONFLICT (question_id) DO NOTHING'\n )\n .run(questionId, at);\n }\n\n // Voids by kind, so the one-answer index frees and the question reopens; an\n // older build that ignores the table still reads the row as a plain message.\n voidAnswer(answerId: string, questionId: string, at: string): boolean {\n return this.transaction(() => {\n const changed = this.db\n .prepare(\n \"UPDATE messages SET kind = 'message' WHERE id = ? AND reply_to = ? AND kind = 'answer'\"\n )\n .run(answerId, questionId);\n if (Number(changed.changes) === 0) return false;\n this.db\n .prepare(\n 'INSERT INTO voided_answers (answer_id, question_id, at) VALUES (?,?,?) ON CONFLICT (answer_id) DO NOTHING'\n )\n .run(answerId, questionId, at);\n return true;\n });\n }\n\n // SQL narrows to answered questions with gate data and no recorded effect;\n // the engine keeps the types it implements, and system closes are dropped.\n unappliedAnsweredGates(): { question: Message; answer: Message }[] {\n const rows = queryAll<{ question_id: string; answer_id: string }>(\n this.db,\n `SELECT q.id AS question_id, a.id AS answer_id FROM messages q\n JOIN messages a ON a.reply_to = q.id AND a.kind = 'answer'\n WHERE q.data_json LIKE '%\"type\":%'\n AND NOT EXISTS (SELECT 1 FROM gate_effects g WHERE g.question_id = q.id)\n ORDER BY q.id`\n );\n return rows.flatMap((r) => {\n const question = this.getMessage(r.question_id);\n const answer = this.getMessage(r.answer_id);\n if (question === null || answer === null || !hasGateData(question))\n return [];\n return isSystemMarker(answer, 'x-closed') ? [] : [{ question, answer }];\n });\n }\n\n // Counts by arrival, so a remote sender cannot dodge a quota by backdating createdAt.\n countFrom(\n from: Address,\n sinceIso: string,\n urgentOnly: boolean,\n origin?: string,\n untilIso?: string\n ): number {\n const row = queryOne<{ n: number }>(\n this.db,\n `SELECT COUNT(*) AS n FROM messages WHERE from_addr = ? AND COALESCE(received_at, created_at) >= ? AND COALESCE(received_at, created_at) <= ?${urgentOnly ? ' AND urgent = 1' : ''}${origin === undefined ? '' : ' AND origin = ?'}`,\n origin === undefined\n ? [from, sinceIso, untilIso ?? '9999']\n : [from, sinceIso, untilIso ?? '9999', origin]\n );\n return row === undefined ? 0 : Number(row.n);\n }\n\n countDeliveredTo(\n recipient: Address,\n sinceIso: string,\n untilIso?: string\n ): number {\n const row = queryOne<{ n: number }>(\n this.db,\n 'SELECT COUNT(DISTINCT m.id) AS n FROM deliveries d JOIN messages m ON m.id = d.message_id WHERE d.recipient = ? AND m.created_at >= ? AND m.created_at <= ?',\n [recipient, sinceIso, untilIso ?? '9999']\n );\n return row === undefined ? 0 : Number(row.n);\n }\n\n countAgentThreadsFrom(from: Address, sinceIso: string): number {\n const row = queryOne<{ n: number }>(\n this.db,\n \"SELECT COUNT(*) AS n FROM messages m WHERE m.from_addr = ? AND m.thread = m.id AND COALESCE(m.received_at, m.created_at) >= ? AND EXISTS (SELECT 1 FROM recipients r WHERE r.message_id = m.id AND (r.addr LIKE 'agent:%' OR r.addr LIKE 'run:%' OR r.addr LIKE 'task:%')) AND NOT EXISTS (SELECT 1 FROM recipients r WHERE r.message_id = m.id AND r.addr LIKE 'human:%') AND NOT EXISTS (SELECT 1 FROM deliveries d WHERE d.message_id = m.id AND d.recipient LIKE 'human:%')\",\n [from, sinceIso]\n );\n return row === undefined ? 0 : Number(row.n);\n }\n\n // A remote agent:dispatch is an ordinary agent here, so only the local\n // system address is excluded.\n countAgentAuthored(\n threadId: string,\n sinceIso: string,\n exclude: Address\n ): number {\n const row = queryOne<{ n: number }>(\n this.db,\n \"SELECT COUNT(*) AS n FROM messages WHERE thread = ? AND COALESCE(received_at, created_at) >= ? AND (from_addr != ? OR origin IS NOT NULL) AND (from_addr LIKE 'run:%' OR from_addr LIKE 'agent:%' OR from_addr LIKE 'a2a:%')\",\n [threadId, sinceIso, exclude]\n );\n return row === undefined ? 0 : Number(row.n);\n }\n\n settledAs(messageId: string): SettledAs | null {\n const row = queryOne<{ settled_as: string | null }>(\n this.db,\n 'SELECT settled_as FROM messages WHERE id = ?',\n [messageId]\n );\n return row === undefined || row.settled_as === null\n ? null\n : oneOf(row.settled_as, SETTLED_AS, 'settled_as');\n }\n\n setSettled(\n messageId: string,\n kind: 'answer' | 'message',\n settledAs: SettledAs | null\n ): void {\n this.db\n .prepare('UPDATE messages SET kind = ?, settled_as = ? WHERE id = ?')\n .run(kind, settledAs, messageId);\n }\n\n answerCandidates(\n questionId: string\n ): { message: Message; settledAs: SettledAs | null }[] {\n return queryAll<MessageRow>(\n this.db,\n \"SELECT * FROM messages WHERE reply_to = ? AND (kind = 'answer' OR settled_as IS NOT NULL) ORDER BY rowid\",\n [questionId]\n ).map((r) => ({\n message: this.toMessage(r),\n settledAs:\n r.settled_as === null\n ? null\n : oneOf(r.settled_as, SETTLED_AS, 'settled_as'),\n }));\n }\n\n insertRemote(row: RemoteDelivery): boolean {\n const result = this.db\n .prepare(\n 'INSERT INTO remote_deliveries (message_id, recipient, via, state, homes_json, wake_at, refused_by, updated_at) VALUES (?,?,?,?,?,?,?,?) ON CONFLICT (message_id, recipient) DO NOTHING'\n )\n .run(\n row.messageId,\n row.recipient,\n row.via,\n row.state,\n JSON.stringify(row.homes),\n row.wakeAt,\n JSON.stringify(row.refusedBy),\n row.updatedAt\n );\n return Number(result.changes) > 0;\n }\n\n private toRemote(r: RemoteRow): RemoteDelivery {\n return {\n messageId: r.message_id,\n recipient: r.recipient,\n via: oneOf<DeliveryVia>(r.via, ['direct', 'channel'], 'via'),\n state: oneOf(r.state, REMOTE_STATES, 'remote state'),\n homes: JSON.parse(r.homes_json) as string[],\n wakeAt: r.wake_at,\n refusedBy:\n r.refused_by === null ? [] : (JSON.parse(r.refused_by) as string[]),\n updatedAt: r.updated_at,\n };\n }\n\n remoteDeliveries(filter: {\n messageId?: string;\n recipient?: Address;\n states?: RemoteState[];\n }): RemoteDelivery[] {\n const where: string[] = [];\n const params: SqlValue[] = [];\n if (filter.messageId !== undefined) {\n where.push('message_id = ?');\n params.push(filter.messageId);\n }\n if (filter.recipient !== undefined) {\n where.push('recipient = ?');\n params.push(filter.recipient);\n }\n if (filter.states !== undefined) {\n const placeholders = filter.states.map(() => '?').join(',');\n where.push(`state IN (${placeholders.length > 0 ? placeholders : \"''\"})`);\n params.push(...filter.states);\n }\n const sql = `SELECT * FROM remote_deliveries${where.length > 0 ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY message_id, recipient`;\n return queryAll<RemoteRow>(this.db, sql, params).map((r) =>\n this.toRemote(r)\n );\n }\n\n setRemote(\n messageId: string,\n recipient: Address,\n patch: { state?: RemoteState; refusedBy?: string[]; homes?: string[] },\n at: string,\n expected?: RemoteState\n ): boolean {\n const sets = ['updated_at = ?'];\n const params: SqlValue[] = [at];\n if (patch.state !== undefined) {\n sets.push('state = ?');\n params.push(patch.state);\n }\n if (patch.refusedBy !== undefined) {\n sets.push('refused_by = ?');\n params.push(JSON.stringify(patch.refusedBy));\n }\n if (patch.homes !== undefined) {\n sets.push('homes_json = ?');\n params.push(JSON.stringify(patch.homes));\n }\n params.push(messageId, recipient);\n if (expected !== undefined) params.push(expected);\n const result = this.db\n .prepare(\n `UPDATE remote_deliveries SET ${sets.join(', ')} WHERE message_id = ? AND recipient = ?${expected === undefined ? '' : ' AND state = ?'}`\n )\n .run(...params);\n return Number(result.changes) > 0;\n }\n\n deleteRemote(messageId: string, recipient: Address): boolean {\n return (\n Number(\n this.db\n .prepare(\n 'DELETE FROM remote_deliveries WHERE message_id = ? AND recipient = ?'\n )\n .run(messageId, recipient).changes\n ) > 0\n );\n }\n\n settlement(questionId: string): Settlement | null {\n const row = queryOne<SettlementRow>(\n this.db,\n 'SELECT * FROM settlements WHERE question_id = ?',\n [questionId]\n );\n return row === undefined ? null : toSettlement(row);\n }\n\n putSettlement(s: Settlement): void {\n this.db\n .prepare(\n `INSERT INTO settlements (question_id, answer_id, closed_reason, settler, at) VALUES (?,?,?,?,?)\n ON CONFLICT (question_id) DO UPDATE SET answer_id = excluded.answer_id, closed_reason = excluded.closed_reason,\n settler = excluded.settler, at = excluded.at`\n )\n .run(s.questionId, s.answerId, s.closedReason, s.settler, s.at);\n }\n\n putEarlySettlement(s: Settlement): void {\n this.db\n .prepare(\n `INSERT INTO early_settlements (question_id, settler, answer_id, closed_reason, at) VALUES (?,?,?,?,?)\n ON CONFLICT (question_id, settler) DO UPDATE SET answer_id = excluded.answer_id,\n closed_reason = excluded.closed_reason, at = excluded.at`\n )\n .run(s.questionId, s.settler, s.answerId, s.closedReason, s.at);\n }\n\n earlySettlements(questionId: string): Settlement[] {\n return queryAll<SettlementRow>(\n this.db,\n 'SELECT * FROM early_settlements WHERE question_id = ? ORDER BY at, settler',\n [questionId]\n ).map(toSettlement);\n }\n\n clearEarlySettlements(questionId: string): void {\n this.db\n .prepare('DELETE FROM early_settlements WHERE question_id = ?')\n .run(questionId);\n }\n\n // The outbound scan's watermark is a rowid: messages rows are never deleted,\n // so each new row's rowid is higher than every earlier one.\n messagesAfter(\n rowid: number,\n limit: number\n ): { rowid: number; message: Message }[] {\n return queryAll<MessageRow & { rid: number }>(\n this.db,\n 'SELECT rowid AS rid, * FROM messages WHERE rowid > ? AND origin IS NULL ORDER BY rowid LIMIT ?',\n [rowid, limit]\n ).map((r) => ({ rowid: Number(r.rid), message: this.toMessage(r) }));\n }\n\n maxRowid(): number {\n const row = queryOne<{ n: number | null }>(\n this.db,\n 'SELECT MAX(rowid) AS n FROM messages'\n );\n return row === undefined || row.n === null ? 0 : Number(row.n);\n }\n\n ensureChannel(name: string, at: string, auto: boolean): void {\n this.db\n .prepare(\n 'INSERT INTO channels (name, created_at, auto) VALUES (?,?,?) ON CONFLICT (name) DO NOTHING'\n )\n .run(name, at, auto ? 1 : 0);\n }\n\n channels(): ChannelRecord[] {\n return queryAll<{ name: string; created_at: string; auto: number }>(\n this.db,\n 'SELECT * FROM channels ORDER BY name'\n ).map((r) => ({\n name: r.name,\n createdAt: r.created_at,\n auto: r.auto === 1,\n }));\n }\n\n addMember(channel: string, member: Address, at: string): boolean {\n return (\n Number(\n this.db\n .prepare(\n 'INSERT INTO members (channel, addr, joined_at) VALUES (?,?,?) ON CONFLICT (channel, addr) DO NOTHING'\n )\n .run(channel, member, at).changes\n ) > 0\n );\n }\n\n removeMember(channel: string, member: Address): boolean {\n return (\n Number(\n this.db\n .prepare('DELETE FROM members WHERE channel = ? AND addr = ?')\n .run(channel, member).changes\n ) > 0\n );\n }\n\n members(channel: string): Address[] {\n return queryAll<{ addr: string }>(\n this.db,\n 'SELECT addr FROM members WHERE channel = ? ORDER BY addr',\n [channel]\n ).map((r) => r.addr);\n }\n\n channelsOf(member: Address): string[] {\n return queryAll<{ channel: string }>(\n this.db,\n 'SELECT channel FROM members WHERE addr = ? ORDER BY channel',\n [member]\n ).map((r) => r.channel);\n }\n\n putAgent(a: AgentRecord): void {\n this.db\n .prepare(\n `INSERT INTO agents (addr, display_name, client, token_hash, status, muted, approved_by, created_at) VALUES (?,?,?,?,?,?,?,?)\n ON CONFLICT (addr) DO UPDATE SET display_name = excluded.display_name, client = excluded.client, token_hash = excluded.token_hash,\n status = excluded.status, muted = excluded.muted, approved_by = excluded.approved_by`\n )\n .run(\n a.address,\n a.displayName,\n a.client,\n a.tokenHash,\n a.status,\n a.muted ? 1 : 0,\n a.approvedBy,\n a.createdAt\n );\n }\n\n private toAgent(r: AgentRow): AgentRecord {\n return {\n address: r.addr,\n displayName: r.display_name,\n client: r.client,\n tokenHash: r.token_hash,\n status: oneOf<AgentStatus>(\n r.status,\n ['pending', 'approved', 'revoked'],\n 'agent status'\n ),\n muted: r.muted === 1,\n approvedBy: r.approved_by,\n createdAt: r.created_at,\n };\n }\n\n getAgent(address: Address): AgentRecord | null {\n const row = queryOne<AgentRow>(\n this.db,\n 'SELECT * FROM agents WHERE addr = ?',\n [address]\n );\n return row === undefined ? null : this.toAgent(row);\n }\n\n agentByTokenHash(hash: string): AgentRecord | null {\n const row = queryOne<AgentRow>(\n this.db,\n 'SELECT * FROM agents WHERE token_hash = ?',\n [hash]\n );\n return row === undefined ? null : this.toAgent(row);\n }\n\n agents(): AgentRecord[] {\n return queryAll<AgentRow>(\n this.db,\n 'SELECT * FROM agents ORDER BY addr'\n ).map((r) => this.toAgent(r));\n }\n\n // Most recently active threads by local arrival (rowid), newest first.\n // `about` keeps threads with a message from, to or delivered to one of those addresses.\n recentThreads(limit: number, about?: readonly Address[]): ThreadSummary[] {\n if (about !== undefined && about.length === 0) return [];\n const params: SqlValue[] = [];\n let where = '';\n if (about !== undefined) {\n const clause = threadsAbout(about);\n where = `WHERE thread IN (${clause.sql})`;\n params.push(...clause.params);\n }\n params.push(limit);\n const rows = queryAll<{\n thread: string;\n last_rowid: number;\n count: number;\n }>(\n this.db,\n `SELECT thread, MAX(rowid) AS last_rowid, COUNT(*) AS count\n FROM messages ${where} GROUP BY thread ORDER BY last_rowid DESC LIMIT ?`,\n params\n );\n return rows.flatMap((r) => {\n // A thread's id is its root's id; a partial thread falls back to its\n // earliest stored row, never to MIN(id) across skewed machines.\n const root = this.getMessage(r.thread) ?? this.firstStored(r.thread);\n const last = this.byRowid(Number(r.last_rowid));\n return root === null || last === null\n ? []\n : [{ thread: r.thread, root, last, count: Number(r.count) }];\n });\n }\n\n /** Messages a conversation read matches, newest (highest id) first. */\n conversation(match: ConversationMatch, page: ConversationPage): Message[] {\n const where: string[] = [];\n const params: SqlValue[] = [];\n if (match.kind === 'pair') {\n const party =\n '(m.from_addr = ? OR EXISTS (SELECT 1 FROM recipients r WHERE r.message_id = m.id AND r.addr = ?))';\n where.push(`${party} AND ${party}`);\n params.push(match.a, match.a, match.b, match.b);\n } else if (match.kind === 'about') {\n if (match.addresses.length === 0) return [];\n const clause = threadsAbout(match.addresses);\n where.push(`m.thread IN (${clause.sql})`);\n params.push(...clause.params);\n } else {\n where.push(`m.thread IN (SELECT t.thread FROM message_refs x\n JOIN messages t ON t.id = x.message_id WHERE x.type = ? AND x.ref_id = ?)`);\n params.push(match.type, match.id);\n }\n if (page.before !== undefined) {\n where.push('m.id < ?');\n params.push(page.before);\n }\n if (page.rootsOnly === true) where.push('m.id = m.thread');\n params.push(page.limit ?? 50);\n return queryAll<MessageRow>(\n this.db,\n `SELECT m.* FROM messages m WHERE ${where.join(' AND ')} ORDER BY m.id DESC LIMIT ?`,\n params\n ).map((r) => this.toMessage(r));\n }\n\n private firstStored(threadId: string): Message | null {\n const row = queryOne<MessageRow>(\n this.db,\n 'SELECT * FROM messages WHERE thread = ? ORDER BY rowid LIMIT 1',\n [threadId]\n );\n return row === undefined ? null : this.toMessage(row);\n }\n\n private byRowid(rowid: number): Message | null {\n const row = queryOne<MessageRow>(\n this.db,\n 'SELECT * FROM messages WHERE rowid = ?',\n [rowid]\n );\n return row === undefined ? null : this.toMessage(row);\n }\n}\n\n// Threads `about` took part in as sender, recipient or delivery recipient;\n// held mail rebound to a run keeps its task recipient, so match it by run id.\nfunction threadsAbout(about: readonly Address[]): {\n sql: string;\n params: SqlValue[];\n} {\n const marks = about.map(() => '?').join(', ');\n const runIds = about\n .filter((a) => a.startsWith('run:'))\n .map((a) => a.slice('run:'.length));\n const byRun =\n runIds.length === 0\n ? ''\n : ` OR d.run_id IN (${runIds.map(() => '?').join(', ')})`;\n return {\n sql: `SELECT thread FROM messages WHERE from_addr IN (${marks})\n UNION SELECT m.thread FROM messages m JOIN recipients r ON r.message_id = m.id WHERE r.addr IN (${marks})\n UNION SELECT m.thread FROM messages m JOIN deliveries d ON d.message_id = m.id\n WHERE d.recipient IN (${marks})${byRun}`,\n params: [...about, ...about, ...about, ...runIds],\n };\n}\n\nfunction toSettlement(r: SettlementRow): Settlement {\n return {\n questionId: r.question_id,\n answerId: r.answer_id,\n closedReason: r.closed_reason,\n settler: r.settler,\n at: r.at,\n };\n}\n","// The DMP version this package implements (§14.5); set by each release PR.\n// Its own module, so the conformance adapter names it without the index.\nexport const PROTOCOL_VERSION = '1.0.0-draft.2';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@dispatch-foo/protocol",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Reference engine for the Dispatch Messaging Protocol: addresses, envelopes, gates, delivery and a SQLite store.",
5
+ "homepage": "https://dispatch.foo/protocol/",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/wsoule/dispatch.git",
10
+ "directory": "packages/protocol"
11
+ },
12
+ "bin": {
13
+ "dmp-reference-adapter": "./dist/conformance-adapter.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "type": "module",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./browser": {
27
+ "types": "./dist/browser.d.ts",
28
+ "import": "./dist/browser.js"
29
+ },
30
+ "./conformance": {
31
+ "types": "./dist/conformance.d.ts",
32
+ "import": "./dist/conformance.js"
33
+ },
34
+ "./federation": {
35
+ "types": "./dist/federation/index.d.ts",
36
+ "import": "./dist/federation/index.js"
37
+ }
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "dependencies": {
43
+ "@dispatch-foo/core": "0.24.0"
44
+ },
45
+ "devDependencies": {
46
+ "@dispatch-foo/protocol-spec": "1.0.0-draft.2",
47
+ "@types/bun": "1.3.12",
48
+ "tsdown": "0.15.11",
49
+ "typescript": "5.9.2"
50
+ },
51
+ "engines": {
52
+ "node": ">=22.13"
53
+ }
54
+ }