Zum Inhalt springen

UIAP Discovery Mapper

FeldWert
StatusDraft
Version0.1
Datum2026-03-27
Abhängigkeiten[UIAP-CORE], [UIAP-CAP], [UIAP-WEB], [UIAP-ACTION], [UIAP-POLICY]
EditorenPatrick

Die Schlüsselwörter MUSS, DARF NICHT, SOLLTE, KANN in diesem Dokument sind normativ gemäss RFC 2119 und BCP 14 zu interpretieren, wenn und nur wenn sie in GROSSBUCHSTABEN erscheinen.

UIAP Discovery Mapper Spec v0.1 definiert, wie eine Anwendung oder ein Discovery-Werkzeug eine Webanwendung kontrolliert erkundet, strukturiert beschreibt und in agentisch nutzbare Artefakte übersetzt.

Ziel des Mappers ist nicht, zur Laufzeit des Nutzers „mal alles zu verstehen“, sondern in einer kontrollierten Umgebung ein belastbares Inventar zu erzeugen für:

  • Route-Kataloge
  • Scope- und Seitenmodelle
  • Element- und Feldlexika
  • Action-Kandidaten
  • Transition Graphs
  • Workflow-Kandidaten
  • Review- und Lückenlisten
  • Coverage-Reports

Diese Spezifikation baut auf:

  • UIAP Core v0.1
  • UIAP Capability Model v0.1
  • UIAP Web Profile v0.1
  • UIAP Action Runtime Spec v0.1
  • UIAP Policy Extension v0.1
  • optional UIAP Workflow Extension v0.1

auf.

Diese Spezifikation definiert nicht:

  • das LLM-Planungsverhalten,
  • die produktive Laufzeitsteuerung in der User-Session,
  • die endgültige Workflow-Freigabe,
  • Security-Policy der Zielanwendung jenseits des Discovery-Kontexts.

  1. Discovery gehört primär in Staging, Demo-Umgebungen oder kontrollierte Testmandanten, nicht in die Live-Session echter Nutzer.
  2. Discovery ist bounded exploration, kein unendlicher Spider.
  3. Discovery ist evidence-driven: jede extrahierte Aussage soll eine Herkunft und einen Confidence-Wert haben.
  4. Discovery ist safe by default: keine destruktiven oder extern wirksamen Aktionen ohne ausdrückliche Freigabe.
  5. Discovery ist semantik-first: Annotationen, registrierte Actions, Rollen, Namen und Zustände gehen vor Heuristiken.
  6. Discovery erzeugt Kandidaten und Befunde, nicht automatisch finale Wahrheit.
  7. Discovery MUSS Grenzen wie Cross-Origin und Closed Shadow DOM korrekt als Grenzen behandeln, nicht als „wird schon gehen“. Menschen hoffen das gern. Browser weniger.

Der Mapper kann als Companion Spec betrieben werden oder optional als UIAP-Erweiterung exponiert werden.

type ExtensionId = "uiap.discovery";
type ExtensionVersion = "0.1";

Wenn die Discovery-Funktion als UIAP-Erweiterung angeboten wird, MUSS sie im Handshake deklarierbar sein:

{
"id": "uiap.discovery",
"versions": ["0.1"],
"required": false
}

Eine einzelne kontrollierte Erkundungsausführung gegen eine bestimmte Zielumgebung.

Die Zielumgebung mit URL, Auth-Kontext, Rollen, Locale, Feature-Flags und Budgetgrenzen.

Ein Startpunkt für Discovery, z. B. Route, URL, Menüpunkt, registrierte Action, Doku-Hinweis oder bekannter Workflow.

Ein beobachteter UI-Zustand, bestehend aus PageGraph, Zusatzbelegen und Fingerprint.

Ein dokumentierter Übergang von einem Discovery State in einen anderen, ausgelöst durch eine Aktion.

Ein vom Mapper vorgeschlagenes Artefakt, z. B. Route, Action oder Workflow, das noch nicht zwingend freigegeben ist.

Ein maschinen- oder menschenprüfbarer Befund über Lücken, Ambiguitäten oder Unsicherheiten.


Ein konformer Mapper SOLLTE mindestens diese Ziele verfolgen:

  • die navigierbaren Hauptbereiche der Anwendung zu erkennen,
  • sichtbare und relevante Scopes zu katalogisieren,
  • semantisch wichtige UI-Elemente zu extrahieren,
  • sichere und plausible Action-Kandidaten abzuleiten,
  • beobachtbare Success-Signale zu erfassen,
  • Übergänge zwischen Zuständen zu protokollieren,
  • Workflow-Kandidaten aus Transition Chains abzuleiten,
  • Unsicherheit explizit zu kennzeichnen.

interface DiscoveryPackage {
modelVersion: "0.1";
spec: "uiap.discovery";
revision?: string;
run: DiscoveryRunSummary;
environment: DiscoveryEnvironment;
routeCatalog: RouteCatalog;
scopeCatalog: ScopeCatalog;
elementCatalog: ElementCatalog;
actionCatalog: ActionCatalog;
transitionGraph: TransitionGraph;
workflowCandidates?: WorkflowCandidateCatalog;
reviewQueue: ReviewQueue;
coverage: CoverageReport;
evidenceIndex?: EvidenceIndex;
metadata?: Record<string, unknown>;
}

interface RouteCatalog {
routes: DiscoveredRoute[];
}
interface DiscoveredRoute {
routeId: string;
urls?: string[];
titles?: string[];
scopes?: ScopeId[];
discoveredBy: EvidenceRef[];
confidence: Confidence;
entryActions?: string[];
exitSignals?: SuccessSignal[];
metadata?: Record<string, unknown>;
}

interface ScopeCatalog {
scopes: DiscoveredScope[];
}
interface DiscoveredScope {
scopeId: ScopeId;
kind: ScopeKind;
routeIds?: string[];
parentScopeId?: ScopeId;
names?: string[];
stableIds?: StableId[];
discoveredBy: EvidenceRef[];
confidence: Confidence;
metadata?: Record<string, unknown>;
}

interface ElementCatalog {
elements: DiscoveredElement[];
}
interface DiscoveredElement {
stableId?: StableId;
semanticKey: string;
routes?: string[];
scopes?: ScopeId[];
role: UIRole;
names?: string[];
meanings?: string[];
stateKeys?: UIStateKey[];
affordances?: UIAffordance[];
supportedActions?: ActionId[];
risk?: RiskDescriptor;
dataClasses?: DataClass[];
discoveredBy: EvidenceRef[];
confidence: Confidence;
reviewState?: "verified" | "candidate" | "needs_review";
metadata?: Record<string, unknown>;
}

semanticKey ist die kanonische Mapper-Identität, wenn noch keine stabile stableId existiert.


interface ActionCatalog {
actions: DiscoveredAction[];
}
interface DiscoveredAction {
id: ActionId;
kind: "primitive" | "domain" | "candidate";
targetPatterns?: ActionTargetPattern[];
routes?: string[];
scopes?: ScopeId[];
args?: ActionArgDescriptor[];
risk?: RiskDescriptor;
sideEffectClass?: SideEffectClass;
successSignals?: SuccessSignal[];
prerequisites?: WorkflowCondition[];
discoveredBy: EvidenceRef[];
confidence: Confidence;
reviewState?: "verified" | "candidate" | "unsafe" | "needs_review";
metadata?: Record<string, unknown>;
}
interface ActionTargetPattern {
role?: UIRole;
stableId?: StableId;
meaning?: string;
scopeId?: ScopeId;
}

interface TransitionGraph {
states: DiscoveryStateNode[];
edges: DiscoveryTransition[];
}
interface DiscoveryStateNode {
stateId: string;
fingerprint: string;
routeId?: string;
scopeIds?: ScopeId[];
modalStack?: string[];
pageGraphRef?: string;
screenshotRef?: string;
discoveredBy: EvidenceRef[];
confidence: Confidence;
metadata?: Record<string, unknown>;
}
interface DiscoveryTransition {
transitionId: string;
fromStateId: string;
toStateId: string;
viaActionId: ActionId;
target?: TargetRef;
args?: Record<string, unknown>;
sideEffectClass?: SideEffectClass;
observedSignals?: SuccessSignal[];
confidence: Confidence;
discoveredBy: EvidenceRef[];
metadata?: Record<string, unknown>;
}

interface WorkflowCandidateCatalog {
workflows: DiscoveredWorkflowCandidate[];
}
interface DiscoveredWorkflowCandidate {
id: string;
title?: string;
category?: WorkflowCategory;
routeIds?: string[];
entryConditions?: WorkflowCondition[];
requiredInputs?: WorkflowParameter[];
stepSkeleton: WorkflowStepSkeleton[];
successSignals?: SuccessSignal[];
discoveredBy: EvidenceRef[];
confidence: Confidence;
reviewState?: "candidate" | "verified" | "needs_review";
metadata?: Record<string, unknown>;
}
interface WorkflowStepSkeleton {
type: "instruction" | "collect" | "action" | "ensure" | "branch" | "handoff" | "complete";
actionId?: ActionId;
target?: TargetRef;
parameterNames?: string[];
signals?: SuccessSignal[];
}

interface ReviewQueue {
items: ReviewItem[];
}
interface ReviewItem {
id: string;
severity: "low" | "medium" | "high";
kind:
| "missing_stable_id"
| "duplicate_name"
| "ambiguous_target"
| "opaque_frame"
| "closed_shadow"
| "missing_success_signal"
| "unsafe_action_candidate"
| "inferred_only"
| "coverage_gap"
| "workflow_uncertain"
| "custom";
routeId?: string;
scopeId?: ScopeId;
stableId?: StableId;
description: string;
evidence: EvidenceRef[];
remediation?: string;
}

interface CoverageReport {
seedsTotal: number;
seedsVisited: number;
routesDiscovered: number;
scopesDiscovered: number;
elementsDiscovered: number;
actionsDiscovered: number;
workflowCandidatesDiscovered: number;
opaqueRegions: number;
unresolvedTransitions: number;
reviewItems: number;
confidenceSummary?: {
high: number;
medium: number;
low: number;
};
}

Discovery darf nicht bloß „ich glaube, das ist ein Button“ sagen. Das ist nett für Demos, unerquicklich für Produktbetrieb.

type EvidenceSource =
| "annotation"
| "app_registry"
| "dom"
| "accessibility"
| "visible_text"
| "signal"
| "transition"
| "network"
| "screenshot"
| "vision"
| "documentation"
| "manual_review"
| "inferred";
interface EvidenceRef {
source: EvidenceSource;
refId: string;
note?: string;
}
type Confidence = "high" | "medium" | "low";
  • high: durch Annotation, App Registry oder wiederholt beobachtete Transition mit konsistenten Signalen gestützt
  • medium: durch mehrere semantische Indikatoren oder einmalig erfolgreiche Transition gestützt
  • low: nur durch Heuristik, Screenshot oder partielle Ableitung gestützt

interface DiscoveryEnvironment {
environmentId: string;
baseUrl: string;
locale?: string;
viewport?: {
width: number;
height: number;
};
authMode?: "manual" | "seeded" | "session_reuse";
principalProfiles?: DiscoveryPrincipalProfile[];
featureFlags?: Record<string, boolean | string | number>;
budgets?: DiscoveryBudget;
safety?: DiscoverySafetyPolicy;
metadata?: Record<string, unknown>;
}
interface DiscoveryPrincipalProfile {
id: string;
roles?: string[];
grants?: PolicyGrant[];
description?: string;
}
interface DiscoveryBudget {
maxStates?: number;
maxTransitions?: number;
maxDepth?: number;
maxRuntimeMs?: number;
maxPerRoute?: number;
}
interface DiscoverySafetyPolicy {
defaultMode: "observe_only" | "safe_explore" | "sandbox_write";
allowExternalEffects?: boolean;
allowDestructiveActions?: boolean;
allowAuthFlows?: boolean;
allowPaymentFlows?: boolean;
}
  • observe_only DARF keine schreibenden oder aktivierenden Actions ausführen.
  • safe_explore DARF nur reversible, nicht-destruktive und nicht-externe Actions ausführen.
  • sandbox_write DARF Test-/Seed-Aktionen in kontrollierten Mandanten ausführen.
  • Discovery MUSS konservativ sein: unbekannte oder unsichere Aktionen SOLLTEN als nicht ausführbar gelten.

type DiscoverySeed =
| {
kind: "route";
routeId: string;
}
| {
kind: "url";
url: string;
}
| {
kind: "menu";
label: string;
}
| {
kind: "action";
actionId: ActionId;
}
| {
kind: "workflow";
workflowId: string;
}
| {
kind: "documentation";
ref: string;
};

Ein Mapper SOLLTE Seeds aus mehreren Quellen beziehen:

  • statische Router-/App-Manifeste
  • bekannte UIAP-Annotationen
  • registrierte App-Actions
  • Navigation und Menüs
  • Produktdokumentation
  • vorherige Discovery Packages
  • manuelle Reviewer-Eingaben

type DiscoveryRunStatus =
| "planning"
| "preparing"
| "seeding"
| "exploring"
| "extracting"
| "synthesizing"
| "reviewing"
| "completed"
| "failed"
| "cancelled";
interface DiscoveryRunSummary {
runId: string;
startedAt: string;
finishedAt?: string;
status: DiscoveryRunStatus;
environmentId: string;
profile?: string;
seeds?: DiscoverySeed[];
notes?: string[];
}

Ein konformer Mapper MUSS einen Run mindestens in dieser Reihenfolge behandeln:

  1. Umgebung vorbereiten
  2. Seeds auflösen
  3. initiale Zustände aufnehmen
  4. sichere Exploration durchführen
  5. Artefakte extrahieren
  6. Workflow-Kandidaten synthetisieren
  7. Review- und Coverage-Artefakte erzeugen
  8. Discovery Package finalisieren

Der Mapper MUSS mindestens erfassen:

  • Zielumgebung
  • Principal Profile
  • Feature-Flags
  • Budgets
  • Safety Policy
  • verfügbare UIAP-Profile/Extensions
  • Seeds

Wenn ein UIAP SDK vorhanden ist, SOLLTE der Mapper zuerst vorhandene:

  • data-uiap-*-Annotationen
  • Action Registries
  • Capability Documents
  • Policy Documents
  • Workflow Catalogs

einlesen.

Für jeden Seed MUSS der Mapper einen initialen Zustand erzeugen.

Ein Discovery State SOLLTE enthalten:

interface DiscoveryStateSnapshot {
stateId: string;
pageGraph: PageGraph;
screenshotRef?: string;
evidence: EvidenceRef[];
fingerprint: string;
discoveredAt: string;
entrySeed?: DiscoverySeed;
}

Der Mapper SOLLTE DOM- und UI-Änderungen während Exploration beobachten; MutationObserver ist dafür das Standardinstrument auf der Webplattform. ([MDN Web Docs][2])

  • Der Mapper SOLLTE PageGraph aus dem UIAP Web Profile bevorzugen.
  • Falls verfügbar, SOLLTE zusätzlich ein AX-Beleg gespeichert werden.
  • Für reichere AX-Snapshots DARF der Mapper CDP-Methoden wie Accessibility.getFullAXTree oder Accessibility.getPartialAXTree verwenden. ([chromedevtools.github.io][3])
  • Screenshots DÜRFEN als Zusatzbeleg gespeichert werden, aber nicht als einzige Quelle für Semantik.

Der Mapper MUSS Zustände deduplizieren können.

Ein Fingerprint SOLLTE primär aus diesen stabilen Merkmalen gebildet werden:

  • routeId oder normalisierte URL
  • sichtbare Scopes
  • stabile Element-IDs
  • normalisierte Rollen und Namen relevanter Controls
  • Modal-/Drawer-/Popover-Stack
  • strukturierte Collectionsignaturen
  • fokussiertes Primärelement

Ein Fingerprint SOLLTE nicht primär von flüchtigen Werten abhängen wie:

  • Zeitstempeln
  • Toaster-IDs
  • zufälligen React-/DOM-IDs
  • Scroll-Positionen ohne Layoutrelevanz
  • transienten Ladeindizien
interface StateFingerprintPolicy {
includeTextValues?: boolean;
includeCollections?: boolean;
ignoreTransientToasts?: boolean;
ignoreSpinners?: boolean;
}

Aus jedem Discovery State SOLLTE der Mapper extrahieren:

  • Route-Kandidaten
  • Scope-Kandidaten
  • Element-Kandidaten
  • Feld-Bedeutungen
  • Risiko- und Sensitivitätshinweise
  • Success-Signal-Kandidaten
  1. App-Annotierung
  2. Action Registry / Capability Model
  3. native HTML + ARIA
  4. sichtbarer Text und Label-Assoziation
  5. AX-Belege
  6. Heuristiken
  7. Vision-Fallback

Der Mapper SOLLTE von einem Zustand aus nur Aktionen ausführen, die:

  • durch Safety Policy erlaubt sind,
  • keine verbotenen Seiteneffekte erzeugen,
  • das Ziel verständlich erweitern,
  • innerhalb des Budgets liegen.
  1. bekannte, sichere appActions
  2. semantische Navigation
  3. Öffnen von Tabs, Accordions, Menüs, Drawern, Dialogen
  4. Navigation zu Hauptbereichen
  5. Auswahl in sicheren Filtern oder Tabs
  6. Formular-Drafts nur in Sandbox-Kontexten
  7. visuelle oder externe Fallbacks nur bei dokumentierter Notwendigkeit

Ein Mapper SOLLTE Ziele priorisiert über:

  • stabile IDs / Agent-IDs
  • Rolle
  • Name / Text
  • Scope-Kontext

auflösen. Test-/Agent-IDs sind in der Praxis oft robuster als Text oder CSS, und Playwright priorisiert für resiliente Locators Rolle, Text und Test IDs vor CSS/XPath. ([Playwright][4])

Vor jeder Exploration Action SOLLTE der Mapper mindestens prüfen:

  • Ziel ist attached
  • sichtbar
  • enabled
  • nicht blockiert
  • hinreichend stabil
  • im Viewport oder dorthin scrollbar

Playwrights Actionability-Checks und Auto-Waiting sind dafür ein gutes Referenzmodell. ([Playwright][5])

Jede ausgeführte Action SOLLTE als Transition dokumentiert werden mit:

  • Ausgangszustand
  • Zielauflösung
  • gewählter Action
  • Arguments
  • beobachteten Signalen
  • Zielzustand
  • Confidence

Wenn eine Action zu keinem klar unterscheidbaren Zielzustand führt, SOLLTE ein Review Item erzeugt werden.

Der Mapper SOLLTE aus Transition Chains Workflow-Kandidaten ableiten.

Ein Workflow-Kandidat ist plausibel, wenn:

  • ein fachlich erkennbares Ziel vorliegt,
  • die Schrittfolge nicht rein zufällig ist,
  • Inputs identifizierbar sind,
  • Success-Signale beobachtbar sind,
  • Policy-/Risk-Lagen bekannt oder zumindest konservativ ableitbar sind.

Bevorzugte Quellen für Workflow-Synthese:

  1. vorhandene Workflow-/Action-Kataloge
  2. wiederholt beobachtete Transition Chains
  3. Doku- und UI-Texte
  4. semantische Form-/Dialog-Strukturen
  5. manuell markierte High-Value-Flows

Die Same-Origin-Policy beschränkt direkte Interaktion mit Dokumenten anderer Origins, und ShadowRoot.mode unterscheidet zwischen open und closed, wobei closed die internen Strukturen für JavaScript von außen unzugänglich macht. Der Mapper MUSS diese Grenzen korrekt abbilden. ([MDN Web Docs][6])

DÜRFEN direkt erkundet werden.

MÜSSEN als opaque behandelt werden. Es DÜRFEN nur Container- oder Frame-Metadaten erfasst werden.

DÜRFEN als eigener Discovery-Kontext mit separatem Dokument- und Evidenzraum behandelt werden.

DARF erkundet werden.

MUSS als opaque behandelt werden, außer der Host publiziert explizite UIAP-Bindings oder Adapter.

SOLLTEN als vision-assisted markiert werden und standardmäßig low confidence erhalten, wenn keine zusätzliche Semantik oder Registry vorhanden ist.


Discovery MUSS vor jeder Action eine Discovery-Sicherheitsentscheidung treffen.

interface DiscoveryActionPolicyDecision {
effect: "allow" | "skip" | "review" | "deny";
reason:
| "safe"
| "unknown_side_effect"
| "destructive"
| "external_effect"
| "credential"
| "payment"
| "security_sensitive"
| "budget_exceeded"
| "opaque_boundary"
| "manual_only";
}
  • destructive, billing_change, security_change, irreversible SOLLTEN standardmäßig deny sein.
  • Credential-, Secret- und Payment-Bereiche SOLLTEN standardmäßig review oder deny sein.
  • Unklare Actions ohne sichere Seiteneffektklassifikation SOLLTEN nicht autonom ausgeführt werden.
  • Workflow-Synthese DARF auf Beobachtung basieren, ohne riskante Actions wirklich auszuführen.

Wenn der Mapper als UIAP-Erweiterung exponiert wird, SOLLTEN mindestens diese Nachrichtentypen unterstützt werden.

interface DiscoveryPlanPayload {
environment: DiscoveryEnvironment;
seeds?: DiscoverySeed[];
}
interface DiscoveryPlannedPayload {
runId: string;
estimatedSeedCount?: number;
acceptedSeeds?: DiscoverySeed[];
rejectedSeeds?: Array<{
seed: DiscoverySeed;
reason: string;
}>;
}

interface DiscoveryStartPayload {
runId: string;
}
interface DiscoveryStartedPayload {
runId: string;
status: "preparing" | "seeding" | "exploring";
}

interface DiscoveryProgressPayload {
runId: string;
status: DiscoveryRunStatus;
currentSeed?: DiscoverySeed;
currentRouteId?: string;
currentStateId?: string;
visitedStates?: number;
visitedTransitions?: number;
discoveredRoutes?: number;
discoveredActions?: number;
discoveredWorkflowCandidates?: number;
note?: string;
}

interface DiscoveryPausePayload {
runId: string;
reason?: string;
}
interface DiscoveryPausedPayload {
runId: string;
status: "paused";
}

interface DiscoveryResumePayload {
runId: string;
}
interface DiscoveryResumedPayload {
runId: string;
status: DiscoveryRunStatus;
}

interface DiscoveryCancelPayload {
runId: string;
reason?: string;
}
interface DiscoveryCancelledPayload {
runId: string;
status: "cancelled";
}

interface DiscoveryResultPayload {
runId: string;
status: "completed" | "failed" | "cancelled";
package: DiscoveryPackage;
}

interface DiscoveryPackageGetPayload {
runId: string;
}
interface DiscoveryPackagePayload {
package: DiscoveryPackage;
}

Ein Route-Kandidat SOLLTE erzeugt werden, wenn mindestens eines davon zutrifft:

  • eindeutige Router- oder App-Route vorhanden
  • stabile URL/Path-Struktur
  • Navigation führt reproduzierbar in unterscheidbaren State
  • Route ist durch Annotation oder App Registry markiert

Ein Scope-Kandidat SOLLTE erzeugt werden für:

  • Formulare
  • Dialoge
  • Drawer
  • Menüs
  • Popovers
  • Tabpanels
  • größere Regions mit eigenem Interaktionskontext

Ein Element-Kandidat SOLLTE erzeugt werden, wenn das Objekt:

  • interaktiv ist oder
  • Erfolg/Fehler/Zustand signalisiert oder
  • als Parameterquelle relevant ist.

Ein Action-Kandidat SOLLTE erzeugt werden, wenn:

  • registrierte App Action vorhanden ist oder
  • primitive UI-Affordance vorhanden ist oder
  • eine wiederholt beobachtete Transition fachlich stabil erscheint.
  • button + activateui.activate
  • editierbares Feld → ui.enterText, ui.clearText
  • checkbox / switchui.toggle
  • combobox / listboxui.choose
  • formulierbarer Scope → ui.submit
  • routefähiges Ziel → nav.navigate

Ein Success-Signal SOLLTE abgeleitet werden aus:

  • Route-Wechsel
  • Dialog öffnet/schließt
  • Toast/Status-Meldung
  • Validierungsstatus
  • Collection Count oder Entity-Änderung
  • deklarierter App-Signalquelle

Wenn kein beobachtbares Signal existiert, MUSS ein Review Item missing_success_signal erzeugt werden.


Ein Mapper MUSS mindestens dann ein Review Item erzeugen, wenn:

  • mehrere gleich plausible Ziele existieren
  • eine wichtige Action nur per Heuristik erkannt wurde
  • ein Cross-Origin- oder Closed-Shadow-Bereich Discovery blockiert
  • ein Workflow-Kandidat keine sauberen Success-Signale hat
  • eine Route ohne stabile Identität gefunden wurde
  • ein sicherheits- oder billingnaher Flow berührt wurde
  • Semantik und beobachtetes Verhalten widersprüchlich sind

Ein konformer Discovery Mapper v0.1 MUSS:

  • kontrollierte Runs planen und ausführen können
  • mindestens einen PageGraph pro Seed erzeugen können
  • Zustände deduplizieren können
  • Route-, Scope-, Element- und Action-Kandidaten erzeugen können
  • Transitionen dokumentieren können
  • Review Queue und Coverage Report erzeugen können
  • opaque Boundaries korrekt markieren

Ein konformer Mapper SOLLTE:

  • AX-Evidenz nutzen können
  • mehrere Principal Profiles unterstützen
  • Workflow-Kandidaten synthetisieren können
  • Deltas oder wiederholte State-Aufnahmen effizient verwalten
  • historische Discovery Packages vergleichen können

{
"uiap": "0.1",
"kind": "request",
"type": "uiap.discovery.plan",
"id": "msg_501",
"sessionId": "sess_mapper",
"ts": "2026-03-26T16:00:00.000Z",
"source": { "role": "agent", "id": "uiap-discovery" },
"payload": {
"environment": {
"environmentId": "staging-admin",
"baseUrl": "https://staging.app.example.com",
"locale": "de-CH",
"viewport": { "width": 1440, "height": 900 },
"authMode": "seeded",
"principalProfiles": [
{
"id": "workspace-admin",
"roles": ["admin"],
"grants": ["observe", "guide", "draft", "act", "admin"]
}
],
"budgets": {
"maxStates": 500,
"maxTransitions": 1200,
"maxDepth": 8,
"maxRuntimeMs": 1800000
},
"safety": {
"defaultMode": "safe_explore",
"allowExternalEffects": false,
"allowDestructiveActions": false,
"allowAuthFlows": true,
"allowPaymentFlows": false
}
},
"seeds": [
{ "kind": "route", "routeId": "dashboard" },
{ "kind": "route", "routeId": "videos" },
{ "kind": "route", "routeId": "settings" }
]
}
}
{
"modelVersion": "0.1",
"spec": "uiap.discovery",
"run": {
"runId": "disc_77",
"startedAt": "2026-03-26T16:00:00.000Z",
"finishedAt": "2026-03-26T16:11:22.000Z",
"status": "completed",
"environmentId": "staging-admin"
},
"routeCatalog": {
"routes": [
{
"routeId": "videos.new",
"urls": ["https://staging.app.example.com/videos/new"],
"titles": ["Neues Video"],
"confidence": "high",
"discoveredBy": [
{ "source": "annotation", "refId": "route:videos.new" },
{ "source": "transition", "refId": "tr_18" }
]
}
]
},
"actionCatalog": {
"actions": [
{
"id": "video.create",
"kind": "domain",
"routes": ["videos.new"],
"targetPatterns": [
{ "stableId": "video.submit", "role": "button", "scopeId": "video.create.form" }
],
"risk": { "level": "confirm", "tags": ["external_effect"] },
"successSignals": [
{ "kind": "route.changed", "pattern": "/videos/:id" },
{ "kind": "toast.contains", "text": "erstellt" }
],
"confidence": "high",
"reviewState": "candidate",
"discoveredBy": [
{ "source": "app_registry", "refId": "action:video.create" },
{ "source": "transition", "refId": "tr_33" }
]
}
]
},
"workflowCandidates": {
"workflows": [
{
"id": "candidate.video.create_first_video",
"title": "Erstes Video erstellen",
"category": "onboarding",
"routeIds": ["dashboard", "videos", "videos.new"],
"requiredInputs": [
{ "name": "title", "type": "string", "required": true }
],
"stepSkeleton": [
{ "type": "action", "actionId": "nav.navigate" },
{ "type": "action", "actionId": "ui.enterText", "parameterNames": ["title"] },
{ "type": "action", "actionId": "video.create" },
{ "type": "ensure", "signals": [{ "kind": "route.changed", "pattern": "/videos/:id" }] },
{ "type": "complete" }
],
"confidence": "medium",
"reviewState": "needs_review",
"discoveredBy": [
{ "source": "transition", "refId": "chain_9" },
{ "source": "documentation", "refId": "doc_3" }
]
}
]
},
"reviewQueue": {
"items": [
{
"id": "rev_19",
"severity": "medium",
"kind": "missing_success_signal",
"routeId": "videos.new",
"description": "Für ui.enterText auf video.use_case wurde kein verlässliches Erfolgs-Signal gefunden.",
"evidence": [
{ "source": "transition", "refId": "tr_29" }
],
"remediation": "Explizites success signal oder field binding ergänzen."
}
]
},
"coverage": {
"seedsTotal": 3,
"seedsVisited": 3,
"routesDiscovered": 12,
"scopesDiscovered": 31,
"elementsDiscovered": 186,
"actionsDiscovered": 44,
"workflowCandidatesDiscovered": 8,
"opaqueRegions": 2,
"unresolvedTransitions": 5,
"reviewItems": 17,
"confidenceSummary": {
"high": 122,
"medium": 104,
"low": 17
}
}
}

Der Mapper sollte nicht versuchen, die ganze App frei und blind zu „durchspidern“. Der effiziente Weg ist:

  • Seeds + App-Semantik + UIAP-Annotationen zuerst,
  • dann kontrollierte Exploration mit Budgets,
  • dann Transition Graph + Candidate Synthesis,
  • dann menschliche Review für High-Value- oder High-Risk-Flows.

Das spart Kosten, senkt Halluzinationsmüll und führt zu Discovery-Paketen, die man tatsächlich in Workflow- und Runtime-Specs weiterverwenden kann, statt sie nachher feierlich wegzuwerfen.


  • [UIAP-CORE] UIAP Core v0.1
  • [UIAP-CAP] UIAP Capability Model v0.1
  • [UIAP-WEB] UIAP Web Profile v0.1
  • [UIAP-ACTION] UIAP Action Runtime v0.1
  • [UIAP-POLICY] UIAP Policy Extension v0.1
  • [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
  • Discovery DARF NICHT auf Seiten ausgeführt werden, für die keine Autorisierung vorliegt.
  • Gecrawlte Inhalte KÖNNEN sensitive Daten enthalten; Discovery-Ergebnisse SOLLTEN vor der Persistierung redaktiert werden.
  • LLM-gestützte Review-Modi MÜSSEN darauf achten, dass keine sensitive DOM-Inhalte an externe Modell-APIs gesendet werden, sofern dies nicht explizit autorisiert ist.
  • Discovery-Ergebnisse sind Vorschläge, keine verbindlichen Konfigurationen; sie MÜSSEN vor Produktiveinsatz manuell geprüft werden.
VersionDatumÄnderungen
0.12026-03-27Initialer Entwurf