/** * Interactive Probe — Phase 2 Dynamic Observation * * The static crawl captures DOM structure at rest. This module runs AFTER the static crawl * to observe dynamic behaviour by actually interacting with the UI: * * 1. Empty submit → captures required-field validation error messages * 2. Invalid format → captures format validation errors (bad email, short password) * 3. Button clicks → captures modal/dialog contents * 4. Select changes → captures conditional reveals (show/hide logic) * 5. Success paths → captures toast/banner messages (where input is safe) * * Results are stored as KnowledgeChunks (sourceType='probe') and update the * ERROR_CATALOGUE + INTERACTION_PATTERNS skill files with real observed data * instead of LLM inference. * * Call signature: probeScreen(page, screenId, elements, opts) * Called from crawlProject() after static element extraction when opts.interactive=true. */ import type { Page } from 'playwright'; export interface ProbeElementFact { meaning: string; role: string; expectedData?: string; } export interface ValidationError { field: string; trigger: 'empty_submit' | 'invalid_format' | 'boundary'; errorText: string; } export interface SuccessMessage { type: 'toast' | 'inline_success' | 'redirect'; content: string; } export interface ModalObservation { triggerElement: string; title: string; content: string; fields: string[]; } export interface ConditionalReveal { triggerElement: string; triggerValue: string; revealedText: string; } export interface TooltipCapture { triggerLabel: string; tooltipText: string; } export interface TabPanelCapture { tabLabel: string; panelContent: string; panelHeading?: string; } export interface CarouselSlide { slideIndex: number; heading?: string; content: string; } export interface WizardStep { stepIndex: number; stepLabel?: string; content: string; fields: string[]; } export interface FocusTrapResult { modalTrigger: string; focusTrapped: boolean; sampledFocused: string[]; } export interface ContextMenuCapture { trigger: string; items: string[]; } export interface ProbeResult { screenId: string; url: string; validationErrors: ValidationError[]; successMessages: SuccessMessage[]; modals: ModalObservation[]; conditionals: ConditionalReveal[]; loadingPatterns: string[]; tooltips?: TooltipCapture[]; tabPanels?: TabPanelCapture[]; carouselSlides?: CarouselSlide[]; wizardSteps?: WizardStep[]; focusTraps?: FocusTrapResult[]; skipNavIssues?: string[]; contextMenus?: ContextMenuCapture[]; } /** * Run interactive probing on a single screen page. * The page must already be navigated to the screen URL. * `elements` is the output of the static extractElements pass. */ export declare function probeScreen(page: Page, screenId: string, url: string, elements: ProbeElementFact[]): Promise; /** Phase 5: Convert ProbeResult to typed ProbeObservationFact rows for direct DB storage. */ export declare function probeResultToObservations(result: ProbeResult): Array<{ elementMeaning: string; observationType: string; observedText: string; triggeredBy: string; }>; /** * Convert a ProbeResult into markdown to store as KnowledgeChunks * and update ERROR_CATALOGUE + INTERACTION_PATTERNS skill files. */ export declare function probeResultToMarkdown(result: ProbeResult): { errorCatalogueChunk: string; interactionPatternsChunk: string; }; /** * Run interactive probing for all screens discovered in a crawl session. * Called from crawlProject() when opts.interactive = true. */ export declare function probeAllScreens(page: any, tenantId: string, projectId: string, discovered: Array<{ url: string; screenId?: string; elements?: any[]; }>, onProgress?: (pct: number, step: string) => Promise): Promise; export interface FocusableElement { tag: string; role: string | null; ariaLabel: string | null; text: string | null; hasFocusIndicator: boolean; tabIndex: number | null; } export interface KeyboardNavResult { focusableCount: number; elementsWithNoFocusIndicator: number; sequence: FocusableElement[]; issues: string[]; } /** * Probe keyboard navigation accessibility by pressing Tab up to 50 times and * recording each focused element's properties and focus-indicator visibility. * Stops early if focus wraps back to the start or hits the same element twice. */ export declare function probeKeyboardNav(page: Page): Promise;