/** * Deterministic personal-field classifier for the browser auto-answer loop. * * The auto-answer agent must never answer questions that ask about the person * behind the browser (name, email, phone, address, IDs, salary, credentials). * Prompt rules alone are not enough: the completeness pressure in the loop * ("answer every question or the task fails") overrides them, and small vision * models happily invent plausible-looking values. * * This module is the single source of truth for "is this field personal". * It is pure and data-driven so it can be unit-tested and extended by editing * the tables below - no logic changes required. * * Tiers: * credential - always blocked, cannot be enabled by any flag (passwords, * one-time codes, card data, bank details) * hard - blocked unless the run explicitly allows personal answers * soft - never blocked by code; the model is told to skip it and it is * reported, but the human decides */ export type PersonalTier = 'credential' | 'hard' | 'soft'; export type PersonalCategory = 'credential' | 'financial' | 'identity' | 'contact' | 'address' | 'government_id' | 'date_of_birth' | 'salary' | 'eligibility' | 'profile_link' | 'demographics' | 'essay'; /** Raw signals of a single (typable) element, gathered in the page. */ export interface FieldSignals { tag?: string; type?: string; name?: string; id?: string; autocomplete?: string; placeholder?: string; ariaLabel?: string; label?: string; questionText?: string; text?: string; } export interface PersonalClassification { tier: PersonalTier | null; category: PersonalCategory | null; /** Short human label used in logs and in the prompt element listing. */ label: string; /** Which signal decided it (for logs/debugging). */ reason: string; } /** autocomplete tokens that are always blocked (never overridable). */ export declare const CREDENTIAL_AUTOCOMPLETE: Set; interface KeywordRule { category: PersonalCategory; tier: PersonalTier; label: string; pattern: RegExp; } /** * Keyword rules, checked in order (first match wins). Patterns run against the * normalized `label | placeholder | aria-label | name | id | question text`. */ export declare const PERSONAL_KEYWORD_RULES: KeywordRule[]; /** * Stable identity for a field, used to skip the same field across LLM passes * (element indices change every pass, the field does not). */ export declare function fieldKeyOf(signals: FieldSignals): string; export declare function classifyField(signals: FieldSignals): PersonalClassification; /** True when the field must never be typed into, regardless of any flag. */ export declare function isAlwaysBlocked(c: PersonalClassification): boolean; /** * True when the field must not be typed into for this run. * `allowPersonal` is the explicit user override; it can never unlock * credentials. */ export declare function isBlocked(c: PersonalClassification, opts: { allowPersonal: boolean; }): boolean; /** True when an empty field must NOT count as "unanswered" (so `done` sticks). */ export declare function excludesFromCompleteness(c: PersonalClassification): boolean; export declare function isPersonal(c: PersonalClassification): boolean; /** Short marker shown next to the element in the LLM prompt. */ export declare function promptMarker(c: PersonalClassification): string; export {};