/** * Identity decoding: pure recognition of a harness's identity announcement * inside its output stream. D-022: claude re-emits `system/init` with the * same session_id at every turn start, so announcements are deduped against * the last seen id - an identity is only "news" on first sight or change. * Under caller-assigned authority an announcement that differs from the * REQUESTED id is a rotation anomaly (v1 HSI005): binding it would silently * attach the conversation to a context that never saw it, so the outcome is * surfaced for the runner to refuse, never papered over. * * A harness may also self-attest the model it runs (pi streams assistant * `message` records carrying `provider`/`model` on every turn - observed on * pi --mode json against pi 0.85.1, where the transcript-only `model_change` * record never appears on stdout). decodeModelObservation reads that * attestation: it records WHAT the harness says it runs (an observed model * id plus provider) and NOTHING ELSE. The observed value must never widen * authority - it feeds display/capability fields only, never validation * (validateModel ignores it), refusal paths, or capability claims anywhere. */ import type { HarnessDescriptor } from "../knowledge/descriptor.js"; export type IdentityOutcome = /** Not an identity announcement at all. */ "none" /** First sight (or a changed id under harness-minted authority). */ | "announced" /** Same id as last seen - turn-start metadata, not news. */ | "duplicate" /** Caller-assigned authority, but the harness announced a DIFFERENT id * than the one requested - refuse to bind, do not paper over. */ | "rotated" /** Announcement present but the id fails the shape rule - not believed. */ | "malformed"; export interface ModelObservation { /** The exact model id the harness announced (message.message.model). */ readonly model: string; /** The provider the harness announced alongside it, if any. */ readonly provider?: string; } export interface DecodedIdentity { /** The id this raw event announces, whether or not it is news. */ readonly sessionId: string | null; /** The id to surface as an identity HarnessEvent, or null when not news. */ readonly identity: string | null; readonly outcome: IdentityOutcome; /** The harness's own model self-attestation on this record, if any. */ readonly observedModel: ModelObservation | null; } /** * Read a harness's model self-attestation off one parsed record. pi * carries `message: { provider, model }` on assistant records (verified on * pi 0.85.1 stdout: `message_start`/`message_end`/`turn_end`/`agent_end` * all carry it from the first assistant message on). Anything else - no * message object, an error stopReason, non-string fields - is no * observation, never a refusal. A failed turn says nothing about what * runs the next one. */ export declare const decodeModelObservation: (raw: unknown) => ModelObservation | null; export declare const decodeIdentity: (h: HarnessDescriptor, raw: unknown, lastSeenId: string | null, requestedId?: string | null) => DecodedIdentity; //# sourceMappingURL=identity.d.ts.map