@wenathlan/extension 1.1.54 → 1.1.55

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../workflow.ts", "../../policy.ts", "../../workfloweditor.ts", "../tabscommand.ts", "../pageforms.ts", "../datacommand.ts", "../sidepanel.ts"],
4
- "sourcesContent": ["import type { actionrisk, blockinvocation, delaystep, expressiontype, nestedparam, regexrule, runlogentry, steptemplate, variablebinding, variablekind, variablescope, variablevalue, watchdogconfig, workflowblock, workflowrecord, workflowrun, workflowstep } from \"./types.js\";\nimport type { stepoutcome } from \"./types.js\";\nimport { controlsteps, iscontrolflowkind, validatecontrolpayload } from \"./controlflow.js\";\n\n/**\n * Workflow engine for the 1.1.50 family.\n * Every correlated rule for the reviewed step composition lives in this file: the workflow kind list, the step, block and template normalizers, the composition that validates and freezes a step list, the block expansion that hides no step from review, the pre-run validation of kinds, scopes and bindings, the typed scope stack with shadowing, the variable bindings that link step outputs to names, the expression arithmetic with coercion refusals, the regex extraction with honest no match outcomes, the seeded delay jitter, the run loop with per step checkpoints, the single step execution, the pause, resume and cancel transitions and the pure dry run with read only projections.\n * The engine stays pure: every page, browser and storage effect flows through the injected executor so tests run on plain fixtures, and the risk grading flows through the injected risk callback so the policy table stays the single source of truth.\n */\n\n/** The workflow kinds of the 1.1.50 family: composition, templates, runs, dry runs, jittered delays, element waits, expressions and variable extraction. */\nexport const workflowkinds: string[] = [\"composeworkflow\", \"savetemplate\", \"runworkflow\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\"];\n\n/** The outcome the injected executor returns for one workflow step: control flow executors also return the merged scopes and the iteration runlog entries so the run loop adopts them. */\nexport type stepexecution = { ok: boolean; summary: string; details?: Record<string, unknown>; scopes?: variablescope[]; log?: runlogentry[] };\n\n/** Normalizes one nested parameter of a block invocation: the variable name, the reviewed kind and the optional default value. */\nfunction nestedparamof(value: unknown): nestedparam | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.name)) return undefined;\n if (!variablekinds.includes(candidate.kind as variablekind)) return undefined;\n if (candidate.default !== undefined && ![\"string\", \"number\", \"boolean\"].includes(typeof candidate.default) && !Array.isArray(candidate.default)) return undefined;\n return { name: candidate.name, kind: candidate.kind as variablekind, ...(candidate.default !== undefined ? { default: candidate.default as string | number | boolean | string[] } : {}) };\n}\n\n/** Normalizes one workflow step: id, kind, label, the optional target, value and JSON options, the output bindings, the inline expression, the inline regex rule, the breakpoint marker and the nested block parameters. */\nexport function workflowstepof(value: unknown): workflowstep | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.id !== \"string\" || !candidate.id.trim()) return undefined;\n if (typeof candidate.kind !== \"string\" || !/^[a-z]+$/.test(candidate.kind)) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n if (candidate.target !== undefined && (typeof candidate.target !== \"string\" || !candidate.target)) return undefined;\n if (candidate.value !== undefined && typeof candidate.value !== \"string\") return undefined;\n if (candidate.options !== undefined && typeof candidate.options !== \"string\") return undefined;\n if (candidate.breakpoint !== undefined && typeof candidate.breakpoint !== \"boolean\") return undefined;\n const bindings = Array.isArray(candidate.bindings) ? candidate.bindings.flatMap(binding => bindingof(binding) !== undefined ? [bindingof(binding) as variablebinding] : []) : undefined;\n if (candidate.bindings !== undefined && bindings === undefined) return undefined;\n if (Array.isArray(candidate.bindings) && bindings !== undefined && bindings.length !== (candidate.bindings as unknown[]).length) return undefined;\n const expression = candidate.expression === undefined ? undefined : expressionof(candidate.expression);\n if (candidate.expression !== undefined && expression === undefined) return undefined;\n const extract = candidate.extract === undefined ? undefined : regexruleof(candidate.extract);\n if (candidate.extract !== undefined && extract === undefined) return undefined;\n const params = Array.isArray(candidate.params) ? candidate.params.flatMap(param => nestedparamof(param) !== undefined ? [nestedparamof(param) as nestedparam] : []) : undefined;\n if (candidate.params !== undefined && params === undefined) return undefined;\n if (Array.isArray(candidate.params) && params !== undefined && params.length !== (candidate.params as unknown[]).length) return undefined;\n return { id: candidate.id, kind: candidate.kind as workflowstep[\"kind\"], label: candidate.label, ...(candidate.target !== undefined ? { target: candidate.target } : {}), ...(candidate.value !== undefined ? { value: candidate.value } : {}), ...(candidate.options !== undefined ? { options: candidate.options } : {}), ...(bindings !== undefined && bindings.length > 0 ? { bindings } : {}), ...(expression !== undefined ? { expression } : {}), ...(extract !== undefined ? { extract } : {}), ...(candidate.breakpoint === true ? { breakpoint: true } : {}), ...(params !== undefined && params.length > 0 ? { params } : {}) };\n}\n\n/** Normalizes one block invocation: the referenced block name and the human readable label. */\nexport function blockinvocationof(value: unknown): blockinvocation | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.block !== \"string\" || !candidate.block.trim()) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n const params = Array.isArray(candidate.params) ? candidate.params.flatMap(param => nestedparamof(param) !== undefined ? [nestedparamof(param) as nestedparam] : []) : undefined;\n if (candidate.params !== undefined && params === undefined) return undefined;\n if (Array.isArray(candidate.params) && params !== undefined && params.length !== (candidate.params as unknown[]).length) return undefined;\n return { block: candidate.block, label: candidate.label, ...(params !== undefined && params.length > 0 ? { params } : {}) };\n}\n\n/** Normalizes one reusable workflow block: the unique name, the label and the child steps with nested block invocations. */\nexport function workflowblockof(value: unknown): workflowblock | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.name)) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n if (!Array.isArray(candidate.steps)) return undefined;\n const steps: Array<workflowstep | blockinvocation> = [];\n for (const entry of candidate.steps) {\n const step = workflowstepof(entry);\n if (step) { steps.push(step); continue; }\n const invocation = blockinvocationof(entry);\n if (invocation) { steps.push(invocation); continue; }\n return undefined;\n }\n return { name: candidate.name, label: candidate.label, steps };\n}\n\n/** Normalizes one shareable step template: the id, the unique name, the origin, the step and the share time. */\nexport function steptemplateof(value: unknown): steptemplate | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.id !== \"string\" || !candidate.id.trim()) return undefined;\n if (typeof candidate.name !== \"string\" || !candidate.name.trim()) return undefined;\n if (typeof candidate.origin !== \"string\" || !candidate.origin.trim()) return undefined;\n const step = workflowstepof(candidate.step);\n if (!step) return undefined;\n if (typeof candidate.sharedat !== \"number\" || !Number.isFinite(candidate.sharedat)) return undefined;\n return { id: candidate.id, name: candidate.name, origin: candidate.origin, step, sharedat: candidate.sharedat };\n}\n\n/** Normalizes one variable binding that links a step output path to a named variable of a typed kind. */\nfunction bindingof(value: unknown): variablebinding | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.variable !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.variable)) return undefined;\n if (!variablekinds.includes(candidate.kind as variablekind)) return undefined;\n if (typeof candidate.stepid !== \"string\" || !candidate.stepid.trim()) return undefined;\n if (candidate.path !== undefined && (typeof candidate.path !== \"string\" || !candidate.path.trim())) return undefined;\n return { variable: candidate.variable, kind: candidate.kind as variablekind, stepid: candidate.stepid, ...(candidate.path !== undefined ? { path: candidate.path } : {}) };\n}\n\n/** The typed variable kinds of the scope grammar. */\nconst variablekinds: variablekind[] = [\"string\", \"number\", \"boolean\", \"list\", \"element\"];\n\n/** The reviewed expression operators of the workflow grammar. */\nexport const expressionoperators: string[] = [\"add\", \"subtract\", \"multiply\", \"divide\", \"modulo\", \"equal\", \"notequal\", \"less\", \"greater\", \"lessequal\", \"greaterequal\", \"and\", \"or\", \"not\", \"concat\", \"contains\", \"length\"];\n\n/** Normalizes one reviewed expression: the operands, the operator and the result variable with its result kind. */\nexport function expressionof(value: unknown): expressiontype | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n const left = operandof(candidate.left);\n if (!left) return undefined;\n const right = candidate.right === undefined ? undefined : operandof(candidate.right);\n if (candidate.right !== undefined && right === undefined) return undefined;\n if (typeof candidate.operator !== \"string\" || !expressionoperators.includes(candidate.operator)) return undefined;\n if (typeof candidate.result !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.result)) return undefined;\n if (!variablekinds.includes(candidate.resultkind as variablekind)) return undefined;\n return { left, ...(right !== undefined ? { right } : {}), operator: candidate.operator as expressiontype[\"operator\"], result: candidate.result, resultkind: candidate.resultkind as variablekind };\n}\n\n/** Normalizes one expression operand: a variable reference or a literal of a reviewed primitive kind. */\nfunction operandof(value: unknown): { ref?: string; literal?: string | number | boolean } | undefined {\n if (value === undefined) return undefined;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return { literal: value };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.ref === \"string\" && /^[a-z][a-z0-9]*$/.test(candidate.ref)) return { ref: candidate.ref };\n if (typeof candidate.literal === \"string\" || typeof candidate.literal === \"number\" || typeof candidate.literal === \"boolean\") return { literal: candidate.literal };\n return undefined;\n}\n\n/** Normalizes one reviewed regex rule: the pattern, the flag set and the named capture group list. */\nexport function regexruleof(value: unknown): regexrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.pattern !== \"string\" || !candidate.pattern.trim()) return undefined;\n if (typeof candidate.flags !== \"string\" || !/^[dgimsuvy]*$/.test(candidate.flags)) return undefined;\n const groups = Array.isArray(candidate.groups) ? candidate.groups.flatMap(group => typeof group === \"string\" && /^[a-z][a-z0-9]*$/.test(group) ? [group] : []) : [];\n if (candidate.groups !== undefined && groups.length !== (candidate.groups as unknown[]).length) return undefined;\n return { pattern: candidate.pattern, flags: candidate.flags, groups };\n}\n\n/** Flattens nested blocks into one executable step list; every flattened step carries the innermost block name so runs highlight the active block, and the nested parameters of an invocation stamp onto the first step of its region so the run binds them into the block scope. Unknown or cyclic block references are refused. */\nexport function expandblocks(steps: Array<workflowstep | blockinvocation>, blocks: workflowblock[]): workflowstep[] {\n const byname = new Map(blocks.map(block => [block.name, block]));\n const expanded: workflowstep[] = [];\n const visit = (entries: Array<workflowstep | blockinvocation>, path: string[], inside: string | undefined, params?: nestedparam[]): void => {\n let stamped = params === undefined;\n for (const entry of entries) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) {\n const marked = inside === undefined ? entry : { ...entry, block: inside };\n if (!stamped && params !== undefined) { expanded.push({ ...marked, params }); stamped = true; } else expanded.push(marked);\n continue;\n }\n const invocation = blockinvocationof(entry);\n if (!invocation) throw new Error(\"The step list entry is neither a reviewed step nor a block invocation.\");\n if (path.includes(invocation.block)) throw new Error(`The block ${invocation.block} recurs inside itself and cannot expand.`);\n const block = byname.get(invocation.block);\n if (!block) throw new Error(`The block ${invocation.block} is not defined in the workflow.`);\n visit(block.steps, [...path, invocation.block], invocation.block, invocation.params ?? params);\n }\n };\n visit(steps, [], undefined);\n if (expanded.length === 0) throw new Error(\"A workflow needs at least one executable step after block expansion.\");\n return expanded;\n}\n\n/** Composes one workflow record: validates the name, version, origin grants, steps and blocks, expands every block so no step stays hidden, grades the review risk through the injected risk table and freezes the result. */\nexport function composeworkflow(input: { id?: string; name: string; version: number; origins: string[]; steps: Array<workflowstep | blockinvocation>; blocks?: workflowblock[]; now: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): workflowrecord {\n if (typeof input.name !== \"string\" || !input.name.trim()) throw new Error(\"The workflow name must be a non-empty string.\");\n if (typeof input.version !== \"number\" || !Number.isInteger(input.version) || input.version < 1) throw new Error(\"The workflow version must be a positive integer.\");\n if (!Array.isArray(input.origins) || input.origins.length === 0) throw new Error(\"A workflow needs at least one granted HTTPS origin.\");\n const origins = input.origins.map(origin => {\n try { return new URL(origin).origin; } catch { throw new Error(`The workflow origin ${origin} is not a valid url.`); }\n });\n if (origins.some(origin => !origin.startsWith(\"https://\"))) throw new Error(\"Workflow origins must use HTTPS.\");\n const blocks = input.blocks ?? [];\n if (blocks.some((block, index) => blocks.findIndex(other => other.name === block.name) !== index)) throw new Error(\"Workflow block names must stay unique.\");\n for (const entry of input.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) {\n if (input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} is not a reviewed action kind.`);\n }\n }\n for (const block of blocks) for (const entry of block.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} inside block ${block.name} is not a reviewed action kind.`);\n }\n const steps = expandblocks(input.steps, blocks);\n for (const step of steps) {\n if (input.kindallowed && !input.kindallowed(step.kind)) throw new Error(`The workflow step kind ${step.kind} is not a reviewed action kind.`);\n if (iscontrolflowkind(step.kind)) {\n validatecontrolpayload(step);\n for (const child of controlsteps(step)) {\n if (input.kindallowed && !input.kindallowed(child.kind)) throw new Error(`The workflow step kind ${child.kind} inside the control payload of ${step.id} is not a reviewed action kind.`);\n }\n }\n if (step.bindings) for (const binding of step.bindings) {\n if (!steps.some(other => other.id === binding.stepid)) throw new Error(`The binding of ${binding.variable} references the unknown step ${binding.stepid}.`);\n }\n }\n const riskof = input.riskof ?? ((): actionrisk => \"sensitive\");\n const gradedkinds = steps.flatMap(step => [step.kind, ...controlsteps(step).map(child => child.kind)]);\n const risk: actionrisk = gradedkinds.some(kind => riskof(kind) === \"sensitive\") ? \"sensitive\" : gradedkinds.some(kind => riskof(kind) === \"interaction\") ? \"interaction\" : \"read\";\n const record: workflowrecord = { id: input.id ?? crypto.randomUUID(), name: input.name, version: input.version, origins: [...new Set(origins)], steps, blocks, risk, createdat: input.now };\n return deepfreeze(record);\n}\n\n/** Freezes a composed workflow record so later mutations of the shared object graph never rewrite a reviewed workflow. */\nfunction deepfreeze(record: workflowrecord): workflowrecord {\n for (const step of record.steps) Object.freeze(step);\n for (const block of record.blocks) for (const entry of block.steps) if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) Object.freeze(entry);\n Object.freeze(record.blocks);\n Object.freeze(record.steps);\n return Object.freeze(record);\n}\n\n/** Validates a composed workflow before any run: the expanded step list, every step kind against the injected allowlist, the bindings against earlier steps and every variable reference against the bindings, the inputs and the root scope. */\nexport function validateworkflow(record: workflowrecord, options?: { kindallowed?: (kind: string) => boolean; inputs?: string[] }): { allowed: boolean; reason?: string } {\n if (record.steps.length === 0) return { allowed: false, reason: \"A workflow needs at least one reviewed step.\" };\n const defined = new Set(options?.inputs ?? []);\n const byid = new Map(record.steps.map((step, index) => [step.id, { step, index }]));\n for (let index = 0; index < record.steps.length; index += 1) {\n const step = record.steps[index] as workflowstep;\n if (options?.kindallowed && !options.kindallowed(step.kind)) return { allowed: false, reason: `The workflow step kind ${step.kind} is not a reviewed action kind.` };\n if (step.bindings) for (const binding of step.bindings) {\n const source = byid.get(binding.stepid);\n if (!source) return { allowed: false, reason: `The binding of ${binding.variable} references the unknown step ${binding.stepid}.` };\n if (source.index >= index) return { allowed: false, reason: `The binding of ${binding.variable} must link an earlier step than ${step.id}.` };\n defined.add(binding.variable);\n }\n if (step.expression) {\n for (const operand of [step.expression.left, step.expression.right]) {\n if (operand?.ref && !defined.has(operand.ref)) return { allowed: false, reason: `The expression of step ${step.id} references the undefined variable ${operand.ref}.` };\n }\n defined.add(step.expression.result);\n }\n if (step.extract) for (const group of step.extract.groups) defined.add(group);\n }\n return { allowed: true };\n}\n\n/** Opens one child scope for a block invocation; the parent chain stays intact so resolution walks outward. */\nexport function pushscope(scopes: variablescope[], name: string, parent?: string): variablescope[] {\n return [...scopes, { name, variables: [], ...(parent !== undefined ? { parent } : {}) }];\n}\n\n/** Closes the newest scope and keeps every parent scope intact. */\nexport function popscope(scopes: variablescope[]): variablescope[] {\n if (scopes.length === 0) return scopes;\n return scopes.slice(0, -1);\n}\n\n/** Resolves one variable from the nearest scope outward through the parent chain; shadowing follows the newest scope first. */\nexport function resolvevariable(scopes: variablescope[], name: string): variablevalue | undefined {\n for (let index = scopes.length - 1; index >= 0; index -= 1) {\n const scope = scopes[index] as variablescope;\n const found = scope.variables.find(variable => variable.name === name);\n if (found) return found;\n if (scope.parent === undefined) continue;\n const parentindex = scopes.findIndex(candidate => candidate.name === scope.parent);\n if (parentindex >= 0 && parentindex < index) {\n const inherited = resolvevariable([scopes[parentindex] as variablescope], name);\n if (inherited) return inherited;\n }\n }\n return undefined;\n}\n\n/** Writes one variable into the newest scope, replacing a same named value of that scope only. */\nexport function setvariable(scopes: variablescope[], name: string, kind: variablekind, value: string | number | boolean | string[], now: number): variablescope[] {\n if (scopes.length === 0) scopes = [{ name: \"root\", variables: [] }];\n const target = scopes[scopes.length - 1] as variablescope;\n const variables = [...target.variables.filter(variable => variable.name !== name), { name, kind, value, setat: now }];\n return [...scopes.slice(0, -1), { ...target, variables }];\n}\n\n/** Coerces one raw binding value into the reviewed variable kind; mismatched values are refused instead of silently rewritten. */\nfunction coercevariable(value: unknown, kind: variablekind): string | number | boolean | string[] {\n if (kind === \"number\") {\n const parsed = typeof value === \"number\" ? value : typeof value === \"string\" && value.trim() !== \"\" ? Number(value) : NaN;\n if (!Number.isFinite(parsed)) throw new Error(\"The bound value is not a finite number.\");\n return parsed;\n }\n if (kind === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw new Error(\"The bound value is not a boolean.\");\n }\n if (kind === \"list\") {\n if (Array.isArray(value)) return value.map(item => String(item));\n if (typeof value === \"string\") return value.length === 0 ? [] : value.split(\",\");\n throw new Error(\"The bound value is not a list.\");\n }\n if (kind === \"element\") {\n if (typeof value === \"string\" && value.trim()) return value;\n throw new Error(\"The bound value is not an element reference.\");\n }\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n throw new Error(\"The bound value is not a string.\");\n}\n\n/** Reads one dotted path out of a step outcome; an absent path returns the outcome summary. */\nfunction outcomedetail(outcome: stepoutcome, path: string | undefined): unknown {\n if (!path) return outcome.summary;\n let current: unknown = outcome.details ?? {};\n for (const segment of path.split(\".\")) {\n if (!current || typeof current !== \"object\" || Array.isArray(current)) return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/** Resolves every binding whose source step already produced an outcome into the newest scope; the engine runs this before each step so following steps read fresh values. */\nexport function bindvariables(scopes: variablescope[], bindings: variablebinding[], outputs: Record<string, stepoutcome>, now: number): { scopes: variablescope[]; produced: string[] } {\n let current = scopes;\n const produced: string[] = [];\n for (const binding of bindings) {\n const outcome = outputs[binding.stepid];\n if (!outcome) continue;\n const raw = outcomedetail(outcome, binding.path);\n if (raw === undefined) throw new Error(`The binding of ${binding.variable} found no value at ${binding.path ?? \"the summary\"} of step ${binding.stepid}.`);\n current = setvariable(current, binding.variable, binding.kind, coercevariable(raw, binding.kind), now);\n produced.push(binding.variable);\n }\n return { scopes: current, produced };\n}\n\n/** Resolves one expression operand: a variable reference resolved from the nearest scope outward or a literal; list values flow through so the list operators handle them while every other operator refuses them at coercion. */\nfunction operandvalue(operand: { ref?: string; literal?: string | number | boolean }, scopes: variablescope[]): string | number | boolean | string[] {\n if (operand.ref !== undefined) {\n const resolved = resolvevariable(scopes, operand.ref);\n if (!resolved) throw new Error(`The expression references the undefined variable ${operand.ref}.`);\n return resolved.value;\n }\n if (operand.literal === undefined) throw new Error(\"The expression operand needs a variable reference or a literal.\");\n return operand.literal;\n}\n\n/** Evaluates one reviewed expression between variables: arithmetic, comparison and logic operators with operand coercion and mismatched operator refusals, resolving references from the nearest scope outward; list operands join only the contains and length operators while every other operator refuses them at coercion. */\nexport function expressioneval(expression: expressiontype, scopes: variablescope[]): string | number | boolean {\n const left = operandvalue(expression.left, scopes);\n const right = expression.right === undefined ? undefined : operandvalue(expression.right, scopes);\n const operand = (value: string | number | boolean | string[] | undefined): string | number | boolean => {\n if (Array.isArray(value)) throw new Error(\"The expression operand is a list and needs the contains or length operator.\");\n if (value === undefined) throw new Error(\"The expression operand is missing.\");\n return value;\n };\n const numbervalue = (value: string | number | boolean | string[] | undefined): number => {\n const primitive = operand(value);\n if (typeof primitive === \"number\") return primitive;\n if (typeof primitive === \"string\" && primitive.trim() !== \"\") {\n const parsed = Number(primitive);\n if (Number.isFinite(parsed)) return parsed;\n }\n throw new Error(\"The arithmetic operand is not a number.\");\n };\n const booleanvalue = (value: string | number | boolean | string[] | undefined): boolean => {\n const primitive = operand(value);\n if (typeof primitive === \"boolean\") return primitive;\n throw new Error(\"The logic operand is not a boolean.\");\n };\n const stringvalue = (value: string | number | boolean | string[] | undefined): string => {\n const primitive = operand(value);\n if (typeof primitive === \"string\") return primitive;\n if (typeof primitive === \"number\" || typeof primitive === \"boolean\") return String(primitive);\n throw new Error(\"The text operand is not a string.\");\n };\n switch (expression.operator) {\n case \"add\": return numbervalue(left) + numbervalue(right);\n case \"subtract\": return numbervalue(left) - numbervalue(right);\n case \"multiply\": return numbervalue(left) * numbervalue(right);\n case \"divide\": {\n const divisor = numbervalue(right);\n if (divisor === 0) throw new Error(\"The expression divides by zero.\");\n return numbervalue(left) / divisor;\n }\n case \"modulo\": {\n const divisor = numbervalue(right);\n if (divisor === 0) throw new Error(\"The expression divides by zero.\");\n return numbervalue(left) % divisor;\n }\n case \"equal\": return left === right;\n case \"notequal\": return left !== right;\n case \"less\": return numbervalue(left) < numbervalue(right);\n case \"greater\": return numbervalue(left) > numbervalue(right);\n case \"lessequal\": return numbervalue(left) <= numbervalue(right);\n case \"greaterequal\": return numbervalue(left) >= numbervalue(right);\n case \"and\": return booleanvalue(left) && booleanvalue(right);\n case \"or\": return booleanvalue(left) || booleanvalue(right);\n case \"not\": return !booleanvalue(left);\n case \"concat\": return `${stringvalue(left)}${stringvalue(right)}`;\n case \"contains\": {\n if (Array.isArray(left)) return left.includes(stringvalue(right));\n return stringvalue(left).includes(stringvalue(right));\n }\n case \"length\": {\n if (Array.isArray(left)) return left.length;\n return stringvalue(left).length;\n }\n default: throw new Error(\"The reviewed expression operator is unknown.\");\n }\n}\n\n/** Applies one reviewed regex rule to text and stores the named capture groups as string variables; the no match case is an honest outcome instead of a crash. */\nexport function regexextract(rule: regexrule, text: string, now: number): { matched: boolean; variables: variablevalue[] } {\n const pattern = new RegExp(rule.pattern, rule.flags);\n const match = pattern.exec(text);\n if (!match) return { matched: false, variables: [] };\n const variables: variablevalue[] = [];\n for (const group of rule.groups) {\n const value = match.groups?.[group];\n variables.push({ name: group, kind: \"string\", value: typeof value === \"string\" ? value : \"\", setat: now });\n }\n return { matched: true, variables };\n}\n\n/** Plans the element wait polling: how many probe passes fit inside the reviewed timeout window at the reviewed poll interval; a zero timeout or a zero poll interval runs a single immediate probe. */\nexport function waitelementplan(wait: { timeout: number; poll: number }): { probes: number; lastwait: number } {\n if (wait.timeout <= 0 || wait.poll <= 0) return { probes: 1, lastwait: 0 };\n const probes = Math.floor(wait.timeout / wait.poll) + 1;\n return { probes, lastwait: wait.timeout % wait.poll };\n}\n\n/** Samples one delay inside the reviewed jitter window from a seeded random source: the window spans base minus half the jitter to base plus half the jitter and never dips below zero. */\nexport function delayjitter(delay: delaystep, seed: number): number {\n if (delay.jitter <= 0) return Math.max(0, delay.base);\n const sample = seededrandom(seed);\n return Math.max(0, delay.base - delay.jitter / 2 + sample * delay.jitter);\n}\n\n/** Deterministic random source of the delay jitter so reviewed windows replay exactly during tests and audits; the seed passes an avalanche mix before the xorshift steps so nearby seeds spread across the whole window. */\nexport function seededrandom(seed: number): number {\n let state = seed >>> 0;\n state ^= state >>> 16;\n state = Math.imul(state, 0x85ebca6b);\n state ^= state >>> 13;\n state = Math.imul(state, 0xc2b2ae35);\n state ^= state >>> 16;\n state = (state >>> 0) || 1;\n state ^= state << 13; state >>>= 0;\n state ^= state >> 17;\n state ^= state << 5; state >>>= 0;\n return state / 0x100000000;\n}\n\n/** Builds one new workflow run: pending state, a zero step cursor and the optional dry run flag. */\nexport function newworkflowrun(input: { id?: string; workflowid: string; dryrun?: boolean; now: number }): workflowrun {\n return { id: input.id ?? crypto.randomUUID(), workflowid: input.workflowid, state: \"pending\", cursor: 0, startedat: input.now, ...(input.dryrun === true ? { dryrun: true } : {}) };\n}\n\n/** Pauses one running workflow run at its last checkpoint; the cursor keeps the completed steps so a resume continues exactly there. */\nexport function pauserun(run: workflowrun, now: number): workflowrun {\n if (run.state !== \"running\") throw new Error(\"Only a running workflow can pause.\");\n return { ...run, state: \"paused\", pausedat: now };\n}\n\n/** Cancels one workflow run and records the reviewed reason; done and already cancelled runs stay untouched. */\nexport function cancelrun(run: workflowrun, reason: string, now: number): workflowrun {\n if (run.state === \"done\" || run.state === \"cancelled\") return run;\n return { ...run, state: \"cancelled\", cancelreason: reason, endedat: now };\n}\n\n/** Substitutes ${name} variable references of one step field from the scopes; undefined references are refused with the variable name. */\nfunction interpolate(text: string, scopes: variablescope[]): { text: string; consumed: string[] } {\n const consumed: string[] = [];\n const resolved = text.replace(/\\$\\{([a-z][a-z0-9]*)\\}/g, (_whole, name: string) => {\n const variable = resolvevariable(scopes, name);\n if (!variable) throw new Error(`The step references the undefined variable ${name}.`);\n consumed.push(name);\n return Array.isArray(variable.value) ? variable.value.join(\",\") : String(variable.value);\n });\n return { text: resolved, consumed };\n}\n\n/** Builds the runlog entry of one finished workflow step. */\nfunction runlogof(step: workflowstep, state: runlogentry[\"state\"], startedat: number, duration: number, summary: string, extra: { block?: string; consumed?: string[]; produced?: string[]; details?: Record<string, unknown>; checkpoint?: boolean }): runlogentry {\n return { stepid: step.id, label: step.label, state, startedat, duration, summary, ...(extra.block !== undefined ? { block: extra.block } : {}), ...(extra.consumed !== undefined && extra.consumed.length > 0 ? { consumed: extra.consumed } : {}), ...(extra.produced !== undefined && extra.produced.length > 0 ? { produced: extra.produced } : {}), ...(extra.checkpoint === true ? { checkpoint: true } : {}), ...(extra.details !== undefined ? { details: extra.details } : {}) };\n}\n\n/** Executes exactly one workflow step outside the run loop: resolves the bindings of earlier steps, evaluates the inline expression and regex rule, interpolates the variable references, dispatches through the injected executor and binds the outcome into the newest scope; a control flow executor returns the merged scopes and its iteration runlog so the step adopts them before its own entry. */\nexport async function runstep(input: { step: workflowstep; scopes: variablescope[]; outputs: Record<string, stepoutcome>; execute: (step: workflowstep, context: { scopes: variablescope[]; block?: string; outputs?: Record<string, stepoutcome> }) => Promise<stepexecution>; now: number; block?: string }): Promise<{ scopes: variablescope[]; log: runlogentry; childlog?: runlogentry[]; output: stepexecution }> {\n const startedat = input.now;\n let scopes = input.scopes;\n const consumed: string[] = [];\n if (input.step.bindings) {\n const bound = bindvariables(scopes, input.step.bindings.filter(binding => input.outputs[binding.stepid] !== undefined), input.outputs, input.now);\n scopes = bound.scopes;\n }\n let produced: string[] = [];\n try {\n if (input.step.expression) {\n const value = expressioneval(input.step.expression, scopes);\n scopes = setvariable(scopes, input.step.expression.result, input.step.expression.resultkind, coercevariable(value, input.step.expression.resultkind), input.now);\n produced = [...produced, input.step.expression.result];\n }\n let stepvalue = input.step.value;\n if (input.step.extract) {\n const text = stepvalue ?? \"\";\n const interpolated = interpolate(text, scopes);\n consumed.push(...interpolated.consumed);\n const extraction = regexextract(input.step.extract, interpolated.text, input.now);\n if (extraction.matched) {\n for (const variable of extraction.variables) scopes = setvariable(scopes, variable.name, \"string\", variable.value, input.now);\n produced = [...produced, ...extraction.variables.map(variable => variable.name)];\n }\n stepvalue = interpolated.text;\n }\n // Control flow steps skip interpolation: the control engine owns variable rebinding inside its payload (the item and index variables of every iteration), so it dispatches the reviewed payload unchanged and interpolates the child steps itself once the iteration scopes are bound.\n const controlled = iscontrolflowkind(input.step.kind);\n const target = !controlled && input.step.target !== undefined ? interpolate(input.step.target, scopes) : undefined;\n if (target) consumed.push(...target.consumed);\n const value = !controlled && stepvalue !== undefined ? interpolate(stepvalue, scopes) : undefined;\n if (value) consumed.push(...value.consumed);\n const options = !controlled && input.step.options !== undefined ? interpolate(input.step.options, scopes) : undefined;\n if (options) consumed.push(...options.consumed);\n const dispatchable: workflowstep = { ...input.step, ...(target !== undefined ? { target: target.text } : {}), ...(value !== undefined ? { value: value.text } : {}), ...(options !== undefined ? { options: options.text } : {}) };\n const output = await input.execute(dispatchable, { scopes, outputs: input.outputs, ...(input.block !== undefined ? { block: input.block } : {}) });\n if (output.scopes !== undefined) scopes = output.scopes;\n const childlog = output.log;\n if (input.step.bindings) {\n const bound = bindvariables(scopes, input.step.bindings, { ...input.outputs, [input.step.id]: { stepid: input.step.id, ok: output.ok, summary: output.summary, ...(output.details !== undefined ? { details: output.details } : {}), at: input.now } }, input.now);\n scopes = bound.scopes;\n produced = [...new Set([...produced, ...bound.produced])];\n }\n const duration = Date.now() - startedat;\n return { scopes, log: runlogof(input.step, output.ok ? \"done\" : \"failed\", startedat, duration, output.summary, { ...(input.block !== undefined ? { block: input.block } : {}), ...(consumed.length > 0 ? { consumed } : {}), ...(produced.length > 0 ? { produced } : {}), ...(output.details !== undefined ? { details: output.details } : {}), ...(output.ok ? { checkpoint: true } : {}) }), ...(childlog !== undefined ? { childlog } : {}), output };\n } catch (error) {\n const duration = Date.now() - startedat;\n const summary = error instanceof Error ? error.message : String(error);\n return { scopes, log: runlogof(input.step, \"failed\", startedat, duration, summary, { ...(input.block !== undefined ? { block: input.block } : {}), ...(consumed.length > 0 ? { consumed } : {}) }), output: { ok: false, summary } };\n }\n}\n\n/** Advances one workflow run one step at a time: gates the run behind the active session, the approved plan and the origin grants, opens a child scope per block region, checkpoints after every completed step and resumes a paused run from its last checkpoint. */\nexport async function runworkflow(input: { record: workflowrecord; run: workflowrun; scopes?: variablescope[]; log?: runlogentry[]; outputs?: Record<string, stepoutcome>; execute: (step: workflowstep, context: { scopes: variablescope[]; block?: string; outputs?: Record<string, stepoutcome> }) => Promise<stepexecution>; now: number; gates?: { sessionactive: boolean; planapproved: boolean; origingranted: (origin: string) => boolean }; oncheckpoint?: (state: { run: workflowrun; scopes: variablescope[]; log: runlogentry[] }) => Promise<void> | void }): Promise<{ run: workflowrun; scopes: variablescope[]; log: runlogentry[]; outputs: Record<string, stepoutcome> }> {\n if (input.gates && !input.gates.sessionactive) throw new Error(\"The workflow refuses to run outside an approved session.\");\n if (input.gates && !input.gates.planapproved) throw new Error(\"The workflow refuses to run without the approved plan review.\");\n if (input.gates) for (const origin of input.record.origins) {\n if (!input.gates.origingranted(origin)) throw new Error(`The workflow origin ${origin} falls outside the session grants.`);\n }\n if (input.run.state === \"done\" || input.run.state === \"failed\" || input.run.state === \"cancelled\") throw new Error(`The workflow run is already ${input.run.state}.`);\n const { pausedat, ...resumed } = input.run;\n void pausedat;\n let run: workflowrun = input.run.state === \"paused\" ? { ...resumed, state: \"running\" } : { ...input.run, state: \"running\" };\n let scopes = input.scopes ?? [{ name: \"root\", variables: [] }];\n const log = [...(input.log ?? [])];\n const outputs: Record<string, stepoutcome> = { ...(input.outputs ?? {}) };\n let activeblock: string | undefined;\n for (let index = run.cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n if (step.block !== undefined && step.block !== activeblock) {\n scopes = pushscope(scopes, step.block, (scopes[scopes.length - 1] as variablescope).name);\n activeblock = step.block;\n // The nested parameters of the block invocation bind into the fresh child scope before its first step runs; a default of the wrong kind fails the run honestly with the parameter name.\n if (step.params) {\n try {\n for (const param of step.params) {\n if (param.default === undefined) continue;\n scopes = setvariable(scopes, param.name, param.kind, coercevariable(param.default, param.kind), input.now);\n }\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return { run: { ...run, state: \"failed\", endedat: Date.now(), failreason: `The nested parameter of block ${step.block} failed: ${reason}` }, scopes, log, outputs };\n }\n }\n } else if (step.block === undefined && activeblock !== undefined) {\n while (scopes.length > 1) scopes = popscope(scopes);\n activeblock = undefined;\n }\n const executed = await runstep({ step, scopes, outputs, execute: input.execute, now: Date.now(), ...(step.block !== undefined ? { block: step.block } : {}) });\n scopes = executed.scopes;\n if (executed.childlog !== undefined) log.push(...executed.childlog);\n log.push(executed.log);\n outputs[step.id] = { stepid: step.id, ok: executed.output.ok, summary: executed.output.summary, ...(executed.output.details !== undefined ? { details: executed.output.details } : {}), at: Date.now() };\n if (!executed.output.ok) {\n run = { ...run, state: \"failed\", endedat: Date.now(), failreason: executed.output.summary };\n return { run, scopes, log, outputs };\n }\n run = { ...run, cursor: index + 1 };\n if (input.oncheckpoint) await input.oncheckpoint({ run, scopes, log });\n }\n run = { ...run, state: \"done\", endedat: Date.now() };\n return { run, scopes, log, outputs };\n}\n\n/** Evaluates every step of a workflow with no page mutation and no storage write: steps with a read only projection record their would be outcome and every other step is refused in the runlog. */\nexport function dryrunworkflow(input: { record: workflowrecord; run: workflowrun; scopes?: variablescope[]; log?: runlogentry[]; now: number; projection: (step: workflowstep) => string | undefined }): { run: workflowrun; scopes: variablescope[]; log: runlogentry[] } {\n const run: workflowrun = { ...input.run, state: \"running\", ...(input.run.dryrun === true ? { dryrun: true } : { dryrun: true }) };\n let scopes = input.scopes ?? [{ name: \"root\", variables: [] }];\n const log = [...(input.log ?? [])];\n for (let index = run.cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n const summary = input.projection(step);\n const entry = summary === undefined\n ? runlogof(step, \"refused\", input.now, 0, `The ${step.kind} step has no read only projection and the dry run refuses it.`, { ...(step.block !== undefined ? { block: step.block } : {}) })\n : runlogof(step, \"done\", input.now, 0, summary, { ...(step.block !== undefined ? { block: step.block } : {}) });\n log.push(entry);\n scopes = setvariable(scopes, `${step.id}outcome`, \"boolean\", entry.state === \"done\", input.now);\n }\n return { run: { ...run, state: \"done\", cursor: input.record.steps.length, endedat: input.now }, scopes, log };\n}\n\n/** One watchdog verdict of a running workflow run: the verdict, the recovery action the configuration picks and the honest reason. */\nexport type watchdogverdict = { runid: string; verdict: \"stalled\" | \"zombie\" | \"healthy\"; action: \"retry\" | \"pause\" | \"cancel\" | \"reap\" | \"none\"; reason: string; lastcompletedat?: number };\n\n/** Scans the running workflow runs for stalled steps and zombie runs: a run grades stalled when no step completed inside the configured threshold and it grades zombie when its executor is gone \u2014 a browser shutdown left it running \u2014 and the window elapsed; the recovery action stays the reviewed user configuration of retry, pause or cancel while a zombie always reaps. */\nexport function watchdogpass(input: { runs: workflowrun[]; lastcompletedat: Record<string, number>; liveexecutors: string[]; config: watchdogconfig; now: number }): watchdogverdict[] {\n const verdicts: watchdogverdict[] = [];\n for (const run of input.runs) {\n if (run.state !== \"running\") continue;\n const lastcompletedat = input.lastcompletedat[run.id] ?? run.startedat;\n const live = input.liveexecutors.includes(run.id);\n const silence = input.now - lastcompletedat;\n if (!live && input.config.zombiewindow !== undefined && silence >= input.config.zombiewindow) {\n verdicts.push({ runid: run.id, verdict: \"zombie\", action: \"reap\", reason: `The run ${run.id} lost its executor ${silence} ms ago and reaps as a zombie of a browser shutdown at its last checkpoint ${run.cursor}.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n continue;\n }\n if (!live) continue;\n if (silence >= input.config.stallthreshold) {\n const action = input.config.action;\n verdicts.push({ runid: run.id, verdict: \"stalled\", action, reason: `The run ${run.id} completed no step for ${silence} ms past the reviewed threshold and the watchdog recovers it with ${action} at cursor ${run.cursor}.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n continue;\n }\n verdicts.push({ runid: run.id, verdict: \"healthy\", action: \"none\", reason: `The run ${run.id} completed its last step ${silence} ms ago and stays healthy.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n }\n return verdicts;\n}\n", "import type { actionkind, agentplan, agentsession, attachtarget, captureexport, captureformat, capturenaming, captureoptions, cdpallowlist, cleanuprule, clientrecord, consoleconsentrecord, debuggergrant, delaystep, downloadspec, editormodel, endpointconfig, fieldkind, formprofile, locationconsent, loglevel, loglevelset, mimefilter, mcpserverconfig, observationmode, permissionstate, policyevaluation, quarantineentry, regionrect, rotationrule, runsettings, safetyverdict, siteoverride, sourcemapconsent, spamrule, steptemplate, toolcatalog, tooldef, toolstep, transformrule, waitstep, watchdogconfig, workflowrecord, workflowstep } from \"./types.js\";\nimport { domainkinds, toolnamespaces } from \"./toolcatalog.js\";\nimport { channeloptionsof, channelorigin, pollcursorof, subscriptionoptionsof } from \"./socketbus.js\";\nimport { apireplayspecof, privatemime } from \"./netwatch.js\";\nimport { blockruleof, cookiedomaingranted, cookierecordof, mockspecof, patternorigin, proxyrouteof, headeruleof } from \"./netcontrol.js\";\nimport { allowlistcovers, breakpointinputof, cdpallowlistof, cdpdomains, cdpeventruleof, methoddomain, overrideinputof, stepmodeof, teardownplanof, watchexpressionof } from \"./cdpbus.js\";\nimport { annotationof, attachtargetof, flowspecof, tracecategories } from \"./profilers.js\";\nimport { agentgrammarvalid, agentpresetof, blackboxruleof, browserpermissions, devicepresetof, familyofkind, locationconsentcovers, locationpresetof, locationrangevalid, networkpresetof, permissiongrantof, permissiongrade, permissionstates, revertplanof } from \"./emulation.js\";\nimport { autointervalof, importsessionfile, restoreplanof, searchqueryof, sessionkinds, snapshotplanof } from \"./sessions.js\";\nimport { composeworkflow, expressionof, expressionoperators, regexruleof, steptemplateof, validateworkflow, workflowblockof, workflowstepof } from \"./workflow.js\";\nimport { branchof, conditionof, controlsteps, foreachof, iscontrolflowkind, loopof, parallelof, repeatuntilof, tryof, whileof } from \"./controlflow.js\";\nimport { armrule, cronparse, triggerfamilyof, triggerpayloadof, triggereventcatalog, webhooksecretok } from \"./trigger.js\";\nimport { formpayloadof, multipartpayloadof, oauthflowof } from \"./netauth.js\";\nimport { loglevels, timelinesources } from \"./runtimeline.js\";\n\nconst sensitiveactions = new Set<actionkind>([\"click\", \"type\", \"navigate\", \"select\", \"presskey\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"reload\", \"back\", \"forward\", \"writestorage\", \"setattribute\", \"removeattribute\", \"evaluate\", \"tabcreate\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowcreate\", \"windowclose\", \"windowresize\", \"downloadfile\", \"clickpoint\", \"shiftclick\", \"dismissdialog\", \"enterframe\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"keyhold\", \"keyrelease\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"openlink\", \"openprivate\", \"reloadcache\", \"stopnav\", \"followlink\", \"spanav\", \"rewritequery\", \"setfragment\", \"navlist\", \"navprofile\", \"handleauth\", \"printpdf\", \"prefetch\", \"preconnect\", \"deeplink\", \"reopentab\", \"pausenav\", \"navrate\", \"openclipboard\", \"batchopen\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"restorelayout\", \"reopenrun\", \"badgetab\", \"fillform\", \"filllabel\", \"fillplaceholder\", \"submitform\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcard\", \"fillcode\", \"consentpassword\", \"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"streamdisk\", \"paginateextract\", \"resumeextract\", \"batchdownload\", \"pausedownload\", \"resumedownload\", \"interceptmime\", \"readclipboard\", \"writeclipboard\", \"copyscreen\", \"quarantinedownload\", \"scanvirus\", \"cleanupartifacts\", \"recordscreen\", \"captureaudio\", \"downloadimages\", \"callrest\", \"callgraphql\", \"sendmessage\", \"blockrequest\", \"mockresponse\", \"rewriteheaders\", \"setcookies\", \"clearcookies\", \"authflow\", \"saveapikey\", \"routeproxy\", \"postform\", \"postfiles\", \"attachcdp\", \"detachcdp\", \"cdpcmd\", \"overridescript\", \"heapshot\", \"profilecpu\", \"capturesourcemaps\", \"emulatedevice\", \"emulatenetwork\", \"emulatelocate\", \"setuseragent\", \"overridepermission\", \"restoresession\", \"exportsessions\", \"importsessions\", \"runworkflow\", \"visitrule\", \"urlrule\", \"menurule\", \"keyrule\", \"buttonrule\", \"cronrule\", \"intervalrule\", \"urllistrule\", \"webhookrule\", \"eventrule\"]);\nconst interactionactions = new Set<actionkind>([\"focus\", \"scroll\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"scrollpage\", \"scrollby\", \"scrollend\", \"scrolltop\", \"fullscreen\", \"zoomset\", \"movepointer\", \"clicktext\", \"clickaria\", \"clickname\", \"expanddetails\", \"pierceshadow\", \"retryaction\", \"capturebodies\", \"setbreakpoint\", \"stepcode\", \"watchexpr\", \"loop\", \"repeatuntil\", \"whileloop\", \"foreach\", \"parallel\", \"trycatch\"]);\nconst readactions = new Set<actionkind>([\"observe\", \"inspect\", \"extract\", \"wait\", \"waitfor\", \"waittext\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"readlinks\", \"readimages\", \"readmeta\", \"readforms\", \"readstorage\", \"highlight\", \"tablist\", \"windowlist\", \"tabsnapshot\", \"mapclicks\", \"verifyvisible\", \"verifyenabled\", \"resolvexpath\", \"a11ytree\", \"readvisible\", \"readertree\", \"detectlists\", \"detecttables\", \"readjson\", \"watchmutate\", \"waitquiet\", \"watchbanner\", \"detectinfinitescroll\", \"detectvirtual\", \"detectlazy\", \"readscrollpos\", \"readlang\", \"readoutline\", \"countpages\", \"listshadow\", \"listframes\", \"classifypage\", \"fingerprintsection\", \"diffsnapshots\", \"readselection\", \"watchfocus\", \"detectsticky\", \"detectscrolllock\", \"readopengraph\", \"detectlanguage\", \"deriveselector\", \"waitload\", \"waiturl\", \"spawait\", \"detecthttp\", \"readredirects\", \"readfinalurl\", \"trailaudit\", \"navintent\", \"checksafe\", \"querytabs\", \"watchtab\", \"findclones\", \"searchtabs\", \"listaudio\", \"snapshotsession\", \"savelayout\", \"attachmeta\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"readerrors\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\", \"handoffcaptcha\", \"scrapetable\", \"importcsv\", \"looprows\", \"transformvalues\", \"deduperows\", \"mergepages\", \"stamplerows\", \"previewgrid\", \"logprovenance\", \"verifydownload\", \"exportnetlog\", \"namecaptures\", \"shotview\", \"shotfullpage\", \"shotelement\", \"shotregion\", \"contactsheet\", \"capturepdf\", \"captureframe\", \"readmedia\", \"readassets\", \"probestream\", \"timelapse\", \"shotcanvas\", \"convertimage\", \"makethumbs\", \"fetchurl\", \"parsejson\", \"parsehtml\", \"opensocket\", \"waitmessage\", \"watchrequests\", \"readheaders\", \"mapapi\", \"subscribesse\", \"longpoll\", \"extractapi\", \"readcookies\", \"watchconsole\", \"watcherrors\", \"watchtasks\", \"watchcdp\", \"measureflow\", \"trackmemory\", \"watchshifts\", \"traceload\", \"annotatetrace\", \"replaytrace\", \"blackboxscripts\", \"persiststate\", \"capturesession\", \"namedsessions\", \"diffsessions\", \"searchsessions\", \"composeworkflow\", \"savetemplate\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\", \"listruns\", \"condition\", \"branch\"]);\nconst allowedactions = new Set<actionkind>([...sensitiveactions, ...interactionactions, ...readactions]);\nconst watchactions = new Set<actionkind>([\"watchmutate\", \"watchbanner\", \"watchfocus\", \"watchtab\"]);\nconst targetactions = new Set<actionkind>([\"inspect\", \"focus\", \"click\", \"type\", \"scroll\", \"select\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"highlight\", \"setattribute\", \"removeattribute\", \"waitfor\", \"shiftclick\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\", \"verifyvisible\", \"verifyenabled\", \"pierceshadow\", \"deriveselector\", \"fingerprintsection\", \"submitform\", \"retryform\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\", \"scrapetable\", \"paginateextract\", \"shotelement\", \"captureframe\", \"shotcanvas\"]);\nconst valueactions = new Set<actionkind>([\"presskey\", \"drag\", \"drop\", \"upload\", \"readattribute\", \"removeattribute\", \"waittext\", \"evaluate\", \"zoomset\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowclose\", \"windowresize\", \"tabcreate\", \"windowcreate\", \"downloadfile\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"keyhold\", \"keyrelease\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"followlink\", \"setfragment\", \"handleauth\", \"navintent\", \"openclipboard\", \"checksafe\", \"reopentab\", \"spanav\", \"duplicatetab\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"focuswindow\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"incognitowindow\", \"asksubmit\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\", \"pausedownload\", \"resumedownload\", \"verifydownload\", \"writeclipboard\", \"quarantinedownload\", \"scanvirus\"]);\nconst tabscommandactions = new Set<actionkind>([\"querytabs\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"watchtab\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"savelayout\", \"restorelayout\", \"findclones\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"listaudio\", \"reopenrun\", \"snapshotsession\"]);\nconst formactions = new Set<actionkind>([\"fillform\", \"filllabel\", \"fillplaceholder\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"submitform\", \"readerrors\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"handoffcaptcha\", \"fillcard\", \"fillcode\", \"consentpassword\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\"]);\n/** Extraction, transform, export and provenance kinds of the forms and data part two family. */\nconst datasetactions = new Set<actionkind>([\"scrapetable\", \"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"importcsv\", \"looprows\", \"transformvalues\", \"deduperows\", \"paginateextract\", \"mergepages\", \"stamplerows\", \"previewgrid\", \"streamdisk\", \"resumeextract\", \"logprovenance\"]);\n/** Export kinds that move extracted data out of local memory to disk, the clipboard or a reviewed sheet endpoint. */\nconst exportactions = new Set<actionkind>([\"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"streamdisk\"]);\n/** Files, clipboard and downloads kinds of the batch queue, interception, clipboard, quarantine, naming and cleanup family. */\nconst filesactions = new Set<actionkind>([\"batchdownload\", \"pausedownload\", \"resumedownload\", \"verifydownload\", \"interceptmime\", \"exportnetlog\", \"readclipboard\", \"writeclipboard\", \"copyscreen\", \"quarantinedownload\", \"scanvirus\", \"namecaptures\", \"cleanupartifacts\"]);\nconst captureactions = new Set<actionkind>([\"shotview\", \"shotfullpage\", \"shotelement\", \"shotregion\", \"contactsheet\"]);\n/** Media capture part two kinds of the pdf, recording, image, canvas, stream, asset, lapse, conversion and thumbnail family. */\nconst mediaactions = new Set<actionkind>([\"capturepdf\", \"recordscreen\", \"captureaudio\", \"captureframe\", \"downloadimages\", \"shotcanvas\", \"probestream\", \"readmedia\", \"readassets\", \"timelapse\", \"convertimage\", \"makethumbs\"]);\n\nconst httpactions = new Set<actionkind>([\"fetchurl\", \"parsejson\", \"parsehtml\", \"callrest\", \"callgraphql\"]);\n\nconst socketactions = new Set<actionkind>([\"opensocket\", \"sendmessage\", \"waitmessage\", \"subscribesse\", \"longpoll\"]);\n\nconst netwatchactions = new Set<actionkind>([\"watchrequests\", \"readheaders\", \"capturebodies\", \"mapapi\", \"extractapi\"]);\n\n/** Network control kinds of the 1.1.44 family: blocking, mocking, header rewriting, cookies, auth, api keys, proxy routing and uploads. */\nconst controlactions = new Set<actionkind>([\"blockrequest\", \"mockresponse\", \"rewriteheaders\", \"setcookies\", \"readcookies\", \"clearcookies\", \"authflow\", \"saveapikey\", \"routeproxy\", \"postform\", \"postfiles\"]);\n\n/** Debugging kinds of the 1.1.45 family: console, error and task watching stays read only timeline capture. */\nconst debugactions = new Set<actionkind>([\"watchconsole\", \"watcherrors\", \"watchtasks\"]);\n\n/** The devtools protocol kinds of the 1.1.46 debugging family: attach, detach, raw commands, event watches, breakpoints, stepping, watch expressions and script overrides. */\nconst cdpactions = new Set<actionkind>([\"attachcdp\", \"detachcdp\", \"cdpcmd\", \"watchcdp\", \"setbreakpoint\", \"stepcode\", \"watchexpr\", \"overridescript\"]);\n\n/** The profiling kinds of the 1.1.47 debugging part three family: flow measurement, heap snapshots, memory growth tracking, cpu profiles, layout shift watches, trace records, trace annotation, offline trace replay and source map capture. */\nconst profileractions = new Set<actionkind>([\"measureflow\", \"heapshot\", \"trackmemory\", \"profilecpu\", \"watchshifts\", \"traceload\", \"annotatetrace\", \"replaytrace\", \"capturesourcemaps\"]);\n\nconst emulationactions = new Set<actionkind>([\"emulatedevice\", \"emulatenetwork\", \"emulatelocate\", \"setuseragent\", \"overridepermission\", \"blackboxscripts\"]);\n\n/** The session memory kinds of the 1.1.49 family: task state persistence, session capture, restore, naming, diffing, search, export and import. */\nconst sessionactions = new Set<actionkind>([\"persiststate\", \"capturesession\", \"restoresession\", \"namedsessions\", \"diffsessions\", \"searchsessions\", \"exportsessions\", \"importsessions\"]);\n\n/** The workflow kinds of the 1.1.50 and 1.1.51 families: composition, templates, runs, dry runs, jittered delays, element waits, expressions, variable extraction, and the control flow family of conditionals, branching, loops, parallel branches with joins and try catch with retries and timeouts. */\nconst workflowactions = new Set<actionkind>([\"composeworkflow\", \"savetemplate\", \"runworkflow\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\", \"condition\", \"branch\", \"loop\", \"repeatuntil\", \"whileloop\", \"foreach\", \"parallel\", \"trycatch\"]);\n\n/** The trigger kinds of the 1.1.52 family: page visit, url pattern, context menu, keyboard shortcut, toolbar button, cron, interval, url list, webhook and page event rules that launch reviewed workflows; every rule arms behind the explicit arm review and grades sensitive because it launches runs automatically. */\nconst triggeractions = new Set<actionkind>([\"visitrule\", \"urlrule\", \"menurule\", \"keyrule\", \"buttonrule\", \"cronrule\", \"intervalrule\", \"urllistrule\", \"webhookrule\", \"eventrule\"]);\n\n/** Header names that carry credentials; sending any of them needs the explicit consent that names the header. */\nconst credentialheaders = new Set([\"authorization\", \"proxy-authorization\", \"cookie\", \"cookie2\", \"set-cookie\", \"api-key\", \"x-api-key\", \"x-auth-token\", \"x-session-token\", \"proxy-authorization\"]);\n/** Field kinds the form grammar accepts inside records, profiles and value rules. */\nconst fieldkinds: fieldkind[] = [\"text\", \"email\", \"phone\", \"date\", \"number\", \"select\", \"check\", \"radio\", \"file\", \"password\", \"card\", \"code\"];\nconst layoutmutationactions = new Set<actionkind>([\"grouptabs\", \"colorgroup\", \"collapsegroup\", \"savelayout\", \"restorelayout\"]);\n/** Chromium tab group colors accepted as reviewed group color choices. */\nconst groupcolors = [\"grey\", \"blue\", \"red\", \"yellow\", \"green\", \"pink\", \"purple\", \"cyan\", \"orange\"];\n\n/** Normalizes a user supplied HTTPS endpoint without preserving a provider lock-in. */\nexport function normalizeendpoint(value: string): endpointconfig {\n const endpoint = new URL(value.trim());\n if (endpoint.protocol !== \"https:\") throw new Error(\"Devthink accepts HTTPS endpoints only.\");\n if (endpoint.username || endpoint.password) throw new Error(\"Endpoint credentials are not allowed in the URL.\");\n return { endpoint: endpoint.toString(), origin: endpoint.origin, configuredat: Date.now() };\n}\n\n/** Creates the exact optional host pattern requested from Chromium. */\nexport function hostpattern(origin: string): string {\n const parsed = new URL(origin);\n if (parsed.protocol !== \"https:\") throw new Error(\"Only HTTPS origins can be granted.\");\n return `${parsed.origin}/*`;\n}\n\n/** True when the kind belongs to the session memory family of the 1.1.49 release. */\nexport function issessionkind(kind: actionkind): boolean {\n return sessionactions.has(kind);\n}\n\n/** True when the kind belongs to the workflow family of the 1.1.50 release. */\nexport function isworkflowkind(kind: actionkind): boolean {\n return workflowactions.has(kind);\n}\n\n/** True when the kind belongs to the trigger family of the 1.1.52 release: every trigger kind arms an automatic launcher and needs the explicit arm review. */\nexport function istriggeraction(kind: actionkind): boolean {\n return triggeractions.has(kind);\n}\n\n/** True when the action kind observes the page over a reviewed lifetime window. */\nexport function iswatchkind(kind: actionkind): boolean {\n return watchactions.has(kind);\n}\n\n/** True when the kind belongs to the debugging family of console, error and task watching. */\nexport function isdebugkind(kind: actionkind): boolean {\n return debugactions.has(kind);\n}\n\n/** True when the kind belongs to the devtools protocol family of attaches, raw commands, event watches, breakpoints, stepping, watch expressions and script overrides. */\nexport function iscdpkind(kind: actionkind): boolean {\n return cdpactions.has(kind);\n}\n\n/** True when the kind belongs to the profiling family of flow, heap, cpu, shift, trace and source map instruments. */\nexport function isprofilekind(kind: actionkind): boolean {\n return profileractions.has(kind);\n}\n\n/** True when the kind belongs to the emulation family of device, network, location, agent and permission layers plus blackbox trace shaping. */\nexport function isemulationkind(kind: actionkind): boolean {\n return emulationactions.has(kind);\n}\n\n/** Grades the observation mode of a kind: passive capture, watched lifetimes or diffing passes. */\nexport function observationmodeof(kind: actionkind): observationmode {\n if (watchactions.has(kind) || debugactions.has(kind) || profileractions.has(kind) && kind !== \"heapshot\" && kind !== \"replaytrace\" && kind !== \"annotatetrace\" && kind !== \"capturesourcemaps\" && kind !== \"profilecpu\" || cdpactions.has(kind) && kind === \"watchcdp\" || kind === \"waitquiet\") return \"watching\";\n if (kind === \"diffsnapshots\") return \"diffing\";\n return \"passive\";\n}\n\n/** Defines action risk from the fixed local allowlist. */\nexport function actionrisk(kind: actionkind): \"read\" | \"interaction\" | \"sensitive\" {\n if (!allowedactions.has(kind)) throw new Error(\"Unsupported browser action.\");\n if (sensitiveactions.has(kind)) return \"sensitive\";\n return interactionactions.has(kind) ? \"interaction\" : \"read\";\n}\n\n/** True when the action kind accepts a css selector target or a reviewed targetref. */\nexport function needstarget(kind: actionkind): boolean {\n return targetactions.has(kind);\n}\n\n/** Parses the reviewed JSON options of a step; malformed payloads are rejected early. */\nexport function parseoptions(step: toolstep): Record<string, unknown> {\n if (step.options === undefined) return {};\n let parsed: unknown;\n try { parsed = JSON.parse(step.options); } catch { throw new Error(\"Step options must be a JSON object.\"); }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"Step options must be a JSON object.\");\n return parsed as Record<string, unknown>;\n}\n\n/** Maps an action kind to the optional browser permission it requires, if any. */\nexport function requiredcapability(kind: actionkind): string | undefined {\n if (kind === \"tablist\") return \"tabs\";\n if (kind === \"downloadfile\") return \"downloads\";\n if (kind === \"openclipboard\") return \"clipboardRead\";\n if (kind === \"copytable\") return \"clipboardWrite\";\n if (kind === \"batchdownload\" || kind === \"pausedownload\" || kind === \"resumedownload\" || kind === \"verifydownload\" || kind === \"interceptmime\" || kind === \"quarantinedownload\" || kind === \"scanvirus\") return \"downloads\";\n if (kind === \"readclipboard\") return \"clipboardRead\";\n if (kind === \"writeclipboard\" || kind === \"copyscreen\") return \"clipboardWrite\";\n if (kind === \"downloadimages\") return \"downloads\";\n if (kind === \"authflow\") return \"tabs\";\n if (kind === \"capturesession\" || kind === \"restoresession\") return \"tabs\";\n if (kind === \"exportsessions\") return \"downloads\";\n if (kind === \"openlink\" || kind === \"openprivate\" || kind === \"navlist\" || kind === \"batchopen\" || kind === \"reopentab\" || kind === \"deeplink\") return \"tabs\";\n if (tabscommandactions.has(kind)) return \"tabs\";\n return undefined;\n}\n\n/** True when the kind commands tabs or windows beyond the active tab and needs the optional tabs capability. */\nexport function istabscommandkind(kind: actionkind): boolean {\n return tabscommandactions.has(kind);\n}\n\n/** True when the kind mutates tab groups or layouts and therefore stays inside the active session. */\nexport function islayoutkind(kind: actionkind): boolean {\n return layoutmutationactions.has(kind);\n}\n\n/** True when the kind belongs to the forms and data family. */\nexport function isformkind(kind: actionkind): boolean {\n return formactions.has(kind);\n}\n\n/** True when the kind belongs to the extraction, transform, export and provenance family. */\nexport function isdatasetkind(kind: actionkind): boolean {\n return datasetactions.has(kind);\n}\n\n/** True when the kind exports extracted data out of local memory to disk, the clipboard or a reviewed sheet endpoint. */\nexport function isexportkind(kind: actionkind): boolean {\n return exportactions.has(kind);\n}\n\n/** True when the kind belongs to the files, clipboard and downloads family. */\nexport function isfileskind(kind: actionkind): boolean {\n return filesactions.has(kind);\n}\n\n/** True when the kind belongs to the media capture family of viewport, full page, element, region and contact sheet shots. */\nexport function iscapturekind(kind: actionkind): boolean {\n return captureactions.has(kind);\n}\n\n/** Requires the active tab grant of the live session before any capture kind runs: the session tab and origin must match and the origin grant must cover the active origin. */\nexport function capturegate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** Validates one reviewed capture options payload: format inside the png, jpeg and webp set, quality bounded only by the format range, pixel ratio from one up with no code ceiling, and a known export target. */\nexport function validatecaptureoptions(value: unknown): policyevaluation {\n if (value === undefined) return { allowed: true };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"The reviewed capture options must be an object in options.capture.\" };\n const options = value as Record<string, unknown>;\n if (options.format !== undefined && options.format !== \"png\" && options.format !== \"jpeg\" && options.format !== \"webp\") return { allowed: false, reason: \"The reviewed capture format must be png, jpeg or webp.\" };\n if (options.quality !== undefined && (typeof options.quality !== \"number\" || !Number.isFinite(options.quality) || options.quality < 0 || options.quality > 100)) return { allowed: false, reason: \"The reviewed capture quality must stay between zero and one hundred; any value in that range is the user choice with no code cap.\" };\n if (options.pixelratio !== undefined && (typeof options.pixelratio !== \"number\" || !Number.isFinite(options.pixelratio) || options.pixelratio < 1)) return { allowed: false, reason: \"The reviewed pixel ratio starts at one and climbs to any user configured ceiling with no code ceiling.\" };\n if (options.annotate !== undefined && typeof options.annotate !== \"boolean\") return { allowed: false, reason: \"The reviewed capture annotation flag must be a boolean.\" };\n if (options.exporttarget !== undefined && options.exporttarget !== \"memory\" && options.exporttarget !== \"download\" && options.exporttarget !== \"clipboard\") return { allowed: false, reason: \"The reviewed capture export target must be memory, download or clipboard.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed region rectangle in css pixels; negative coordinates and non positive sizes are refused. */\nexport function validateregionrect(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed regionrect with x, y, width and height in css pixels is required in options.\" };\n const rect = value as Record<string, unknown>;\n for (const field of [\"x\", \"y\", \"width\", \"height\"]) {\n if (typeof rect[field] !== \"number\" || !Number.isFinite(rect[field] as number)) return { allowed: false, reason: `The reviewed regionrect needs a numeric ${field} in css pixels.` };\n }\n if ((rect.x as number) < 0 || (rect.y as number) < 0) return { allowed: false, reason: \"The reviewed regionrect refuses negative coordinates.\" };\n if ((rect.width as number) <= 0 || (rect.height as number) <= 0) return { allowed: false, reason: \"The reviewed regionrect needs positive width and height values.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed capture naming rule against the allowed segment set: run, step, sequence and kind flags only. */\nexport function validatecapturenaming(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed capturenaming rule with run, step, sequence and kind flags is required.\" };\n const rule = value as Record<string, unknown>;\n const segments = [\"run\", \"step\", \"sequence\", \"kind\"];\n for (const key of Object.keys(rule)) {\n if (!segments.includes(key)) return { allowed: false, reason: `The reviewed capturenaming rule refuses the unknown ${key} segment; only run, step, sequence and kind participate.` };\n }\n for (const segment of segments) {\n if (rule[segment] !== undefined && typeof rule[segment] !== \"boolean\") return { allowed: false, reason: `The reviewed capturenaming ${segment} flag must be a boolean.` };\n }\n if (!segments.some(segment => rule[segment] === true)) return { allowed: false, reason: \"The reviewed capturenaming rule needs at least one enabled segment of run, step, sequence and kind.\" };\n return { allowed: true };\n}\n\n/** Routes the capture export target: memory stays local, clipboard needs the clipboardwrite grant and disk writes only run through the reviewed download flow. */\nexport function captureexportgranted(target: captureexport | undefined): policyevaluation {\n if (target === undefined || target === \"memory\") return { allowed: true };\n if (target === \"clipboard\") return { allowed: true, reason: \"The clipboard capture export runs behind the optional clipboardwrite capability, negotiated through the permissions api before the copy.\" };\n if (target === \"download\") return { allowed: true, reason: \"The download capture export runs only through the reviewed download flow behind the optional downloads capability.\" };\n return { allowed: false, reason: \"The capture export target must be memory, download or clipboard; no other disk route exists.\" };\n}\n\n/** Keeps the stitching scroll budget inside the reviewed wait window: the settle windows of every tile must fit the reviewed wait window with no code ceiling on either side. */\nexport function stitchbudgetallowed(tiles: number, settle: number, wait: number): policyevaluation {\n if (tiles <= 0) return { allowed: false, reason: \"The stitch budget needs at least one tile.\" };\n if (settle < 0 || wait < 0) return { allowed: false, reason: \"The reviewed settle and wait windows must be zero or positive milliseconds.\" };\n if (tiles * settle > wait) return { allowed: false, reason: `The stitching scroll budget of ${tiles} tiles at ${settle} milliseconds exceeds the reviewed wait window of ${wait} milliseconds; review a wider window or a smaller settle.` };\n return { allowed: true };\n}\n\n/** Allows beforeafter state capture to wrap any existing action kind except the capture kinds themselves; pixel evidence around sensitive actions grades as reviewable evidence. */\nexport function beforeafterwrapallowed(kind: actionkind): boolean {\n return allowedactions.has(kind) && !captureactions.has(kind);\n}\n\n/** Exposes the capture retention window as a user configured choice; an absent value keeps every capture byte forever with no code ceiling. */\nexport function captureretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.captureretention;\n}\n\n/** Validates the reviewed media capture parameter grammar; pixel ratios, quality values, cell counts and retention windows stay user choices with no code ceilings. */\nfunction validatecapturegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n const optioncheck = validatecaptureoptions(options.capture);\n if (!optioncheck.allowed) return optioncheck;\n if (options.settle !== undefined && (typeof options.settle !== \"number\" || !Number.isFinite(options.settle) || options.settle < 0)) return { allowed: false, reason: \"The reviewed capture settle window must be zero or a positive number of milliseconds.\" };\n if (options.overlap !== undefined && (typeof options.overlap !== \"number\" || !Number.isInteger(options.overlap) || options.overlap < 0)) return { allowed: false, reason: \"The reviewed stitch overlap must be zero or a positive number of rows.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed capture wait window must be zero or a positive number of milliseconds.\" };\n if (options.naming !== undefined) {\n const namingcheck = validatecapturenaming(options.naming);\n if (!namingcheck.allowed) return namingcheck;\n }\n if (kind === \"shotregion\") {\n const rectcheck = validateregionrect(options.regionrect);\n if (!rectcheck.allowed) return rectcheck;\n if (options.reviewed !== true) return { allowed: false, reason: \"Every reviewed regionrect needs the explicit reviewed flag before shotregion runs.\" };\n if (options.container !== undefined && !isnonempty(options.container)) return { allowed: false, reason: \"The reviewed scrollable container selector must be a non-empty string.\" };\n if (options.steps !== undefined && (typeof options.steps !== \"number\" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: \"The reviewed container scroll steps must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"contactsheet\") {\n const elements = options.elements;\n if (!Array.isArray(elements) || elements.length === 0 || !elements.every(item => isnonempty(item))) return { allowed: false, reason: \"A reviewed non-empty list of element selectors is required in options for the contact sheet; the cell count stays the user choice.\" };\n const layout = options.sheet;\n if (layout !== undefined) {\n if (!layout || typeof layout !== \"object\" || Array.isArray(layout)) return { allowed: false, reason: \"The reviewed sheetlayout must be an object with cellsize, columns and label.\" };\n const sheet = layout as Record<string, unknown>;\n if (typeof sheet.cellsize !== \"number\" || !Number.isFinite(sheet.cellsize) || sheet.cellsize <= 0) return { allowed: false, reason: \"The reviewed contact sheet cell size must be a positive number of pixels.\" };\n if (typeof sheet.columns !== \"number\" || !Number.isInteger(sheet.columns) || sheet.columns < 1) return { allowed: false, reason: \"The reviewed contact sheet column count must be a positive integer with no code ceiling.\" };\n if (sheet.label !== undefined && sheet.label !== \"none\" && sheet.label !== \"index\" && sheet.label !== \"selector\" && sheet.label !== \"both\") return { allowed: false, reason: \"The reviewed contact sheet label style must be none, index, selector or both.\" };\n }\n }\n return { allowed: true };\n}\n\n/** Refuses any export that would leave local memory while the session origin grants do not cover the active origin. */\nexport function exportgranted(session: agentsession | undefined, origin: string): policyevaluation {\n if (!origingranted(session, origin)) return { allowed: false, reason: `The export of extracted data from ${origin} needs the session origin grants before it leaves local memory.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed fieldmatch grammar of one form field entry. */\nexport function validatefieldmatch(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed field match is required in options.\" };\n const match = value as Record<string, unknown>;\n if (match.mode !== \"label\" && match.mode !== \"placeholder\" && match.mode !== \"arialabel\" && match.mode !== \"name\") return { allowed: false, reason: \"The reviewed field match mode must be label, placeholder, arialabel or name.\" };\n const key = match.mode === \"label\" ? \"label\" : match.mode === \"placeholder\" ? \"placeholder\" : match.mode === \"arialabel\" ? \"arialabel\" : \"name\";\n if (!isnonempty(match[key])) return { allowed: false, reason: `The reviewed ${match.mode} field match needs a non-empty ${key}.` };\n return { allowed: true };\n}\n\n/** Validates a reviewed structured form record; password entries are refused because passwords need the explicit consentpassword consent. */\nexport function validateformrecord(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed form record with entries is required in options.\" };\n const record = value as Record<string, unknown>;\n if (record.form !== undefined && !isnonempty(record.form)) return { allowed: false, reason: \"The reviewed form record form selector must be a non-empty string.\" };\n if (!Array.isArray(record.entries) || record.entries.length === 0) return { allowed: false, reason: \"The reviewed form record needs a non-empty list of entries.\" };\n for (const item of record.entries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed form record entry must be an object.\" };\n const entry = item as Record<string, unknown>;\n const matchcheck = validatefieldmatch(entry.match);\n if (!matchcheck.allowed) return matchcheck;\n if (typeof entry.kind !== \"string\" || !fieldkinds.includes(entry.kind as fieldkind)) return { allowed: false, reason: \"Every reviewed form record entry needs a known field kind.\" };\n if (typeof entry.value !== \"string\") return { allowed: false, reason: \"Every reviewed form record entry needs a string value.\" };\n if (entry.kind === \"password\") return { allowed: false, reason: \"Password entries are refused inside form records; use consentpassword with a reviewed consent ref.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed valuegen grammar of a generatevalues step. */\nexport function validatevaluegen(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed valuegen rule with a field kind is required in options.\" };\n const rule = value as Record<string, unknown>;\n if (typeof rule.kind !== \"string\" || !fieldkinds.includes(rule.kind as fieldkind)) return { allowed: false, reason: \"The reviewed valuegen kind must be a known field kind.\" };\n if (rule.locale !== undefined && !isnonempty(rule.locale)) return { allowed: false, reason: \"The reviewed valuegen locale must be a non-empty string.\" };\n if (rule.seed !== undefined && (typeof rule.seed !== \"number\" || !Number.isFinite(rule.seed))) return { allowed: false, reason: \"The reviewed valuegen seed must be a finite number.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed list of label or placeholder value pairs for filllabel and fillplaceholder steps. */\nfunction validatefieldpairs(options: Record<string, unknown>, mode: \"label\" | \"placeholder\"): policyevaluation {\n const pairs = options.fields;\n if (!Array.isArray(pairs) || pairs.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of field pairs is required in options.\" };\n for (const item of pairs) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed field pair must be an object.\" };\n const pair = item as Record<string, unknown>;\n if (!isnonempty(pair[mode])) return { allowed: false, reason: `Every reviewed field pair needs a non-empty ${mode}.` };\n if (typeof pair.value !== \"string\" || !pair.value.trim()) return { allowed: false, reason: \"Every reviewed field pair needs a non-empty value.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed card segment grammar of a fillcard step. */\nfunction validatecardsegments(value: unknown): policyevaluation {\n if (!Array.isArray(value) || value.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of card segments is required in options.\" };\n for (const item of value) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed card segment must be an object.\" };\n const segment = item as Record<string, unknown>;\n const matchcheck = validatefieldmatch(segment.match);\n if (!matchcheck.allowed) return matchcheck;\n if (typeof segment.value !== \"string\" || !segment.value.trim()) return { allowed: false, reason: \"Every reviewed card segment needs a non-empty value.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed forms and data parameter grammar of the form family. */\nfunction validateformgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"fillform\" || (kind === \"saveprofiles\" && options.formrecord !== undefined)) {\n const recordcheck = validateformrecord(options.formrecord);\n if (!recordcheck.allowed) return recordcheck;\n }\n if (kind === \"filllabel\" || kind === \"fillplaceholder\") {\n const paircheck = validatefieldpairs(options, kind === \"filllabel\" ? \"label\" : \"placeholder\");\n if (!paircheck.allowed) return paircheck;\n }\n if (kind === \"generatevalues\" && options.valuegen !== undefined) {\n const rulecheck = validatevaluegen(options.valuegen);\n if (!rulecheck.allowed) return rulecheck;\n }\n if (kind === \"saveprofiles\" && !isnonempty(options.name)) return { allowed: false, reason: \"A reviewed profile name is required in options.\" };\n if (kind === \"submitform\" && !isnonempty(options.consentref)) return { allowed: false, reason: \"A reviewed consent ref of an approved asksubmit ticket is required in options.\" };\n if (kind === \"retryform\") {\n const backoff = options.backoff;\n if (!backoff || typeof backoff !== \"object\" || Array.isArray(backoff)) return { allowed: false, reason: \"A reviewed backoff rule with wait and factor is required in options.\" };\n const rule = backoff as Record<string, unknown>;\n if (typeof rule.wait !== \"number\" || !Number.isFinite(rule.wait) || rule.wait <= 0) return { allowed: false, reason: \"The reviewed retry backoff wait must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof rule.factor !== \"number\" || !Number.isFinite(rule.factor) || rule.factor < 1) return { allowed: false, reason: \"The reviewed retry backoff factor must be one or greater with no code ceiling.\" };\n if (options.attempts !== undefined && (typeof options.attempts !== \"number\" || !Number.isInteger(options.attempts) || options.attempts < 1)) return { allowed: false, reason: \"The reviewed retry attempts must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"runwizard\" && options.steps !== undefined && (typeof options.steps !== \"number\" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: \"The reviewed wizard step count must be a positive integer with no code ceiling.\" };\n if (kind === \"selectchain\") {\n if (!isnonempty(options.child)) return { allowed: false, reason: \"A reviewed child selector of the dependent control is required in options.\" };\n if (!nonnegativeoption(options, \"wait\")) return { allowed: false, reason: \"The reviewed dependent wait must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"picktypeahead\") {\n if (!isnonempty(options.pick)) return { allowed: false, reason: \"A reviewed suggestion entry to pick is required in options.\" };\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The reviewed typeahead timeout must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"pickdate\" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed date must use the yyyy-mm-dd form.\" };\n if (kind === \"fillcard\") {\n const segmentcheck = validatecardsegments(options.segments);\n if (!segmentcheck.allowed) return segmentcheck;\n if (!nonnegativeoption(options, \"pause\")) return { allowed: false, reason: \"The reviewed card typing pause must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"fillcode\" && !isnonempty(options.source)) return { allowed: false, reason: \"A reviewed one time code source is required in options.\" };\n if (kind === \"consentpassword\" && !isnonempty(options.consentref)) return { allowed: false, reason: \"A reviewed consent ref is required in options before any password is filled.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed transform rule: a supported expression, source columns and a target column. */\nexport function validatetransformrule(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed transform rule with an expression, sources and a target is required in options.\" };\n const rule = value as Record<string, unknown>;\n const expression = rule.expression;\n if (typeof expression !== \"string\" || !/^(trim|upper|lower|number|prefix|suffix|replace)(?::.+)?$/.test(expression)) return { allowed: false, reason: \"The reviewed transform expression must be trim, upper, lower, number, prefix, suffix or replace with an optional argument.\" };\n if (expression.startsWith(\"replace\") && !expression.slice(\"replace\".length).includes(\"=>\")) return { allowed: false, reason: \"The reviewed replace expression needs the from=>to separator.\" };\n if (expression.startsWith(\"replace\") && expression.slice(\"replace:\".length).split(\"=>\")[0] === \"\") return { allowed: false, reason: \"The reviewed replace expression needs a non-empty from part.\" };\n if (!Array.isArray(rule.sources) || rule.sources.length === 0 || !rule.sources.every(source => isnonempty(source))) return { allowed: false, reason: \"Every reviewed transform rule needs a non-empty list of source columns.\" };\n if (!isnonempty(rule.target)) return { allowed: false, reason: \"Every reviewed transform rule needs a non-empty target column.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed dataset id list in options. */\nfunction validatedatasetids(options: Record<string, unknown>, key: string): policyevaluation {\n const ids = options[key];\n if (!Array.isArray(ids) || ids.length === 0 || !ids.every(id => isnonempty(id))) return { allowed: false, reason: `A reviewed non-empty list of dataset ids is required in options as ${key}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed extraction, transform, export and provenance parameter grammar of the data family. */\nfunction validatedatagrammar(step: toolstep, options: Record<string, unknown>, origin: string): policyevaluation {\n const kind = step.kind;\n if (kind === \"scrapetable\") {\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed dataset name must be a non-empty string.\" };\n if (options.rowlimit !== undefined && (typeof options.rowlimit !== \"number\" || !Number.isInteger(options.rowlimit) || options.rowlimit < 1)) return { allowed: false, reason: \"The reviewed row limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"paginateextract\") {\n if (!isnonempty(options.next)) return { allowed: false, reason: \"A reviewed next control selector is required in options.\" };\n if (options.pages !== undefined && (typeof options.pages !== \"number\" || !Number.isInteger(options.pages) || options.pages < 1)) return { allowed: false, reason: \"The reviewed page count must be a positive integer with no code ceiling.\" };\n if (!nonnegativeoption(options, \"wait\")) return { allowed: false, reason: \"The reviewed row freshness wait must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"exportcsv\" || kind === \"exportjson\" || kind === \"exportexcel\" || kind === \"copytable\" || kind === \"streamdisk\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed artifact name must be a non-empty string.\" };\n }\n if (kind === \"exportcsv\" && options.delimiter !== undefined && (typeof options.delimiter !== \"string\" || options.delimiter.length !== 1)) return { allowed: false, reason: \"The reviewed csv delimiter must be a single character.\" };\n if (kind === \"streamdisk\" && (typeof options.chunk !== \"number\" || !Number.isInteger(options.chunk) || options.chunk < 1)) return { allowed: false, reason: \"The reviewed streaming chunk size must be a positive integer with no code ceiling.\" };\n if (kind === \"pushsheets\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (!isnonempty(options.sheet)) return { allowed: false, reason: \"A reviewed sheet endpoint url is required in options.\" };\n if (!ishttpsurl(options.sheet)) return { allowed: false, reason: \"The reviewed sheet endpoint url must use HTTPS.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The sheet push needs the explicit reviewed flag before any data leaves local memory.\" };\n }\n if (kind === \"importcsv\") {\n if (typeof options.csv !== \"string\" || !options.csv.trim()) return { allowed: false, reason: \"Reviewed csv content is required in options.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed dataset name must be a non-empty string.\" };\n if (options.mapping !== undefined) {\n const mapping = options.mapping;\n if (!mapping || typeof mapping !== \"object\" || Array.isArray(mapping) || !Object.values(mapping).every(item => typeof item === \"string\")) return { allowed: false, reason: \"The reviewed csv column mapping must be an object of string values.\" };\n }\n }\n if (kind === \"looprows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.variable !== undefined && !isnonempty(options.variable)) return { allowed: false, reason: \"The reviewed row variable name must be a non-empty string.\" };\n const inner = validateinnerstep(options, origin);\n if (!inner.allowed) return inner;\n }\n if (kind === \"transformvalues\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of transform rules is required in options.\" };\n for (const item of rules) {\n const rulecheck = validatetransformrule(item);\n if (!rulecheck.allowed) return rulecheck;\n }\n }\n if (kind === \"deduperows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n const keys = options.keys;\n if (!Array.isArray(keys) || keys.length === 0 || !keys.every(key => isnonempty(key))) return { allowed: false, reason: \"A reviewed non-empty list of dedupe column keys is required in options.\" };\n }\n if (kind === \"mergepages\") {\n const listcheck = validatedatasetids(options, \"datasets\");\n if (!listcheck.allowed) return listcheck;\n }\n if (kind === \"stamplerows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.url !== undefined && !ishttpsurl(options.url)) return { allowed: false, reason: \"The reviewed source url must use HTTPS.\" };\n }\n if (kind === \"previewgrid\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.sample !== undefined && (typeof options.sample !== \"number\" || !Number.isInteger(options.sample) || options.sample < 1)) return { allowed: false, reason: \"The reviewed sample row count must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"resumeextract\" && !isnonempty(options.session)) return { allowed: false, reason: \"A reviewed extract session id is required in options.\" };\n if (kind === \"logprovenance\" && !isnonempty(options.artifact)) return { allowed: false, reason: \"A reviewed artifact id or name is required in options.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed batch download specification: a non-empty HTTPS url list, an optional filename rule and an optional completion criterion. */\nexport function validatedownloadspec(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed downloadspec with a url list is required in options.\" };\n const spec = value as Record<string, unknown>;\n if (!Array.isArray(spec.urls) || spec.urls.length === 0 || !spec.urls.every(url => ishttpsurl(url))) return { allowed: false, reason: \"The reviewed downloadspec needs a non-empty list of HTTPS urls.\" };\n if (spec.filename !== undefined && !isnonempty(spec.filename)) return { allowed: false, reason: \"The reviewed downloadspec filename rule must be a non-empty string.\" };\n if (spec.complete !== undefined && spec.complete !== \"size\" && spec.complete !== \"checksum\") return { allowed: false, reason: \"The reviewed downloadspec completion criterion must be size or checksum.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed mime interception filter: include and exclude patterns plus the deny default for unlisted mime types. */\nexport function validatemimefilter(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed mimefilter with include and exclude patterns is required in options.\" };\n const filter = value as Record<string, unknown>;\n if (!Array.isArray(filter.include) || filter.include.length === 0 || !filter.include.every(pattern => isnonempty(pattern))) return { allowed: false, reason: \"The reviewed mimefilter needs a non-empty list of include patterns.\" };\n if (filter.exclude !== undefined && (!Array.isArray(filter.exclude) || !filter.exclude.every(pattern => isnonempty(pattern)))) return { allowed: false, reason: \"The reviewed mimefilter exclude patterns must be a list of non-empty strings.\" };\n if (filter.default !== \"deny\" && filter.default !== \"allow\") return { allowed: false, reason: \"The reviewed mimefilter needs the deny or allow default for unlisted mime types.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed cleanup rule: a positive age window with no code ceiling, an artifact kind and a keep policy. */\nexport function validatecleanuprule(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed cleanuprule with an age, a kind and a keep policy is required.\" };\n const rule = value as Record<string, unknown>;\n if (typeof rule.age !== \"number\" || !Number.isFinite(rule.age) || rule.age <= 0) return { allowed: false, reason: \"The reviewed cleanup age window must be a positive number of milliseconds with no code ceiling.\" };\n if (!isnonempty(rule.kind)) return { allowed: false, reason: \"The reviewed cleanup rule needs a non-empty artifact kind, or any to match every kind.\" };\n if (rule.keep !== \"none\" && rule.keep !== \"latest\" && rule.keep !== \"all\") return { allowed: false, reason: \"The reviewed cleanup keep policy must be none, latest or all.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed files, clipboard and downloads parameter grammar; batch sizes, concurrent windows and cleanup ages stay user configured with no code ceilings. */\nfunction validatefilesgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"batchdownload\") {\n const speccheck = validatedownloadspec(options.downloadspec);\n if (!speccheck.allowed) return speccheck;\n if (options.concurrent !== undefined && (typeof options.concurrent !== \"number\" || !Number.isInteger(options.concurrent) || options.concurrent < 1)) return { allowed: false, reason: \"The reviewed concurrent download window must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"pausedownload\" || kind === \"resumedownload\" || kind === \"verifydownload\" || kind === \"quarantinedownload\" || kind === \"scanvirus\") {\n if (!isnonempty(step.value)) return { allowed: false, reason: \"A reviewed download or quarantine reference is required.\" };\n if (kind === \"verifydownload\") {\n if (options.checksum !== undefined && !isnonempty(options.checksum)) return { allowed: false, reason: \"The reviewed expected checksum must be a non-empty string.\" };\n if (options.bytes !== undefined && (typeof options.bytes !== \"number\" || !Number.isFinite(options.bytes) || options.bytes < 0)) return { allowed: false, reason: \"The reviewed expected size must be zero or a positive number of bytes.\" };\n }\n if (kind === \"scanvirus\" && options.scanner !== undefined && !isnonempty(options.scanner)) return { allowed: false, reason: \"The reviewed scanner name must be a non-empty string.\" };\n if (kind === \"quarantinedownload\" && options.reason !== undefined && !isnonempty(options.reason)) return { allowed: false, reason: \"The reviewed quarantine reason must be a non-empty string.\" };\n }\n if (kind === \"interceptmime\") {\n const filtercheck = validatemimefilter(options.mimefilter);\n if (!filtercheck.allowed) return filtercheck;\n }\n if (kind === \"readclipboard\") {\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"A clipboard read requires a reviewed consent ref of an approved consent prompt in options.\" };\n if (options.prompt !== undefined && !isnonempty(options.prompt)) return { allowed: false, reason: \"The reviewed clipboard consent prompt must be a non-empty string.\" };\n }\n if (kind === \"exportnetlog\" && options.stepid !== undefined && !isnonempty(options.stepid)) return { allowed: false, reason: \"The reviewed netlog step filter must be a non-empty step id.\" };\n if (kind === \"namecaptures\") {\n if (!isnonempty(options.task)) return { allowed: false, reason: \"A reviewed task id is required in options for capture naming.\" };\n if (options.steps !== undefined && (!Array.isArray(options.steps) || options.steps.length === 0 || !options.steps.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed capture steps must be a non-empty list of step ids when present.\" };\n if (options.extension !== undefined && !isnonempty(options.extension)) return { allowed: false, reason: \"The reviewed capture extension must be a non-empty string.\" };\n }\n if (kind === \"cleanupartifacts\" && options.rules !== undefined) {\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"The reviewed cleanup rules must be a non-empty list when present.\" };\n for (const item of rules) {\n const rulecheck = validatecleanuprule(item);\n if (!rulecheck.allowed) return rulecheck;\n }\n }\n return { allowed: true };\n}\n\n/** Requires an approved consent prompt before any clipboard read; every read consumes its own prompt. */\nexport function clipboardconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A clipboard read requires a reviewed consent ref in options.\" };\n return { allowed: true };\n}\n\n/** Refuses to release any quarantined file before a clean scan verdict exists. */\nexport function quarantinereleasegranted(entry: quarantineentry): policyevaluation {\n if (entry.scan !== \"clean\") return { allowed: false, reason: `The quarantined file ${entry.path} cannot leave quarantine with the ${entry.scan} scan verdict; only a clean verdict releases it.` };\n return { allowed: true };\n}\n\n/** Refuses downloads and download interception that fall outside the session origin grants. */\nexport function downloadgranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed download URL is invalid.\" }; }\n if (!origingranted(session, origin)) return { allowed: false, reason: `The download from ${origin} leaves the session origin grants and needs a session grant first.` };\n return { allowed: true };\n}\n\n/** Masks a clipboard payload for every log line; the full text never persists anywhere. */\nexport function maskclipboard(payload: string): string {\n return `[clipboard payload of ${payload.length} character${payload.length === 1 ? \"\" : \"s\"}]`;\n}\n\n/** Requires an asksubmit review step before every form submission step. */\nexport function submitreviewgranted(steps: toolstep[], submitid: string): policyevaluation {\n const position = steps.findIndex(candidate => candidate.id === submitid);\n const asked = steps.some((candidate, index) => candidate.kind === \"asksubmit\" && (position === -1 || index < position));\n return asked ? { allowed: true } : { allowed: false, reason: \"Form submission requires an asksubmit review step before it.\" };\n}\n\n/** Requires a reviewed consent ref before any password field is filled. */\nexport function passwordconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A password fill requires a reviewed consent ref in options.\" };\n return { allowed: true };\n}\n\n/** True when a numeric value passes the Luhn checksum used by card networks. */\nfunction luhnvalid(digits: string): boolean {\n let sum = 0;\n let double = false;\n for (let index = digits.length - 1; index >= 0; index -= 1) {\n let value = Number.parseInt(digits[index] ?? \"\", 10);\n if (!Number.isFinite(value)) return false;\n if (double) { value *= 2; if (value > 9) value -= 9; }\n sum += value;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Refuses generated values that look like real card numbers or personal identifiers; test prefixed card values stay allowed. */\nexport function generatedvalueallowed(value: string): policyevaluation {\n const compact = value.replace(/[\\s-]/g, \"\");\n if (/^\\d{13,19}$/.test(compact) && luhnvalid(compact) && !compact.startsWith(\"4111\")) return { allowed: false, reason: \"The generated value looks like a real card number and is refused; generated card values use the 4111 test prefix.\" };\n if (/^\\d{3}-\\d{2}-\\d{4}$/.test(value.trim())) return { allowed: false, reason: \"The generated value looks like a personal identifier and is refused.\" };\n return { allowed: true };\n}\n\n/** Requires the origin grants of a saved profile to cover the origin before its values fill a page. */\nexport function profilegrantgranted(profile: formprofile, origin: string): policyevaluation {\n if (!profile.grants.includes(origin)) return { allowed: false, reason: `The saved profile ${profile.name} is not granted to ${origin}; add the origin to the profile grants first.` };\n return { allowed: true };\n}\n\n/** Restricts group and layout mutations to the active session: they refuse without a live session. */\nexport function layoutmutationgranted(session: agentsession | undefined, now: number): policyevaluation {\n if (!session || session.stoppedat || session.expiresat <= now) return { allowed: false, reason: \"Group and layout mutations stay inside the active session.\" };\n return { allowed: true };\n}\n\n/** Requires explicit review before closing a window that holds more than one task tab. */\nexport function windowclosegate(tasktabcount: number, reviewed: boolean): policyevaluation {\n if (tasktabcount > 1 && !reviewed) return { allowed: false, reason: `The window holds ${tasktabcount} task tabs and needs explicit review before it closes.` };\n return { allowed: true };\n}\n\n/** Reads the user configured concurrent task tab ceiling; an absent value never refuses a tab. */\nexport function tasktabceiling(settings: runsettings | undefined): number | undefined {\n const ceiling = settings?.tasktabceiling;\n return typeof ceiling === \"number\" && Number.isFinite(ceiling) && ceiling >= 0 ? ceiling : undefined;\n}\n\n/** Parses the reviewed wait duration of a wait step with no upper bound. */\nexport function waitduration(step: toolstep): number {\n const requested = step.value ? Number.parseInt(step.value, 10) : 250;\n if (!Number.isFinite(requested) || requested < 0) throw new Error(\"Wait duration must be zero or a positive number of milliseconds.\");\n return requested;\n}\n\nfunction isnumericid(value: unknown): value is string {\n return typeof value === \"string\" && /^\\d+$/.test(value);\n}\n\nfunction numericoption(options: Record<string, unknown>, key: string): boolean {\n return options[key] === undefined || (typeof options[key] === \"number\" && Number.isFinite(options[key] as number));\n}\n\n/** True when an optional numeric option is absent or a finite number of zero or more. */\nfunction nonnegativeoption(options: Record<string, unknown>, key: string): boolean {\n return numericoption(options, key) && !(typeof options[key] === \"number\" && (options[key] as number) < 0);\n}\n\nfunction isnonempty(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nfunction ispoint(value: unknown): boolean {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const point = value as Record<string, unknown>;\n return typeof point.x === \"number\" && Number.isFinite(point.x) && typeof point.y === \"number\" && Number.isFinite(point.y);\n}\n\n/** Grades a resolution match count: zero is absent, one is resolved and more than one is refused as ambiguous. */\nexport function resolutionverdict(count: number): \"absent\" | \"resolved\" | \"ambiguous\" {\n if (!Number.isFinite(count) || count <= 0) return \"absent\";\n return count === 1 ? \"resolved\" : \"ambiguous\";\n}\n\n/** Validates the reviewed targetref grammar of every resolution mode and rejects empty references. */\nexport function validatetargetref(reference: unknown): policyevaluation {\n if (!reference || typeof reference !== \"object\" || Array.isArray(reference)) return { allowed: false, reason: \"The reviewed target reference must be an object.\" };\n const ref = reference as Record<string, unknown>;\n if (ref.mode === \"selector\") return isnonempty(ref.selector) ? { allowed: true } : { allowed: false, reason: \"The selector target reference needs a non-empty selector.\" };\n if (ref.mode === \"text\") return isnonempty(ref.text) ? { allowed: true } : { allowed: false, reason: \"The text target reference needs non-empty text.\" };\n if (ref.mode === \"aria\") {\n if (!isnonempty(ref.role)) return { allowed: false, reason: \"The aria target reference needs a non-empty role.\" };\n return isnonempty(ref.name) ? { allowed: true } : { allowed: false, reason: \"The aria target reference needs a non-empty name.\" };\n }\n if (ref.mode === \"name\") return isnonempty(ref.name) ? { allowed: true } : { allowed: false, reason: \"The name target reference needs a non-empty name.\" };\n if (ref.mode === \"xpath\") return isnonempty(ref.xpath) ? { allowed: true } : { allowed: false, reason: \"The xpath target reference needs a non-empty expression.\" };\n if (ref.mode === \"index\") {\n const index = ref.index;\n return typeof index === \"number\" && Number.isInteger(index) && index >= 1 ? { allowed: true } : { allowed: false, reason: \"The index target reference needs a positive integer map number.\" };\n }\n if (ref.mode === \"point\") {\n const pointok = typeof ref.x === \"number\" && Number.isFinite(ref.x) && typeof ref.y === \"number\" && Number.isFinite(ref.y);\n return pointok ? { allowed: true } : { allowed: false, reason: \"The point target reference needs numeric x and y coordinates.\" };\n }\n return { allowed: false, reason: \"The target reference mode must be selector, text, aria, name, xpath, index or point.\" };\n}\n\n/** True when the session origin grants cover the given origin; a session without grants only allows its own origin. */\nexport function origingranted(session: agentsession | undefined, origin: string): boolean {\n if (!session) return false;\n const grants = session.grants ?? [session.origin];\n return grants.includes(origin);\n}\n\n/** Decides whether an unreviewed origin may open: the session grants cover it or a safe checksafe verdict vouches for it. */\nexport function originverified(url: string, grants: string[], verdicts: safetyverdict[]): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed navigation URL is invalid.\" }; }\n if (grants.includes(origin)) return { allowed: true };\n const covered = verdicts.find(verdict => verdict.safe && (verdict.url === url || (safeorigin(verdict.url) === origin)));\n if (covered) return { allowed: true };\n return { allowed: false, reason: `The origin ${origin} is outside the session grants and has no safe checksafe verdict; run checksafe and review it first.` };\n}\n\nfunction safeorigin(url: string): string {\n try { return new URL(url).origin; } catch { return \"\"; }\n}\n\n/** Refuses navigation that would move a granted task tab outside the session origin grants until the user consents. */\nexport function navigationgranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed navigation URL is invalid.\" }; }\n if (origingranted(session, origin)) return { allowed: true };\n return { allowed: false, reason: `Navigation to ${origin} leaves the task tab origins and needs the user consent of a session grant first.` };\n}\n\n/** Validates the reviewed inner step of a retry or frame wrapper against the same rules as a top-level step. */\nfunction validateinnerstep(options: Record<string, unknown>, origin: string): policyevaluation {\n const stepid = options.stepid;\n const kind = options.kind;\n if (isnonempty(stepid)) {\n if (kind !== undefined) return { allowed: false, reason: \"The reviewed wrapper must reference a step id or an inline step, not both.\" };\n return { allowed: true };\n }\n if (typeof kind !== \"string\" || !kind.trim()) return { allowed: false, reason: \"A reviewed step id or inline step kind is required in options.\" };\n if (kind === \"retryaction\" || kind === \"enterframe\" || kind === \"looprows\") return { allowed: false, reason: \"The reviewed inner step cannot be another wrapper kind.\" };\n if (!allowedactions.has(kind as actionkind)) return { allowed: false, reason: \"The reviewed inner step kind is unsupported.\" };\n const inneroptions = options.options;\n if (inneroptions !== undefined && (!inneroptions || typeof inneroptions !== \"object\" || Array.isArray(inneroptions))) return { allowed: false, reason: \"The reviewed inner step options must be an object.\" };\n const inner: toolstep = {\n id: \"inner\",\n kind: kind as actionkind,\n summary: \"Reviewed inner step.\",\n risk: actionrisk(kind as actionkind),\n ...(isnonempty(options.target) ? { target: options.target } : {}),\n ...(isnonempty(options.value) ? { value: options.value } : {}),\n ...(inneroptions !== undefined ? { options: JSON.stringify(inneroptions) } : {}),\n };\n return validatestep(inner, origin);\n}\n\n/** True when a reviewed https url parses. */\nfunction ishttpsurl(value: unknown): value is string {\n if (typeof value !== \"string\" || !value.trim()) return false;\n try { return new URL(value).protocol === \"https:\"; } catch { return false; }\n}\n\n/** Validates the reviewed navtarget grammar of a navigation step. */\nfunction validatenavtarget(value: unknown, kind: string): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed navtarget with a url is required in options.\" };\n const target = value as Record<string, unknown>;\n if (!ishttpsurl(target.url)) return { allowed: false, reason: \"The reviewed navtarget url must use HTTPS.\" };\n const container = target.container ?? \"tab\";\n if (container !== \"current\" && container !== \"tab\" && container !== \"window\" && container !== \"private\") return { allowed: false, reason: \"The reviewed navtarget container must be current, tab, window or private.\" };\n if (target.position !== undefined && target.position !== \"adjacent\" && target.position !== \"end\") return { allowed: false, reason: \"The reviewed navtarget position must be adjacent or end.\" };\n if (kind === \"openprivate\" && container !== \"private\") return { allowed: false, reason: \"The openprivate step requires the private container.\" };\n if (kind === \"openlink\" && container === \"private\") return { allowed: false, reason: \"The openlink step cannot open the private container; use openprivate.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed waitprofile grammar with its load signals, thresholds and per origin overrides. */\nfunction validatewaitprofile(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed waitprofile with load signals is required in options.\" };\n const profile = value as Record<string, unknown>;\n if (!Array.isArray(profile.signals) || profile.signals.length === 0 || !profile.signals.every(signal => isnonempty(signal))) return { allowed: false, reason: \"The reviewed waitprofile needs a non-empty list of load signals.\" };\n if (!nonnegativeoption(profile, \"idle\")) return { allowed: false, reason: \"The reviewed waitprofile idle threshold must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(profile, \"timeout\")) return { allowed: false, reason: \"The reviewed waitprofile timeout must be zero or a positive number of milliseconds.\" };\n if (profile.overrides !== undefined) {\n if (!Array.isArray(profile.overrides) || profile.overrides.length === 0) return { allowed: false, reason: \"The reviewed waitprofile overrides must be a non-empty list when present.\" };\n for (const entry of profile.overrides) {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) return { allowed: false, reason: \"Every reviewed waitprofile override must be an object with an origin.\" };\n const override = entry as Record<string, unknown>;\n if (!ishttpsurl(override.origin)) return { allowed: false, reason: \"Every reviewed waitprofile override origin must use HTTPS.\" };\n if (override.signals !== undefined && (!Array.isArray(override.signals) || !override.signals.every(signal => isnonempty(signal)))) return { allowed: false, reason: \"The reviewed waitprofile override signals must be a list of non-empty strings.\" };\n if (!nonnegativeoption(override, \"idle\") || !nonnegativeoption(override, \"timeout\")) return { allowed: false, reason: \"The reviewed waitprofile override thresholds must be zero or positive numbers.\" };\n }\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed urlpattern grammar with its match mode plus query and fragment parts. */\nexport function validateurlpattern(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed urlpattern is required in options.\" };\n const pattern = value as Record<string, unknown>;\n if (pattern.mode !== \"exact\" && pattern.mode !== \"prefix\" && pattern.mode !== \"host\" && pattern.mode !== \"pattern\") return { allowed: false, reason: \"The reviewed urlpattern mode must be exact, prefix, host or pattern.\" };\n if (!ishttpsurl(pattern.url)) return { allowed: false, reason: \"The reviewed urlpattern url must use HTTPS.\" };\n if (pattern.query !== undefined) {\n if (!pattern.query || typeof pattern.query !== \"object\" || Array.isArray(pattern.query)) return { allowed: false, reason: \"The reviewed urlpattern query part must be an object of parameter names and values.\" };\n for (const item of Object.values(pattern.query)) if (typeof item !== \"string\") return { allowed: false, reason: \"The reviewed urlpattern query values must be strings.\" };\n }\n if (pattern.fragment !== undefined && !isnonempty(pattern.fragment)) return { allowed: false, reason: \"The reviewed urlpattern fragment must be a non-empty string.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed non-empty list of HTTPS urls in options. */\nfunction validateurllist(options: Record<string, unknown>, key: string): policyevaluation {\n const urls = options[key];\n if (!Array.isArray(urls) || urls.length === 0 || !urls.every(url => ishttpsurl(url))) return { allowed: false, reason: `A reviewed non-empty list of HTTPS urls is required in options as ${key}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed ratelimit grammar of a navrate step; the window and ceiling stay user configured with no hardcoded cap. */\nfunction validateratelimit(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed ratelimit with a window and a ceiling is required in options.\" };\n const limit = value as Record<string, unknown>;\n if (limit.domain !== undefined && !isnonempty(limit.domain)) return { allowed: false, reason: \"The reviewed ratelimit domain must be a non-empty string.\" };\n if (typeof limit.window !== \"number\" || !Number.isFinite(limit.window) || limit.window <= 0) return { allowed: false, reason: \"The reviewed ratelimit window must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof limit.ceiling !== \"number\" || !Number.isInteger(limit.ceiling) || limit.ceiling < 1) return { allowed: false, reason: \"The reviewed ratelimit ceiling must be a positive integer with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed tabquery grammar with url, title, id and pattern matchers; at least one matcher is required. */\nexport function validatetabquery(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed tabquery with at least one matcher is required in options.\" };\n const query = value as Record<string, unknown>;\n const hasmatcher = query.url !== undefined || query.title !== undefined || query.id !== undefined || query.pattern !== undefined;\n if (!hasmatcher) return { allowed: false, reason: \"The reviewed tabquery needs a url, title, id or pattern matcher.\" };\n if (query.url !== undefined && !isnonempty(query.url)) return { allowed: false, reason: \"The reviewed tabquery url matcher must be a non-empty string.\" };\n if (query.title !== undefined && !isnonempty(query.title)) return { allowed: false, reason: \"The reviewed tabquery title matcher must be a non-empty string.\" };\n if (query.pattern !== undefined && !isnonempty(query.pattern)) return { allowed: false, reason: \"The reviewed tabquery pattern matcher must be a non-empty string.\" };\n if (query.id !== undefined && (typeof query.id !== \"number\" || !Number.isInteger(query.id) || query.id < 0)) return { allowed: false, reason: \"The reviewed tabquery id matcher must be a non-negative integer tab id.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed group color choice against the Chromium tab group palette. */\nfunction validategroupcolor(value: unknown): boolean {\n return typeof value === \"string\" && (groupcolors as string[]).includes(value);\n}\n\n/** Validates a reviewed list of numeric browser ids in options. */\nfunction validateidlist(options: Record<string, unknown>, key: string): boolean {\n const ids = options[key];\n return Array.isArray(ids) && ids.length > 0 && ids.every(id => typeof id === \"number\" && Number.isInteger(id) && id >= 0);\n}\n\n/** Validates the reviewed tab and window parameter grammar of the tabs and windows command family. */\nfunction validatetabsgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"querytabs\" || kind === \"closepattern\") {\n const querycheck = validatetabquery(options.tabquery);\n if (!querycheck.allowed) return querycheck;\n if (kind === \"closepattern\" && options.reviewed !== true) return { allowed: false, reason: \"The close pattern needs the explicit reviewed flag before any tab closes.\" };\n }\n if (kind === \"duplicatetab\" || kind === \"pintab\" || kind === \"mutetab\" || kind === \"movetab\" || kind === \"movetabwindow\" || kind === \"badgetab\" || kind === \"attachmeta\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser tab id is required.\" };\n }\n if (kind === \"focuswindow\" || kind === \"maximizewindow\" || kind === \"minimizewindow\" || kind === \"restorewindow\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser window id is required.\" };\n }\n if (kind === \"pintab\" && typeof options.pinned !== \"boolean\") return { allowed: false, reason: \"A reviewed pinned flag is required in options.\" };\n if (kind === \"mutetab\" && typeof options.muted !== \"boolean\") return { allowed: false, reason: \"A reviewed muted flag is required in options.\" };\n if (kind === \"movetab\") {\n if (typeof options.index !== \"number\" || !Number.isInteger(options.index) || options.index < 0) return { allowed: false, reason: \"A reviewed non-negative target index is required in options.\" };\n }\n if (kind === \"movetabwindow\") {\n if (typeof options.windowid !== \"number\" || !Number.isInteger(options.windowid) || options.windowid < 0) return { allowed: false, reason: \"A reviewed target window id is required in options.\" };\n }\n if (kind === \"grouptabs\") {\n const group = options.group;\n if (!group || typeof group !== \"object\" || Array.isArray(group)) return { allowed: false, reason: \"A reviewed group with a name is required in options.\" };\n const spec = group as Record<string, unknown>;\n if (!isnonempty(spec.name)) return { allowed: false, reason: \"The reviewed group needs a non-empty name.\" };\n if (!validategroupcolor(spec.color)) return { allowed: false, reason: \"The reviewed group color must be a Chromium tab group color.\" };\n if (!validateidlist(spec, \"tabids\")) return { allowed: false, reason: \"The reviewed group needs a non-empty list of member tab ids.\" };\n }\n if (kind === \"colorgroup\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed group name is required in options.\" };\n if (!validategroupcolor(options.color)) return { allowed: false, reason: \"The reviewed group color must be a Chromium tab group color.\" };\n }\n if (kind === \"collapsegroup\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed group name is required in options.\" };\n if (typeof options.collapsed !== \"boolean\") return { allowed: false, reason: \"A reviewed collapsed flag is required in options.\" };\n }\n if (kind === \"discardtab\" || kind === \"reloadtabs\") {\n if (!isnumericid(step.value) && !validateidlist(options, \"tabs\")) return { allowed: false, reason: \"A numeric tab id or a reviewed list of tab ids is required.\" };\n }\n if (kind === \"zoomin\" || kind === \"zoomout\") {\n if (options.step !== undefined && (typeof options.step !== \"number\" || !Number.isFinite(options.step) || options.step <= 0)) return { allowed: false, reason: \"The reviewed zoom step must be a positive number with no code ceiling.\" };\n if (step.value !== undefined && step.value !== \"\" && !isnumericid(step.value)) return { allowed: false, reason: \"The reviewed zoom target must be a numeric tab id.\" };\n }\n if (kind === \"switchtab\") {\n if (options.direction !== \"next\" && options.direction !== \"previous\") return { allowed: false, reason: \"A reviewed switch direction of next or previous is required in options.\" };\n }\n if (kind === \"restorewindow\") {\n const bounds = options.bounds;\n if (bounds !== undefined) {\n if (!bounds || typeof bounds !== \"object\" || Array.isArray(bounds)) return { allowed: false, reason: \"The reviewed window bounds must be an object.\" };\n const shape = bounds as Record<string, unknown>;\n for (const field of [\"left\", \"top\", \"width\", \"height\"]) {\n if (typeof shape[field] !== \"number\" || !Number.isFinite(shape[field])) return { allowed: false, reason: \"The reviewed window bounds need numeric left, top, width and height.\" };\n }\n }\n }\n if (kind === \"scratchwindow\") {\n if (step.value !== undefined && step.value !== \"\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed scratch window url must use HTTPS.\" };\n }\n if (kind === \"incognitowindow\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS url is required to open an incognito window.\" };\n if (kind === \"restoretab\" && step.value !== undefined && step.value !== \"\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed restore url must use HTTPS.\" };\n if (kind === \"savelayout\" || kind === \"restorelayout\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed layout name is required in options.\" };\n }\n if (kind === \"badgetab\") {\n if (!isnonempty(options.label)) return { allowed: false, reason: \"A reviewed badge label is required in options.\" };\n if (options.taskid !== undefined && !isnonempty(options.taskid)) return { allowed: false, reason: \"The reviewed badge task id must be a non-empty string.\" };\n }\n if (kind === \"attachmeta\") {\n const labels = options.labels;\n const taskrefs = options.taskrefs;\n const haslabels = Array.isArray(labels) && labels.length > 0 && labels.every(label => isnonempty(label));\n const hastaskrefs = Array.isArray(taskrefs) && taskrefs.length > 0 && taskrefs.every(ref => isnonempty(ref));\n if (!haslabels && !hastaskrefs) return { allowed: false, reason: \"Reviewed labels or task refs are required in options to attach metadata.\" };\n if (options.provenance !== undefined && !isnonempty(options.provenance)) return { allowed: false, reason: \"The reviewed provenance must be a non-empty string.\" };\n }\n if (kind === \"reopenrun\" && !isnonempty(options.run)) return { allowed: false, reason: \"A reviewed run id is required in options to reopen its tabs.\" };\n return { allowed: true };\n}\n\n/** True when the kind belongs to the media capture family of pdf documents, recordings, images, canvases, streams, assets, lapses, conversions and thumbnails. */\nexport function ismediakind(kind: actionkind): boolean {\n return mediaactions.has(kind);\n}\n\n/** True when the kind belongs to the network observation family of fetching, parsing and typed calls. */\nexport function ishttpkind(kind: actionkind): boolean {\n return httpactions.has(kind);\n}\n\n/** True when the kind belongs to the socket and stream family of channels, messages, subscriptions and poll loops. */\nexport function issocketkind(kind: actionkind): boolean {\n return socketactions.has(kind);\n}\n\n/** True when the kind belongs to the request observation family of watches, headers, bodies and page api discovery. */\nexport function isnetwatchkind(kind: actionkind): boolean {\n return netwatchactions.has(kind);\n}\n\n/** True when the kind belongs to the network control family of blocking, mocking, header rewriting, cookies, auth, api keys, proxy routing and uploads. */\nexport function iscontrolkind(kind: actionkind): boolean {\n return controlactions.has(kind);\n}\n\n/** Resolves the reviewed risk of one step: capturebodies grades sensitive when the reviewed mime list carries private payload types and extractapi grades sensitive when the replay verb mutates, while every other kind keeps its risk table grade. */\nexport function resolvedrisk(step: toolstep): \"read\" | \"interaction\" | \"sensitive\" {\n if (step.kind === \"capturebodies\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const body = options.body;\n const mimes = body && typeof body === \"object\" && !Array.isArray(body) ? (body as Record<string, unknown>).mimes : undefined;\n if (Array.isArray(mimes) && mimes.some(mime => typeof mime === \"string\" && privatemime(mime))) return \"sensitive\";\n return \"interaction\";\n }\n if (step.kind === \"extractapi\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const replay = options.replay;\n const verb = replay && typeof replay === \"object\" && !Array.isArray(replay) ? (replay as Record<string, unknown>).verb : undefined;\n if (typeof verb === \"string\" && ![\"GET\", \"HEAD\", \"OPTIONS\"].includes(verb.trim().toUpperCase())) return \"sensitive\";\n return \"read\";\n }\n return actionrisk(step.kind);\n}\n\n/** Restricts every outbound channel to a granted origin: wss websocket and https event stream urls map onto their https origin, carry no embedded credentials and stay inside the session origin grants. */\nexport function socketgate(session: agentsession | undefined, url: string): policyevaluation {\n let parsed: URL;\n try { parsed = new URL(url); } catch { return { allowed: false, reason: \"The channel needs a valid url before it can be reviewed.\" }; }\n if (parsed.protocol !== \"wss:\" && parsed.protocol !== \"https:\") return { allowed: false, reason: \"Channels use wss websocket urls or https event stream urls only.\" };\n if (parsed.username || parsed.password) return { allowed: false, reason: \"Channel credentials are not allowed in the url.\" };\n const origin = channelorigin(url);\n if (!origingranted(session, origin)) return { allowed: false, reason: `The channel to ${origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** Requires the user granted request watching before any watchrequests step runs; the observation derives from the page timing buffers and the grant adds no manifest permission. */\nexport function watchgate(session: agentsession | undefined, settings: runsettings | undefined, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the request watch.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot watch requests.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot watch requests.\" };\n if (settings?.webrequestgrant !== true) return { allowed: false, reason: \"Request watching needs the webrequest grant in the review panel first; the observation derives from the page timing buffers and adds no manifest permission.\" };\n return { allowed: true };\n}\n\n/** Requires the host grant for every observed origin before header reads, body captures and endpoint replays touch an exchange. */\nexport function observedorigingranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The observed exchange url does not parse for an origin check.\" }; }\n if (!origingranted(session, origin)) return { allowed: false, reason: `The observed origin ${origin} stays outside the session origin grants; grant it before reading headers, bodies or replays.` };\n return { allowed: true };\n}\n\n/** Restricts every outbound request to a granted origin: the url must be a reviewed HTTPS url inside the session origin grants. */\nexport function origincheck(session: agentsession | undefined, url: string): policyevaluation {\n let parsed: URL;\n try { parsed = new URL(url); } catch { return { allowed: false, reason: \"The outbound request needs a valid url before it can be reviewed.\" }; }\n if (parsed.protocol !== \"https:\") return { allowed: false, reason: \"Outbound requests use HTTPS urls only.\" };\n if (parsed.username || parsed.password) return { allowed: false, reason: \"Endpoint credentials are not allowed in the url.\" };\n if (!origingranted(session, parsed.origin)) return { allowed: false, reason: `The outbound request to ${parsed.origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** True when a header name carries credentials and therefore needs the explicit consent that names it. */\nexport function credentialheadername(name: string): boolean {\n return credentialheaders.has(name.trim().toLowerCase());\n}\n\n/** Requires a reviewed consent ref before any custom header leaves the extension; requests without custom headers need no prompt. */\nexport function fetchconsentrefgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const request = options.fetch;\n const headers = request && typeof request === \"object\" && !Array.isArray(request) ? (request as Record<string, unknown>).headers : undefined;\n const names = headers && typeof headers === \"object\" && !Array.isArray(headers) ? Object.keys(headers as Record<string, unknown>) : [];\n if (names.length === 0) return { allowed: true };\n const empty = names.some(name => !name.trim());\n if (empty) return { allowed: false, reason: \"Header allowlists with empty names are refused.\" };\n const credential = names.find(name => credentialheadername(name));\n if (credential !== undefined && !isnonempty(options.consentref)) return { allowed: false, reason: `The credential bearing header ${credential} needs the explicit reviewed consent that names it before it is sent.` };\n if (!isnonempty(options.consentref)) return { allowed: false, reason: `The ${names.length} reviewed custom header${names.length === 1 ? \"\" : \"s\"} need a reviewed consent ref in options before any send.` };\n return { allowed: true };\n}\n\n/** True when one stored fetch consent still covers the origin and every header name inside its expiry window. */\nexport function fetchconsentcovers(consent: { origin: string; headers: Array<{ name: string }>; approved?: boolean; expiresat: number }, origin: string, headernames: string[], now: number): boolean {\n if (consent.approved !== true) return false;\n if (consent.expiresat <= now) return false;\n if (consent.origin !== origin) return false;\n const covered = new Set(consent.headers.map(header => header.name.trim().toLowerCase()));\n return headernames.every(name => covered.has(name.trim().toLowerCase()));\n}\n\n/** True when the reviewed call mutates: rest verbs beyond get, head and options or a graphql mutation; mutating calls grade sensitive. */\nexport function mutationcallof(step: toolstep): boolean {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (step.kind === \"callgraphql\") {\n const request = options.graphql;\n return Boolean(request && typeof request === \"object\" && !Array.isArray(request) && (request as Record<string, unknown>).operationkind === \"mutation\");\n }\n if (step.kind === \"callrest\") {\n const method = typeof options.method === \"string\" ? options.method.trim().toUpperCase() : undefined;\n if (method !== undefined) return ![\"GET\", \"HEAD\", \"OPTIONS\"].includes(method);\n }\n return false;\n}\n\n/** Keeps the reviewed fetch waits inside the reviewed wait budget: the worst case of every timeout plus every backoff wait must fit; every bound itself stays a user choice with no code ceiling. */\nexport function fetchbudgetallowed(timeout: number | undefined, retries: number | undefined, backoff: number | undefined, wait: number | undefined): policyevaluation {\n for (const [label, value] of [[\"timeout\", timeout], [\"retries\", retries], [\"backoff\", backoff]] as Array<[string, number | undefined]>) {\n if (value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)) return { allowed: false, reason: `The reviewed fetch ${label} must be zero or a positive number with no code ceiling.` };\n }\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed fetch wait budget must be zero or a positive number of milliseconds.\" };\n if (wait === undefined || timeout === undefined) return { allowed: true };\n const attempts = Math.max(1, Math.floor((retries ?? 0)) + 1);\n const waits = (backoff ?? 0) * (attempts * (attempts - 1)) / 2;\n const worstcase = timeout * attempts + waits;\n if (worstcase > wait) return { allowed: false, reason: `The fetch worst case of ${worstcase} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or fewer retries.` };\n return { allowed: true };\n}\n\n/** Resolves the outbound url of an http step at review time: the fetch request url of a fetchurl step and nothing for typed calls whose endpoints resolve at execution. */\nexport function outboundtarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const request = options.fetch;\n if (request && typeof request === \"object\" && !Array.isArray(request)) {\n const url = (request as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n return undefined;\n}\n\n/** Validates one reviewed typed endpoint definition: name, method, HTTPS url template with variables, header allowlist with non-empty names and a payload schema with kinds, required flags and defaults. */\nexport function validateendpointrecord(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed endpoint record is required.\" };\n const record = value as Record<string, unknown>;\n if (!isnonempty(record.name)) return { allowed: false, reason: \"The endpoint record needs a reviewed non-empty name.\" };\n if (!isnonempty(record.method)) return { allowed: false, reason: \"The endpoint record needs a reviewed method.\" };\n if (!ishttpsurl(record.url)) return { allowed: false, reason: \"The endpoint record url template must be an HTTPS url.\" };\n if (record.headers !== undefined) {\n if (!record.headers || typeof record.headers !== \"object\" || Array.isArray(record.headers)) return { allowed: false, reason: \"The endpoint header allowlist must be an object of reviewed headers.\" };\n for (const name of Object.keys(record.headers as Record<string, unknown>)) {\n if (!name.trim()) return { allowed: false, reason: \"Endpoint header allowlists with empty names are refused.\" };\n const headervalue = (record.headers as Record<string, unknown>)[name];\n if (typeof headervalue !== \"string\") return { allowed: false, reason: `The endpoint header ${name} needs a reviewed string value.` };\n }\n }\n const schema = record.schema;\n if (!schema || typeof schema !== \"object\" || Array.isArray(schema)) return { allowed: false, reason: \"Every typed endpoint call needs a reviewed payload schema; endpoint records without schemas are refused.\" };\n const fields = (schema as Record<string, unknown>).fields;\n if (!Array.isArray(fields) || fields.length === 0) return { allowed: false, reason: \"The endpoint payload schema needs a non-empty field list.\" };\n for (const item of fields) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every payload schema field must be an object.\" };\n const field = item as Record<string, unknown>;\n if (!isnonempty(field.name)) return { allowed: false, reason: \"Every payload schema field needs a non-empty name.\" };\n if (field.kind !== \"string\" && field.kind !== \"number\" && field.kind !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} must be a string, number or boolean kind.` };\n if (field.required !== undefined && typeof field.required !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} required flag must be a boolean.` };\n if (field.default !== undefined && typeof field.default !== \"string\" && typeof field.default !== \"number\" && typeof field.default !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} default must match its kind.` };\n }\n return { allowed: true };\n}\n\n/** Validates one dotted json path against the path grammar: non-empty segments of names, digits, underscores or hyphens. */\nfunction validpath(path: string): boolean {\n return path.split(\".\").every(segment => /^[A-Za-z0-9_-]+$/.test(segment));\n}\n\n/** Validates the reviewed network observation parameter grammar of the 1.1.42 family: fetch requests with header allowlists, fetch policies with timeout, retries, backoff and follow limit, stream budgets, dotted json paths, html queries, graphql operations and typed endpoint references; every bound stays a user choice with no code ceiling. */\nfunction validatehttpgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"fetchurl\") {\n const request = options.fetch;\n if (!request || typeof request !== \"object\" || Array.isArray(request)) return { allowed: false, reason: \"A reviewed fetch request with a url is required in options.fetch.\" };\n const fetchrequest = request as Record<string, unknown>;\n if (typeof fetchrequest.url !== \"string\" || !fetchrequest.url.trim()) return { allowed: false, reason: \"The reviewed fetch request needs a non-empty url.\" };\n if (fetchrequest.method !== undefined && (typeof fetchrequest.method !== \"string\" || ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(fetchrequest.method.trim().toUpperCase()))) return { allowed: false, reason: \"The reviewed fetch method must be a known HTTP verb.\" };\n if (fetchrequest.headers !== undefined) {\n if (!fetchrequest.headers || typeof fetchrequest.headers !== \"object\" || Array.isArray(fetchrequest.headers)) return { allowed: false, reason: \"The reviewed header allowlist must be an object of custom headers.\" };\n for (const name of Object.keys(fetchrequest.headers as Record<string, unknown>)) {\n if (!name.trim()) return { allowed: false, reason: \"Header allowlists with empty names are refused.\" };\n if (typeof (fetchrequest.headers as Record<string, unknown>)[name] !== \"string\") return { allowed: false, reason: `The reviewed header ${name} needs a string value.` };\n }\n }\n if (fetchrequest.body !== undefined && typeof fetchrequest.body !== \"string\") return { allowed: false, reason: \"The reviewed fetch body must be a string.\" };\n if (fetchrequest.mode !== undefined && fetchrequest.mode !== \"cors\" && fetchrequest.mode !== \"no-cors\" && fetchrequest.mode !== \"same-origin\") return { allowed: false, reason: \"The reviewed fetch mode must be cors, no-cors or same-origin.\" };\n const consentgate = fetchconsentrefgranted(step);\n if (!consentgate.allowed) return consentgate;\n const policycheck = validatefetchoptions(options.fetchoptions);\n if (!policycheck.allowed) return policycheck;\n const fetchpolicy = fetchoptionsvalues(options.fetchoptions);\n const budget = fetchbudgetallowed(fetchpolicy.timeout, fetchpolicy.retries, fetchpolicy.backoff, fetchnumeric(options, \"wait\"));\n if (!budget.allowed) return budget;\n if (options.stream !== undefined) {\n if (!options.stream || typeof options.stream !== \"object\" || Array.isArray(options.stream)) return { allowed: false, reason: \"The reviewed stream window must be an object with an optional byte budget.\" };\n const streambudget = (options.stream as Record<string, unknown>).budget;\n if (streambudget !== undefined && (typeof streambudget !== \"number\" || !Number.isFinite(streambudget) || streambudget < 0)) return { allowed: false, reason: \"The reviewed stream byte budget must be zero or a positive number of bytes with no code ceiling.\" };\n }\n }\n if (kind === \"parsejson\") {\n if (!isnonempty(options.call)) return { allowed: false, reason: \"A reviewed stored call id is required in options.call before the body parses.\" };\n const fields = options.fields;\n if (!Array.isArray(fields) || fields.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of json path rules is required in options.fields.\" };\n for (const item of fields) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every json path rule must be an object.\" };\n const rule = item as Record<string, unknown>;\n if (!isnonempty(rule.name)) return { allowed: false, reason: \"Every json path rule needs a non-empty field name.\" };\n if (typeof rule.path !== \"string\" || !rule.path.trim() || !validpath(rule.path.trim())) return { allowed: false, reason: `The json path of ${rule.name} must be a dotted path of non-empty segments.` };\n if (rule.kind !== undefined && rule.kind !== \"text\" && rule.kind !== \"number\" && rule.kind !== \"boolean\" && rule.kind !== \"json\") return { allowed: false, reason: `The json path kind of ${rule.name} must be text, number, boolean or json.` };\n }\n }\n if (kind === \"parsehtml\") {\n if (!isnonempty(options.call)) return { allowed: false, reason: \"A reviewed stored call id is required in options.call before the markup parses.\" };\n const queries = options.queries;\n if (!Array.isArray(queries) || queries.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of html queries is required in options.queries.\" };\n for (const item of queries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every html query must be an object.\" };\n const query = item as Record<string, unknown>;\n if (!isnonempty(query.selector)) return { allowed: false, reason: \"Every html query needs a selector from the reviewed selector grammar.\" };\n if (query.attribute !== undefined && !isnonempty(query.attribute)) return { allowed: false, reason: \"The reviewed html query attribute must be a non-empty attribute name.\" };\n if (query.multi !== undefined && typeof query.multi !== \"boolean\") return { allowed: false, reason: \"The reviewed html query multi flag must be a boolean.\" };\n }\n }\n if (kind === \"callrest\" || kind === \"callgraphql\") {\n if (!isnonempty(options.endpoint)) return { allowed: false, reason: \"A reviewed typed endpoint name is required in options.endpoint.\" };\n if (kind === \"callrest\") {\n if (options.payload !== undefined && (!options.payload || typeof options.payload !== \"object\" || Array.isArray(options.payload))) return { allowed: false, reason: \"The reviewed rest payload must be an object of reviewed values.\" };\n if (options.method !== undefined && (typeof options.method !== \"string\" || ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(options.method.trim().toUpperCase()))) return { allowed: false, reason: \"The reviewed endpoint method override must be a known HTTP verb.\" };\n if (options.success !== undefined && (!Array.isArray(options.success) || !options.success.every(code => typeof code === \"number\" && Number.isInteger(code)))) return { allowed: false, reason: \"The reviewed success status list must be a list of integer status codes.\" };\n }\n if (kind === \"callgraphql\") {\n const request = options.graphql;\n if (!request || typeof request !== \"object\" || Array.isArray(request)) return { allowed: false, reason: \"A reviewed graphql request with an operation is required in options.graphql.\" };\n const graphql = request as Record<string, unknown>;\n if (typeof graphql.query !== \"string\" || !graphql.query.trim()) return { allowed: false, reason: \"The reviewed graphql operation text must be a non-empty string.\" };\n if (graphql.operationkind !== \"query\" && graphql.operationkind !== \"mutation\") return { allowed: false, reason: \"The reviewed graphql operation kind must be query or mutation; unknown operation kinds are refused.\" };\n if (graphql.variables !== undefined && (!graphql.variables || typeof graphql.variables !== \"object\" || Array.isArray(graphql.variables))) return { allowed: false, reason: \"The reviewed graphql variables must be an object of reviewed values.\" };\n if (graphql.operationname !== undefined && !isnonempty(graphql.operationname)) return { allowed: false, reason: \"The reviewed graphql operation name must be a non-empty string.\" };\n }\n if (options.apikeys !== undefined && (!Array.isArray(options.apikeys) || !options.apikeys.every(name => isnonempty(name)))) return { allowed: false, reason: \"The reviewed api key reference list must be a list of non-empty stored names.\" };\n const policycheck = validatefetchoptions(options.fetchoptions);\n if (!policycheck.allowed) return policycheck;\n const fetchpolicy = fetchoptionsvalues(options.fetchoptions);\n const budget = fetchbudgetallowed(fetchpolicy.timeout, fetchpolicy.retries, fetchpolicy.backoff, fetchnumeric(options, \"wait\"));\n if (!budget.allowed) return budget;\n }\n return { allowed: true };\n}\n\n/** Validates one reviewed fetch policy object: timeout, retries, backoff base and redirect follow limit stay user choices with no code ceiling. */\nfunction validatefetchoptions(value: unknown): policyevaluation {\n if (value === undefined) return { allowed: true };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"The reviewed fetch options must be an object with timeout, retries, backoff and follow.\" };\n const options = value as Record<string, unknown>;\n for (const key of [\"timeout\", \"backoff\"]) {\n if (options[key] !== undefined && (typeof options[key] !== \"number\" || !Number.isFinite(options[key]) || options[key] < 0)) return { allowed: false, reason: `The reviewed fetch ${key} must be zero or a positive number with no code ceiling.` };\n }\n for (const key of [\"retries\", \"follow\"]) {\n if (options[key] !== undefined && (typeof options[key] !== \"number\" || !Number.isInteger(options[key]) || options[key] < 0)) return { allowed: false, reason: `The reviewed fetch ${key} must be zero or a positive integer with no code ceiling.` };\n }\n return { allowed: true };\n}\n\n/** Reads the numeric fetch policy fields of one reviewed fetch options object. */\nfunction fetchoptionsvalues(value: unknown): { timeout?: number | undefined; retries?: number | undefined; backoff?: number | undefined } {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n const options = value as Record<string, unknown>;\n return { timeout: fetchnumeric(options, \"timeout\"), retries: fetchnumeric(options, \"retries\"), backoff: fetchnumeric(options, \"backoff\") };\n}\n\n/** Reads one numeric fetch policy field from the step options. */\nfunction fetchnumeric(options: Record<string, unknown>, key: string): number | undefined {\n const value = options[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\n/** True when the kind records user activity and needs the reviewed recording consent before it starts. */\nexport function isrecordingkind(kind: actionkind): boolean {\n return kind === \"recordscreen\" || kind === \"captureaudio\";\n}\n\n/** Validates the reviewed socket and stream parameter grammar of the 1.1.43 family: channel urls with protocols, reconnect budgets and backoff ceilings, multiplexed message payloads, message filters with dotted paths and match limits, event subscriptions with cancellation paths and long poll cursors with intervals kept inside the reviewed wait budget; every bound stays a user choice with no code ceiling. */\nfunction validatesocketgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"opensocket\") {\n const channel = channeloptionsof(options.socket);\n if (!channel) return { allowed: false, reason: \"A reviewed socket with a url is required in options.socket.\" };\n if (channel.options.reconnect !== undefined && !Number.isInteger(channel.options.reconnect)) return { allowed: false, reason: \"The reviewed socket reconnect budget must be an integer attempt count with no code ceiling.\" };\n for (const label of [\"backoff\", \"backoffceiling\"] as const) {\n const value = channel.options[label];\n if (value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)) return { allowed: false, reason: `The reviewed socket ${label} must be zero or a positive number of milliseconds with no code ceiling.` };\n }\n if (channel.options.lifetime !== undefined && (typeof channel.options.lifetime !== \"number\" || !Number.isFinite(channel.options.lifetime) || channel.options.lifetime <= 0)) return { allowed: false, reason: \"The reviewed socket lifetime window must be a positive number of milliseconds.\" };\n }\n if (kind === \"sendmessage\") {\n const message = options.message;\n if (!message || typeof message !== \"object\" || Array.isArray(message)) return { allowed: false, reason: \"A reviewed message with a channel, stream and payload is required in options.message.\" };\n const envelope = message as Record<string, unknown>;\n if (!isnonempty(envelope.channel)) return { allowed: false, reason: \"The reviewed message needs the open channel id in options.message.channel.\" };\n if (envelope.stream !== undefined && !isnonempty(envelope.stream)) return { allowed: false, reason: \"The reviewed message stream name must be a non-empty string.\" };\n if (typeof envelope.payload !== \"string\") return { allowed: false, reason: \"The reviewed message payload must be a string.\" };\n }\n if (kind === \"waitmessage\") {\n if (options.filter !== undefined) {\n const filter = options.filter;\n if (!filter || typeof filter !== \"object\" || Array.isArray(filter)) return { allowed: false, reason: \"The reviewed message filter must be an object of stream, path and limit.\" };\n const reviewed = filter as Record<string, unknown>;\n if (reviewed.stream !== undefined && !isnonempty(reviewed.stream)) return { allowed: false, reason: \"The reviewed message filter stream name must be a non-empty string.\" };\n if (reviewed.path !== undefined && (typeof reviewed.path !== \"string\" || !validpath(reviewed.path.trim()))) return { allowed: false, reason: \"The reviewed message filter path must be a dotted path of non-empty segments.\" };\n if (reviewed.limit !== undefined && (typeof reviewed.limit !== \"number\" || !Number.isInteger(reviewed.limit) || reviewed.limit < 1)) return { allowed: false, reason: \"The reviewed message match limit must be a positive integer with no code ceiling.\" };\n }\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed message wait budget must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"subscribesse\") {\n const subscription = subscriptionoptionsof(options.subscription);\n if (!subscription) return { allowed: false, reason: \"A reviewed subscription with an event stream url and a cancellation path is required in options.subscription.\" };\n const rawlifetime = options.subscription && typeof options.subscription === \"object\" && !Array.isArray(options.subscription) ? (options.subscription as Record<string, unknown>).lifetime : undefined;\n if (rawlifetime !== undefined && (typeof rawlifetime !== \"number\" || !Number.isFinite(rawlifetime) || rawlifetime <= 0)) return { allowed: false, reason: \"The reviewed subscription lifetime window must be a positive number of milliseconds.\" };\n }\n if (kind === \"longpoll\") {\n const cursor = pollcursorof(options.poll);\n if (!cursor) return { allowed: false, reason: \"A reviewed poll cursor with a url, cursor field, interval and stop condition is required in options.poll.\" };\n const wait = options.wait;\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed long poll wait budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && cursor.interval > wait) return { allowed: false, reason: `The long poll interval of ${cursor.interval} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter interval.` };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed request observation parameter grammar of the 1.1.43 family: watch windows with user configured match limits, header filters whose redaction list is required before any header value is stored, body filters with url patterns, mime lists and byte ceilings and api replay specs with known verbs and dotted extraction paths. */\nfunction validatenetwatchgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"watchrequests\") {\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined && (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0)) return { allowed: false, reason: \"The reviewed watch window must be zero or a positive number of milliseconds.\" };\n }\n if (options.limit !== undefined && (typeof options.limit !== \"number\" || !Number.isInteger(options.limit) || options.limit < 1)) return { allowed: false, reason: \"The reviewed watch match limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"readheaders\") {\n const headers = options.headers;\n if (!headers || typeof headers !== \"object\" || Array.isArray(headers)) return { allowed: false, reason: \"A reviewed header filter with a name allowlist and a redaction list is required in options.headers.\" };\n const reviewed = headers as Record<string, unknown>;\n if (!Array.isArray(reviewed.allow) || reviewed.allow.length === 0 || !reviewed.allow.every((name): name is string => isnonempty(name))) return { allowed: false, reason: \"The reviewed header allowlist must be a non-empty list of header names.\" };\n if (!Array.isArray(reviewed.redact) || reviewed.redact.length === 0 || !reviewed.redact.every((name): name is string => isnonempty(name))) return { allowed: false, reason: \"Header capture requires a reviewed redaction list before any header value is stored.\" };\n }\n if (kind === \"capturebodies\") {\n const body = options.body;\n if (!body || typeof body !== \"object\" || Array.isArray(body)) return { allowed: false, reason: \"A reviewed body filter with a url pattern, mime list and byte ceiling is required in options.body.\" };\n const reviewed = body as Record<string, unknown>;\n if (reviewed.urlpattern !== undefined && !isnonempty(reviewed.urlpattern)) return { allowed: false, reason: \"The reviewed body url pattern must be a non-empty string.\" };\n if (reviewed.mimes !== undefined && (!Array.isArray(reviewed.mimes) || reviewed.mimes.length === 0 || !reviewed.mimes.every((mime): mime is string => isnonempty(mime)))) return { allowed: false, reason: \"The reviewed body mime list must be a non-empty list of mime types.\" };\n if (reviewed.ceiling !== undefined && (typeof reviewed.ceiling !== \"number\" || !Number.isFinite(reviewed.ceiling) || reviewed.ceiling < 0)) return { allowed: false, reason: \"The reviewed body byte ceiling must be zero or a positive number of bytes with no code ceiling.\" };\n }\n if (kind === \"mapapi\") {\n if (options.limit !== undefined && (typeof options.limit !== \"number\" || !Number.isInteger(options.limit) || options.limit < 1)) return { allowed: false, reason: \"The reviewed mapapi match limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"extractapi\") {\n const replay = apireplayspecof(options.replay);\n if (!replay) return { allowed: false, reason: \"A reviewed replay spec with an endpoint is required in options.replay.\" };\n if (!ishttpsurl(replay.endpoint)) return { allowed: false, reason: \"The reviewed replay endpoint must be an HTTPS url.\" };\n if (replay.verb !== undefined && ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(replay.verb)) return { allowed: false, reason: \"The reviewed replay verb must be a known HTTP verb.\" };\n for (const path of replay.paths ?? []) {\n if (!validpath(path.trim())) return { allowed: false, reason: `The reviewed replay extraction path ${path} must be a dotted path of non-empty segments.` };\n }\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed network control parameter grammar of the 1.1.44 family: block rules with url patterns that name their origin, mock fixtures reviewed with their full body, header rewrite rules with named origin patterns and set, append and remove operations, cookie records scoped to granted domains, oauth flows with provider consent refs, api key entries behind explicit consent, proxy routes with required bypass lists, urlencoded form payloads and multipart uploads whose every file carries the explicit reviewed flag; every bound stays a user choice with no code ceiling. */\nfunction validatecontrolgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"blockrequest\") {\n const rule = blockruleof(options.block);\n if (!rule) return { allowed: false, reason: \"A reviewed block rule with a url pattern is required in options.block.\" };\n if (patternorigin(rule.urlpattern) === undefined) return { allowed: false, reason: \"Block rules need an https origin pattern; patterns without a named origin are refused.\" };\n if ((options.block as Record<string, unknown>).reviewed !== true) return { allowed: false, reason: \"The block rule carries the explicit reviewed flag before any request is blocked.\" };\n }\n if (kind === \"mockresponse\") {\n const spec = mockspecof(options.mock);\n if (!spec) return { allowed: false, reason: \"A reviewed mock fixture with a url pattern, status and its reviewed body or a captured body ref is required in options.mock.\" };\n if (patternorigin(spec.urlpattern) === undefined) return { allowed: false, reason: \"Mock fixtures need an https origin pattern; patterns without a named origin are refused.\" };\n if (spec.reviewed !== true) return { allowed: false, reason: \"Every mock fixture is reviewed with its full body or the referenced captured body through the explicit reviewed flag before it serves.\" };\n }\n if (kind === \"rewriteheaders\") {\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of header rewrite rules is required in options.rules.\" };\n for (const item of rules) {\n const rule = headeruleof(item);\n if (!rule) return { allowed: false, reason: \"Every header rewrite rule needs a url pattern, header name, a set, append or remove operation and its value.\" };\n if (patternorigin(rule.urlpattern) === undefined) return { allowed: false, reason: \"Header rewrite rules must name their origin pattern explicitly; patterns without a named origin are refused.\" };\n }\n }\n if (kind === \"setcookies\") {\n const cookies = options.cookies;\n if (!Array.isArray(cookies) || cookies.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of cookie records is required in options.cookies.\" };\n for (const item of cookies) {\n if (!cookierecordof(item)) return { allowed: false, reason: \"Every cookie record needs a name, domain, path and reviewed string value with an optional expiry.\" };\n }\n }\n if (kind === \"readcookies\" && options.domain !== undefined && !isnonempty(options.domain)) return { allowed: false, reason: \"The reviewed cookie read domain must be a non-empty host.\" };\n if (kind === \"clearcookies\") {\n if (!isnonempty(options.domain)) return { allowed: false, reason: \"A reviewed cookie domain is required before cookies are cleared.\" };\n if (options.names !== undefined && (!Array.isArray(options.names) || options.names.length === 0 || !options.names.every((name): name is string => isnonempty(name)))) return { allowed: false, reason: \"The reviewed cookie clear list must be a non-empty list of cookie names when present.\" };\n }\n if (kind === \"authflow\") {\n const flow = oauthflowof(options.oauth);\n if (!flow) return { allowed: false, reason: \"A reviewed oauth flow with provider, authorize url, token url, scopes and redirect origin is required in options.oauth.\" };\n if (!ishttpsurl(flow.authorizeurl) || !ishttpsurl(flow.tokenurl)) return { allowed: false, reason: \"The oauth authorize and token urls must use HTTPS.\" };\n if (!ishttpsurl(flow.redirectorigin) && !/^https:\\/\\/[^/]+\\/?$/.test(flow.redirectorigin)) return { allowed: false, reason: \"The oauth redirect origin must be an HTTPS origin inside the grants.\" };\n const consent = authconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"saveapikey\") {\n const key = options.key;\n if (!key || typeof key !== \"object\" || Array.isArray(key)) return { allowed: false, reason: \"A reviewed api key entry with name, origin scopes and header is required in options.key.\" };\n const entry = key as Record<string, unknown>;\n if (!isnonempty(entry.name)) return { allowed: false, reason: \"The api key entry needs a reviewed non-empty name.\" };\n if (!Array.isArray(entry.origins) || entry.origins.length === 0 || !entry.origins.every((item): item is string => ishttpsurl(item))) return { allowed: false, reason: \"The api key needs a reviewed non-empty list of HTTPS origin scopes.\" };\n if (!isnonempty(entry.header)) return { allowed: false, reason: \"The api key entry needs a reviewed non-empty header name.\" };\n if (typeof entry.value !== \"string\" || !entry.value) return { allowed: false, reason: \"The api key needs its secret value in the reviewed options; it never enters the audit trail.\" };\n const consent = apikeyconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"routeproxy\") {\n if (!proxyrouteof(options.proxy)) return { allowed: false, reason: \"A reviewed proxy route with scheme, host, port and a non-empty bypass list is required in options.proxy.\" };\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"Proxy routing needs the explicit reviewed consent ref before any route applies.\" };\n }\n if (kind === \"postform\") {\n const form = formpayloadof(options.form);\n if (!form) return { allowed: false, reason: \"A reviewed form payload with a url and a non-empty field list is required in options.form.\" };\n if (!ishttpsurl(form.url)) return { allowed: false, reason: \"The form submission target must use HTTPS.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed rate limit wait budget must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"postfiles\") {\n const upload = multipartpayloadof(options.upload);\n if (!upload) return { allowed: false, reason: \"A reviewed multipart upload with a url and reviewed files is required in options.upload; every file carries the explicit reviewed flag.\" };\n if (!ishttpsurl(upload.url)) return { allowed: false, reason: \"The multipart upload target must use HTTPS.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed rate limit wait budget must be zero or a positive number of milliseconds.\" };\n }\n return { allowed: true };\n}\n\n/** Requires the reviewed block rule of a live session before any blockrequest runs: the rule must carry the explicit reviewed flag and the session must stay active, unpaused and unexpired; every rule applies for the run only and reverts at run end. */\nexport function blockgate(session: agentsession | undefined, step: toolstep, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the request block.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot block requests.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot block requests.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const rule = options.block;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule) || (rule as Record<string, unknown>).reviewed !== true) return { allowed: false, reason: \"Request blocking needs its reviewed block rule with the explicit reviewed flag before any rule applies.\" };\n if (!blockruleof(rule)) return { allowed: false, reason: \"The block rule needs a url pattern and an optional resource type list.\" };\n return { allowed: true };\n}\n\n/** Scopes every cookie kind to a granted domain of a live session: the domain must equal a granted origin host or sit beneath it, and every other domain is refused. */\nexport function cookiegate(session: agentsession | undefined, domain: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the cookie operation.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot touch cookies.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot touch cookies.\" };\n const grants = session.grants ?? [session.origin];\n if (!cookiedomaingranted(domain, grants)) return { allowed: false, reason: `The cookie domain ${domain} stays outside the session origin grants; cookie control refuses domains beyond the grants.` };\n return { allowed: true };\n}\n\n/** Requires the explicit reviewed consent before routeproxy changes routing: a live session, a reviewed consent ref and a valid route with its bypass list; the route applies for the run only and restores the previous state at run end. */\nexport function proxygate(session: agentsession | undefined, step: toolstep, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the proxy route.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot change routing.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot change routing.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"Proxy routing needs the explicit reviewed consent ref before any route applies.\" };\n if (!proxyrouteof(options.proxy)) return { allowed: false, reason: \"The proxy route needs a scheme, host, port and a non-empty bypass list of origins that stay direct.\" };\n return { allowed: true };\n}\n\n/** Requires the reviewed provider consent prompt ref before any authflow runs. */\nexport function authconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"An oauth flow requires the reviewed provider consent prompt ref in options before it starts.\" };\n return { allowed: true };\n}\n\n/** Requires the explicit consent prompt ref before saveapikey stores a key. */\nexport function apikeyconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"Storing an api key requires the explicit reviewed consent prompt ref in options before anything is stored.\" };\n return { allowed: true };\n}\n\n/** Keeps the rate limit wait inside the reviewed wait budget as user configured behavior: the wait until the reset window passes must fit when a budget was reviewed; both bounds stay user choices with no code ceiling. */\nexport function ratelimitbudgetallowed(wait: number | undefined, budget: number | undefined): policyevaluation {\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The rate limit wait must be zero or a positive number of milliseconds.\" };\n if (budget !== undefined && (typeof budget !== \"number\" || !Number.isFinite(budget) || budget < 0)) return { allowed: false, reason: \"The reviewed rate limit budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && budget !== undefined && wait > budget) return { allowed: false, reason: `The rate limit wait of ${wait} milliseconds exceeds the reviewed budget of ${budget} milliseconds; review a wider budget or submit later.` };\n return { allowed: true };\n}\n\n/** Requires the active tab grant of the live session for every debugging kind: the timeline gate scopes console, error and task capture to the run tab only and refuses every other tab. */\nexport function timelinegate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the timeline capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture the timeline.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture the timeline.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The timeline capture needs the run tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The timeline capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** True when one approved console capture consent of that origin exists; console capture on a new origin prompts once and the approved decision persists. */\nexport function consoleconsentcovers(origin: string, consents: consoleconsentrecord[]): policyevaluation {\n if (consents.some(consent => consent.origin === origin && consent.approved === true)) return { allowed: true };\n return { allowed: false, reason: `Console capture on ${origin} needs the reviewed console consent first; approve the prompt in the review panel.` };\n}\n\n/** Requires the granted origin before stack frames are captured; stack capture outside the granted origin is refused. */\nexport function stackgate(session: agentsession | undefined, origin: string): policyevaluation {\n if (!origingranted(session, origin)) return { allowed: false, reason: `Stack capture of ${origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** Keeps the debug watch window inside the reviewed wait budget: the watch wait must fit the reviewed budget when one was reviewed; both bounds stay user choices with no code ceiling. */\nexport function debugwaitbudgetallowed(watchwindow: number | undefined, wait: number | undefined): policyevaluation {\n if (watchwindow !== undefined && (typeof watchwindow !== \"number\" || !Number.isFinite(watchwindow) || watchwindow < 0)) return { allowed: false, reason: \"The debug watch window must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed debug wait budget must be zero or a positive number of milliseconds.\" };\n if (watchwindow !== undefined && wait !== undefined && watchwindow > wait) return { allowed: false, reason: `The debug watch window of ${watchwindow} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter window.` };\n return { allowed: true };\n}\n\n/** Exposes the timeline retention window as a user configured choice; an absent value keeps every timeline entry forever while the level count summaries always survive. */\nexport function timelineretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.timelineretention;\n}\n\n/** Grades console diffing as read only comparison evidence: the diff compares two stored console outputs and touches no page or browser state. */\nexport function diffreviewgrade(): { risk: \"read\"; mode: \"diffing\"; evidence: \"comparison\" } {\n return { risk: \"read\", mode: \"diffing\", evidence: \"comparison\" };\n}\n\n/** Validates the reviewed debugging parameter grammar of the 1.1.45 family: a watch window inside the reviewed wait budget, level floors from the reviewed level set, source filters from the reviewed source grammar, spam rules with user configured thresholds, serialization depth bounds, rotation rules with no hardcoded entry ceiling and the required redaction pattern list before any console text is captured. */\nfunction validatetimelinegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n let watchwindow: number | undefined;\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed debug watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined) {\n if (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0) return { allowed: false, reason: \"The reviewed debug watch window must be zero or a positive number of milliseconds.\" };\n watchwindow = reviewed.window;\n }\n }\n const budgetcheck = debugwaitbudgetallowed(watchwindow, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n if (options.level !== undefined && !loglevels.includes(options.level as loglevel)) return { allowed: false, reason: `The reviewed level floor must be one of ${loglevels.join(\", \")}.` };\n if (options.sources !== undefined) {\n if (!Array.isArray(options.sources) || options.sources.length === 0 || !options.sources.every(source => timelinesources.includes(source as never))) return { allowed: false, reason: `The reviewed source filters must be a non-empty list of the reviewed timeline sources: ${timelinesources.join(\", \")}.` };\n }\n if (kind === \"watchconsole\") {\n if (options.redact === undefined || !Array.isArray(options.redact) || options.redact.length === 0 || !options.redact.every(pattern => isnonempty(pattern))) return { allowed: false, reason: \"Console capture requires a reviewed non-empty redaction pattern list before any console text is captured.\" };\n if (options.depth !== undefined && (typeof options.depth !== \"number\" || !Number.isInteger(options.depth) || options.depth < 1)) return { allowed: false, reason: \"The reviewed serialization depth bound must be a positive integer with no code ceiling.\" };\n if (options.spam !== undefined) {\n const rule = spamruleof(options.spam);\n if (!rule) return { allowed: false, reason: \"The reviewed spam rule needs a pattern, a window size and a collapse threshold.\" };\n if (rule.collapse < 1) return { allowed: false, reason: \"The reviewed spam collapse threshold must be a positive integer of user configured value with no code ceiling.\" };\n }\n if (options.rotation !== undefined) {\n const rule = rotationruleof(options.rotation);\n if (!rule) return { allowed: false, reason: \"The reviewed rotation rule needs a max entry count and an overflow target.\" };\n }\n }\n if (kind === \"watchtasks\") {\n if (options.threshold !== undefined && (typeof options.threshold !== \"number\" || !Number.isFinite(options.threshold) || options.threshold < 0)) return { allowed: false, reason: \"The reviewed long task threshold must be zero or a positive number of milliseconds with no code ceiling.\" };\n }\n return { allowed: true };\n}\n\n/** Normalizes a reviewed spam rule: the pattern, the window size and the collapse threshold as user configured values. */\nexport function spamruleof(value: unknown): spamrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const entry = value as Record<string, unknown>;\n const pattern = typeof entry.pattern === \"string\" ? entry.pattern : \"\";\n const windowsize = typeof entry.windowsize === \"number\" && Number.isFinite(entry.windowsize) && entry.windowsize >= 0 ? entry.windowsize : undefined;\n const collapse = typeof entry.collapse === \"number\" && Number.isInteger(entry.collapse) ? entry.collapse : undefined;\n if (windowsize === undefined || collapse === undefined) return undefined;\n return { pattern, windowsize, collapse };\n}\n\n/** Normalizes a reviewed log rotation rule: the max entries per run and the overflow target store with no hardcoded entry ceiling. */\nexport function rotationruleof(value: unknown): rotationrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const entry = value as Record<string, unknown>;\n const maxentries = typeof entry.maxentries === \"number\" && Number.isInteger(entry.maxentries) && entry.maxentries >= 1 ? entry.maxentries : undefined;\n const overflowtarget = typeof entry.overflowtarget === \"string\" && entry.overflowtarget.trim() ? entry.overflowtarget.trim() : undefined;\n if (maxentries === undefined || overflowtarget === undefined) return undefined;\n return { maxentries, overflowtarget };\n}\n\n/** Requires the active run tab grant of the live session for every devtools protocol kind: the debug gate scopes attaches, commands, watches, breakpoints, steps and overrides to the run tab only and refuses every other tab. */\nexport function debuggate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the devtools protocol step.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot run a devtools protocol step.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot run a devtools protocol step.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The devtools protocol step needs the run tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The devtools protocol step on ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** True when one approved debugger consent of that origin covers every requested domain; the first attachcdp of a run needs the approved record and revocation removes the coverage. */\nexport function debuggerconsentcovers(origin: string, domains: string[], grants: debuggergrant[]): policyevaluation {\n const needed = [...new Set(domains)];\n const covering = grants.find(grant => grant.origin === origin && grant.approved === true && grant.revokedat === undefined && needed.every(domain => grant.domains.includes(domain)));\n if (covering) return { allowed: true };\n if (grants.some(grant => grant.origin === origin && grant.revokedat !== undefined)) return { allowed: false, reason: `The debugger consent on ${origin} was revoked; approve a new prompt before the devtools protocol runs again.` };\n return { allowed: false, reason: `The devtools protocol on ${origin} needs the reviewed debugger consent for ${needed.join(\", \")} first; approve the prompt with the domain allowlist shown in the review panel.` };\n}\n\n/** The profiling target gate of every 1.1.47 kind: the live session run tab and origin grants come first, every iframe, worker and service worker target stays inside the granted origins, and the reviewed debugger grant of the origin covers every profiling instrument because profiling is debugger grade instrumentation. */\nexport function targetgate(input: { session: agentsession | undefined; tabid: number; origin: string; targets: attachtarget[]; grants: debuggergrant[] | undefined; now: number }): policyevaluation {\n const base = debuggate(input.session, input.tabid, input.origin, input.now);\n if (!base.allowed) return base;\n for (const target of input.targets) {\n if (target.kind === \"page\") continue;\n const origincheckresult = origincheck(input.session, target.url);\n if (!origincheckresult.allowed) return { allowed: false, reason: `The ${target.kind} target ${target.url} stays outside the granted origins; profiling refuses to attach.` };\n }\n if (input.grants === undefined) return { allowed: true };\n const consent = debuggerconsentcovers(input.origin, [], input.grants);\n if (!consent.allowed) return { allowed: false, reason: `The profiling step on ${input.origin} needs the reviewed debugger grant of the origin first; approve the prompt with the profiling derivation shown in the review panel.` };\n return { allowed: true };\n}\n\n/** True when one approved source map capture consent of that origin covers the capture; revocation removes the coverage and the next capture needs a new reviewed prompt. */\nexport function sourcemapconsentcovers(origin: string, consents: sourcemapconsent[]): policyevaluation {\n const covering = consents.find(consent => consent.origin === origin && consent.approved === true && consent.revokedat === undefined);\n if (covering) return { allowed: true };\n if (consents.some(consent => consent.origin === origin && consent.revokedat !== undefined)) return { allowed: false, reason: `The source map capture consent on ${origin} was revoked; approve a new prompt before another map file is fetched.` };\n return { allowed: false, reason: `The source map capture on ${origin} needs the reviewed per origin consent first; approve the prompt shown in the review panel.` };\n}\n\n/** Exposes the user configured retention window for the heavy profile bytes; an absent window keeps every snapshot, sample and trace file. */\nexport function profileretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.profileretention;\n}\n\n/** Exposes the user configured trace byte ceiling; an absent value never refuses a trace export because the cap stays a user choice only. */\nexport function traceceilingof(settings: runsettings | undefined): number | undefined {\n return settings?.traceceiling;\n}\n\n/** Validates one breakpoint condition against the reviewed expression grammar: member chains, literals of number, string, boolean and null, comparison and logic operators, negation and parentheses; assignments, calls and statements are refused. */\nexport function validatebreakpointcondition(condition: string): policyevaluation {\n const expression = condition.trim();\n if (expression.length === 0) return { allowed: false, reason: \"The breakpoint condition must not be empty.\" };\n if (/(?<![=!<>])=(?!=)/.test(expression)) return { allowed: false, reason: \"Breakpoint conditions refuse assignment because the reviewed grammar is comparison only.\" };\n if (/[A-Za-z_$][\\w$]*\\s*\\(/.test(expression)) return { allowed: false, reason: \"Breakpoint conditions refuse calls because the reviewed grammar is comparison only.\" };\n const literal = /^(?:-?\\d+(?:\\.\\d+)?|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|true|false|null)$/;\n const tokens = expression.match(/(?:[A-Za-z_$][\\w$]*|-?\\d+(?:\\.\\d+)?|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|===|!==|==|!=|>=|<=|&&|\\|\\||[!.<>()+\\-*\\/%])/g);\n if (tokens === null || tokens.join(\"\") !== expression.replace(/\\s+/g, \"\")) return { allowed: false, reason: \"The breakpoint condition must use the reviewed expression grammar of member chains, literals, comparisons, logic operators, negation and parentheses.\" };\n const identifierlike = /^(?:true|false|null)$/;\n for (const token of tokens) {\n if (literal.test(token) || identifierlike.test(token)) continue;\n if ([\"===\", \"!==\", \"==\", \"!=\", \">=\", \"<=\", \"&&\", \"||\", \"!\", \".\", \"(\", \")\", \"<\", \">\", \"+\", \"-\", \"*\", \"/\", \"%\"].includes(token)) continue;\n if (/^[A-Za-z_$][\\w$]*$/.test(token)) continue;\n return { allowed: false, reason: `The token ${token} of the breakpoint condition stays outside the reviewed expression grammar.` };\n }\n return { allowed: true };\n}\n\n/** Keeps the breakpoint count of one run inside the user configured ceiling: an absent ceiling never refuses a breakpoint because the cap stays a user choice only. */\nexport function breakpointbudgetallowed(active: number, ceiling: number | undefined): policyevaluation {\n if (ceiling === undefined) return { allowed: true };\n if (typeof ceiling !== \"number\" || !Number.isInteger(ceiling) || ceiling < 0) return { allowed: false, reason: \"The reviewed breakpoint ceiling must be zero or a positive integer of user configured value with no code ceiling.\" };\n if (active >= ceiling) return { allowed: false, reason: `The run already holds ${active} active breakpoint${active === 1 ? \"\" : \"s\"} and the reviewed breakpoint ceiling is ${ceiling}; revert one or review a wider ceiling.` };\n return { allowed: true };\n}\n\n/** Exposes the pause capture retention window as a user configured choice; an absent value keeps every pause capture with its call frames. */\nexport function pauseretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.pauseretention;\n}\n\n/** Exposes the user configured breakpoint ceiling; an absent value never refuses a breakpoint because the cap stays a user choice only. */\nexport function breakpointceilingof(settings: runsettings | undefined): number | undefined {\n return settings?.breakpointceiling;\n}\n\n/** Requires the review of every emulation layer before it applies: a live session on the run tab, an approved plan, the explicit reviewed flag on the layer options and the reviewed revert plan beside it. */\nexport function emugate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"emulate the run tab\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Emulation layers need an approved plan before they apply.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n if (options.reviewed !== true) return { allowed: false, reason: `The ${input.step.kind} layer needs the explicit reviewed flag before any mask applies.` };\n if (revertplanof(options.revertplan) === undefined) return { allowed: false, reason: `Every ${input.step.kind} layer needs a reviewed revert plan beside it before any mask applies.` };\n return { allowed: true };\n}\n\n/** Allows layer stacking only when the reviewed plan lists the steps: a second layer of one family needs at least two reviewed steps of that family in the same plan because the last applied layer wins conflicts. */\nexport function emulationstackallowed(plan: agentplan | undefined, kind: actionkind, active: number): policyevaluation {\n if (!plan) return { allowed: false, reason: \"Layer stacking needs the reviewed plan first.\" };\n const listed = plan.steps.filter(step => step.kind === kind).length;\n if (active >= listed) return { allowed: false, reason: `The plan lists ${listed} reviewed ${kind} step${listed === 1 ? \"\" : \"s\"} and ${active} layer${active === 1 ? \"\" : \"s\"} of that family are already active; stacking beyond the reviewed plan is refused.` };\n return { allowed: true };\n}\n\n/** True when one approved location consent of that origin covers the reviewed coordinates; the prompt shows the exact latitude and longitude before emulatelocate applies. */\nexport function locationconsentgate(origin: string, latitude: number, longitude: number, consents: locationconsent[]): policyevaluation {\n if (consents.some(consent => consent.origin === origin && consent.revokedat !== undefined)) return { allowed: false, reason: `The location consent on ${origin} was revoked; approve a new prompt before the location override runs again.` };\n if (locationconsentcovers(origin, latitude, longitude, consents)) return { allowed: true };\n return { allowed: false, reason: `The location override of ${latitude}, ${longitude} on ${origin} needs the reviewed location consent first; approve the prompt with the coordinates shown in the review panel.` };\n}\n\n/** Exposes the user configured retention window for reverted emulation layer states; an absent window keeps every prior state while the layer history always survives. */\nexport function emulationretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.emulationretention;\n}\n\n/** Validates the reviewed emulation parameter grammar of the 1.1.48 family: device presets with width, height, pixel ratio and the mobile flag plus the reviewed reload flag, network presets with latency, download and upload bounds and the offline window, location presets inside the latitude and longitude ranges behind the location consent, agent presets of the reviewed user agent grammar with platform and brand list, permission overrides of the reviewed browser permission set graded by name, blackbox rules of explicit origin patterns with their trace scope, and the reviewed revert plan beside every layer. */\nfunction validateemulationgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (revertplanof(options.revertplan) === undefined) return { allowed: false, reason: `Every ${kind} layer needs a reviewed revert plan before any mask applies.` };\n if (kind === \"emulatedevice\") {\n const preset = devicepresetof(options.device);\n if (!preset) return { allowed: false, reason: \"The device layer needs a reviewed preset with a name, positive integer width and height and a positive pixel ratio.\" };\n if (options.reload !== undefined && typeof options.reload !== \"boolean\") return { allowed: false, reason: \"The reviewed reload flag must be a boolean; the page reloads only when the reviewed plan asks.\" };\n return { allowed: true };\n }\n if (kind === \"emulatenetwork\") {\n const preset = networkpresetof(options.network);\n if (!preset) return { allowed: false, reason: \"The network layer needs a reviewed preset with a name and zero or positive latency, download and upload bounds.\" };\n if (options.window !== undefined && (typeof options.window !== \"number\" || !Number.isFinite(options.window) || options.window < 0)) return { allowed: false, reason: \"The reviewed offline window must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"emulatelocate\") {\n const preset = locationpresetof(options.location);\n if (!preset) return { allowed: false, reason: \"The location layer needs a reviewed preset with a name, a latitude inside -90 and 90, a longitude inside -180 and 180 and a zero or positive accuracy radius.\" };\n if (!locationrangevalid(preset.latitude, preset.longitude)) return { allowed: false, reason: \"The reviewed latitude must stay inside -90 and 90 degrees and the longitude inside -180 and 180 degrees.\" };\n return { allowed: true };\n }\n if (kind === \"setuseragent\") {\n const preset = agentpresetof(options.agent);\n if (!preset) return { allowed: false, reason: \"The agent layer needs a reviewed preset with a user agent string of the reviewed grammar, a platform and a non-empty brand list.\" };\n if (!agentgrammarvalid(preset.useragent)) return { allowed: false, reason: \"The reviewed user agent string must use the reviewed grammar of tokens, separators and version marks without line breaks.\" };\n return { allowed: true };\n }\n if (kind === \"overridepermission\") {\n const grant = permissiongrantof(options.permission);\n if (!grant) return { allowed: false, reason: `The permission override needs a reviewed name of the browser permission set (${browserpermissions.join(\", \")}) and a state of ${permissionstates.join(\", \")}.` };\n void permissiongrade(grant.name);\n return { allowed: true };\n }\n if (kind === \"blackboxscripts\") {\n const rules = Array.isArray(options.rules) ? options.rules.flatMap(rule => { const parsed = blackboxruleof(rule); return parsed !== undefined ? [parsed] : []; }) : [];\n if (rules.length === 0) return { allowed: false, reason: \"The blackbox layer needs a reviewed non-empty rule list where every pattern names its origin explicitly and carries a trace scope.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Validates one permission override name against the reviewed browser permission set. */\nexport function permissionnamevalid(name: string): policyevaluation {\n if (!browserpermissions.includes(name)) return { allowed: false, reason: `The permission ${name} stays outside the reviewed browser permission set: ${browserpermissions.join(\", \")}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed session parameter grammar of the 1.1.49 memory family: snapshot plans with the scope, the section toggles of the reviewed grammar and the optional auto interval whose period, maximum snapshot count and expiry stay user choices with no code ceiling, restore plans with their tab, form and capture policies behind the explicit restore review, session filings with unique reviewed names and folders, diffs of two saved records, searches with the term grammar and the field set, exports behind the explicit export review and imports of the known file format behind the full record review. */\nfunction validatesessiongrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"persiststate\") {\n if (options.resume !== undefined && typeof options.resume !== \"boolean\") return { allowed: false, reason: \"The reviewed resume flag must be a boolean.\" };\n return { allowed: true };\n }\n if (kind === \"capturesession\") {\n const plan = snapshotplanof(options.snapshot);\n if (!plan) return { allowed: false, reason: \"The session capture needs a reviewed snapshot plan with its scope, a non-empty section list of the reviewed grammar (tabs, scroll, forms, storage, cookies) and the capture link flag.\" };\n if (plan.auto !== undefined) {\n const interval = autointervalof((options.snapshot as Record<string, unknown>).auto);\n if (interval === undefined) return { allowed: false, reason: \"The reviewed auto snapshot interval needs a positive period, a positive maximum snapshot count and a zero or positive expiry window with no code ceiling.\" };\n }\n return { allowed: true };\n }\n if (kind === \"restoresession\") {\n if (typeof options.sessionid !== \"string\" || !options.sessionid.trim()) return { allowed: false, reason: \"The session restore needs the reviewed session id of the saved record.\" };\n if (restoreplanof(options.restore) === undefined) return { allowed: false, reason: \"The session restore needs a reviewed restore plan with its tab, form and capture policies.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every session restore needs the explicit restore review with its tabs, form state and captures listed before it reopens anything.\" };\n return { allowed: true };\n }\n if (kind === \"namedsessions\") {\n if (typeof options.sessionid !== \"string\" || !options.sessionid.trim()) return { allowed: false, reason: \"The session filing needs the reviewed session id of the saved record.\" };\n if (typeof options.name !== \"string\" || !options.name.trim()) return { allowed: false, reason: \"The session filing needs a reviewed non-empty session name.\" };\n if (options.folder !== undefined && (typeof options.folder !== \"string\" || !options.folder.trim())) return { allowed: false, reason: \"The reviewed folder name must be a non-empty string.\" };\n if (options.tags !== undefined && (!Array.isArray(options.tags) || !options.tags.every(tag => typeof tag === \"string\" && tag.trim()))) return { allowed: false, reason: \"The reviewed tag list must be a list of non-empty strings.\" };\n return { allowed: true };\n }\n if (kind === \"diffsessions\") {\n if (typeof options.left !== \"string\" || !options.left.trim() || typeof options.right !== \"string\" || !options.right.trim()) return { allowed: false, reason: \"The session diff needs the reviewed ids of both saved sessions.\" };\n return { allowed: true };\n }\n if (kind === \"searchsessions\") {\n if (searchqueryof(options.query) === undefined) return { allowed: false, reason: \"The session search needs a reviewed query with a non-empty term list, fields of the reviewed grammar (urls, titles, names, text) and an optional time window.\" };\n return { allowed: true };\n }\n if (kind === \"exportsessions\") {\n if (options.reviewed !== true) return { allowed: false, reason: \"Session exports need the explicit export review before any session file leaves the device.\" };\n if (options.ids !== undefined && (!Array.isArray(options.ids) || options.ids.length === 0 || !options.ids.every(id => typeof id === \"string\" && id.trim()))) return { allowed: false, reason: \"The reviewed export id list must be a non-empty list of saved session ids.\" };\n return { allowed: true };\n }\n if (kind === \"importsessions\") {\n if (options.reviewed !== true) return { allowed: false, reason: \"Session imports need the explicit full record review before any record joins the library.\" };\n if (importsessionfile(options.file) === undefined) return { allowed: false, reason: \"The session import needs a reviewed file of the known format version with an intact checksum.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Requires the explicit restore review flag and the reviewed restore plan before any session restore reopens a tab; the review lists every tab, form state and capture first. */\nexport function restorereviewgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (restoreplanof(options.restore) === undefined) return { allowed: false, reason: \"Every session restore needs a reviewed restore plan with its tab, form and capture policies.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The session restore needs the explicit restore review of its tabs, form state and captures before it reopens anything.\" };\n return { allowed: true };\n}\n\n/** The session consent gate of every session memory step: a live session, an approved plan and the restore review of every restore; crash restore prompts stay inside the same consent model. */\nexport function sessionrestoregate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"run the session memory step\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Session memory steps need an approved plan before they run.\" };\n if (input.step.kind === \"restoresession\") return restorereviewgranted(input.step);\n return { allowed: true };\n}\n\n/** Returns the origins a restore reopens outside the grants so the restore skips and reports them; captures and cookies restore only with their origin grants. */\nexport function restoreoriginsgranted(urls: string[], grants: string[]): { allowed: boolean; skippedorigins: string[] } {\n const covered = new Set(grants);\n const skippedorigins: string[] = [];\n for (const url of urls) {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { origin = \"\"; }\n if (!origin || !covered.has(origin)) skippedorigins.push(origin || url);\n }\n return { allowed: skippedorigins.length === 0, skippedorigins: [...new Set(skippedorigins)] };\n}\n\n/** Requires session names to stay unique inside the library so a filing never shadows another saved session. */\nexport function sessionnameunique(name: string, records: Array<{ id: string; name: string }>, recordid?: string): policyevaluation {\n if (records.some(record => record.name === name && record.id !== recordid)) return { allowed: false, reason: `The session name ${name} already exists in the library; review a unique name.` };\n return { allowed: true };\n}\n\n/** Requires folder names to stay unique inside the folder tree so one folder never shadows another. */\nexport function sessionfolderunique(name: string, folders: Array<{ name: string }>): policyevaluation {\n if (folders.some(folder => folder.name === name)) return { allowed: false, reason: `The folder name ${name} already exists in the library; review a unique folder name.` };\n return { allowed: true };\n}\n\n/** Exposes the user configured retention window for saved session sections; an absent window keeps every section and no code ceiling applies. */\nexport function snapshotretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.sessionretention;\n}\n\n/** Validates the reviewed workflow parameter grammar of the 1.1.50 and 1.1.51 families: composition with the expanded block list so no step stays hidden, shareable step templates, workflow runs behind the explicit run review, dry runs of the known workflow, jittered delays and element waits of user configured bounds with no code ceiling, expressions whose operators match the operand kinds and result kinds, regex rules of bounded backtracking shapes applied to reviewed text, and the control flow payloads of conditionals, branching, loops with user configured safety bounds, foreach selectors, parallel branches with join policies and try catch with retry and timeout policies whose child kinds all stay inside the reviewed vocabulary. */\nfunction validateworkflowgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"composeworkflow\") {\n const payload = options.workflow;\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return { allowed: false, reason: \"The workflow composition needs the reviewed workflow payload with its name, version, origins, steps and blocks.\" };\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !candidate.name.trim()) return { allowed: false, reason: \"The workflow composition needs a reviewed non-empty name.\" };\n if (typeof candidate.version !== \"number\" || !Number.isInteger(candidate.version) || candidate.version < 1) return { allowed: false, reason: \"The workflow version must be a positive integer.\" };\n if (!Array.isArray(candidate.origins) || candidate.origins.length === 0 || !candidate.origins.every(origin => typeof origin === \"string\" && origin.startsWith(\"https://\"))) return { allowed: false, reason: \"The workflow needs at least one granted HTTPS origin so every step stays inside the grants.\" };\n if (!Array.isArray(candidate.steps) || candidate.steps.length === 0 || !candidate.steps.every(entry => workflowstepof(entry) !== undefined || (entry && typeof entry === \"object\" && typeof (entry as Record<string, unknown>).block === \"string\"))) return { allowed: false, reason: \"The workflow needs a non-empty reviewed step list of the workflow step grammar or block invocations.\" };\n const blocks = Array.isArray(candidate.blocks) ? candidate.blocks.flatMap(block => { const parsed = workflowblockof(block); return parsed !== undefined ? [parsed] : []; }) : [];\n if (Array.isArray(candidate.blocks) && blocks.length !== (candidate.blocks as unknown[]).length) return { allowed: false, reason: \"The reviewed block list must carry unique lowercase names, labels and valid child steps.\" };\n try {\n const record = composeworkflow({ name: candidate.name, version: candidate.version, origins: candidate.origins as string[], steps: (candidate.steps as Array<Record<string, unknown>>).map(entry => \"block\" in entry ? { block: entry.block as string, label: typeof entry.label === \"string\" ? entry.label : entry.block as string } : workflowstepof(entry) as workflowstep), blocks, now: 0, kindallowed: candidatekind => { try { actionrisk(candidatekind as actionkind); return true; } catch { return false; } }, riskof: candidatekind => actionrisk(candidatekind as actionkind) });\n const inputs = Array.isArray(candidate.inputs) ? candidate.inputs.flatMap(name => typeof name === \"string\" ? [name] : []) : undefined;\n const checked = validateworkflow(record, { kindallowed: workflowkind => { try { actionrisk(workflowkind as actionkind); return true; } catch { return false; } }, ...(inputs !== undefined ? { inputs } : {}) });\n if (!checked.allowed) return checked;\n } catch (error) {\n return { allowed: false, reason: error instanceof Error ? error.message : \"The workflow payload failed its composition validation.\" };\n }\n return { allowed: true };\n }\n if (kind === \"savetemplate\") {\n const payload = options.template && typeof options.template === \"object\" && !Array.isArray(options.template) ? options.template as Record<string, unknown> : {};\n const template = steptemplateof({ id: \"templatereview\", origin: \"https://example.com\", sharedat: 0, ...payload });\n if (!template) return { allowed: false, reason: \"The step template needs a reviewed name and a valid workflow step it shares across workflows.\" };\n return { allowed: true };\n }\n if (kind === \"runworkflow\") {\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"The workflow run needs the reviewed id of the composed workflow.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes.\" };\n if (options.variables !== undefined && (!options.variables || typeof options.variables !== \"object\" || Array.isArray(options.variables) || !Object.values(options.variables).every(value => typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\"))) return { allowed: false, reason: \"The reviewed run variables must be an object of string, number or boolean values.\" };\n return { allowed: true };\n }\n if (kind === \"dryrun\") {\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"The dry run needs the reviewed id of the composed workflow.\" };\n return { allowed: true };\n }\n if (kind === \"delay\") {\n const delay = options.delay;\n if (!delay || typeof delay !== \"object\" || Array.isArray(delay)) return { allowed: false, reason: \"The delay needs a reviewed base and jitter window in options.\" };\n const reviewed = delay as Record<string, unknown>;\n if (typeof reviewed.base !== \"number\" || !Number.isFinite(reviewed.base) || reviewed.base < 0) return { allowed: false, reason: \"The reviewed delay base must be zero or a positive number of milliseconds.\" };\n if (typeof reviewed.jitter !== \"number\" || !Number.isFinite(reviewed.jitter) || reviewed.jitter < 0) return { allowed: false, reason: \"The reviewed delay jitter window must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"waitelement\") {\n const wait = options.wait;\n if (!wait || typeof wait !== \"object\" || Array.isArray(wait)) return { allowed: false, reason: \"The element wait needs a reviewed selector, timeout and poll interval in options.\" };\n const reviewed = wait as Record<string, unknown>;\n if (typeof reviewed.selector !== \"string\" || !reviewed.selector.trim()) return { allowed: false, reason: \"The element wait needs a reviewed non-empty selector.\" };\n if (typeof reviewed.timeout !== \"number\" || !Number.isFinite(reviewed.timeout) || reviewed.timeout < 0) return { allowed: false, reason: \"The reviewed element wait timeout must be zero or a positive number of milliseconds with no code ceiling.\" };\n if (typeof reviewed.poll !== \"number\" || !Number.isFinite(reviewed.poll) || reviewed.poll < 0) return { allowed: false, reason: \"The reviewed element wait poll interval must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"compute\") {\n const expression = expressionof(options.expression);\n if (!expression) return { allowed: false, reason: `The expression step needs a reviewed expression with operands, an operator of the reviewed set (${expressionoperators.join(\", \")}) and a result variable of a reviewed kind.` };\n const operatorcheck = validatexpressionoperators(expression);\n if (!operatorcheck.allowed) return operatorcheck;\n return { allowed: true };\n }\n if (kind === \"extractvars\") {\n const rule = regexruleof(options.rule);\n if (!rule) return { allowed: false, reason: \"The variable extraction needs a reviewed regex rule with its pattern, flags and named capture groups.\" };\n const shapecheck = validateregexrule(rule.pattern);\n if (!shapecheck.allowed) return shapecheck;\n if (typeof options.text !== \"string\") return { allowed: false, reason: \"The variable extraction needs the reviewed text the regex rule applies to.\" };\n return { allowed: true };\n }\n if (kind === \"condition\") {\n const condition = conditionof(options.condition);\n if (!condition) return { allowed: false, reason: \"The condition step needs a reviewed boolean expression in its options.\" };\n const operatorcheck = validatexpressionoperators(condition.expression);\n if (!operatorcheck.allowed) return operatorcheck;\n return { allowed: true };\n }\n if (kind === \"branch\") {\n const branch = branchof(options.branch);\n if (!branch) return { allowed: false, reason: \"The branch step needs reviewed unique paths with boolean match expressions and an else path in its options so every branch terminates.\" };\n for (const path of [...branch.paths, branch.else]) {\n if (path.when === undefined) continue;\n const operatorcheck = validatexpressionoperators(path.when);\n if (!operatorcheck.allowed) return operatorcheck;\n }\n return controlchildkinds(step);\n }\n if (kind === \"loop\") {\n const loop = loopof(options.loop);\n if (!loop) return { allowed: false, reason: \"The loop step needs a reviewed list variable, distinct item and index variables, an optional positive safety bound and a non-empty body in its options; an absent bound keeps the documented default.\" };\n return controlchildkinds(step);\n }\n if (kind === \"repeatuntil\") {\n const repeat = repeatuntilof(options.repeatuntil);\n if (!repeat) return { allowed: false, reason: \"The repeat until step needs a reviewed convergence expression, an optional positive safety bound and a non-empty body in its options.\" };\n const operatorcheck = validatexpressionoperators(repeat.until);\n if (!operatorcheck.allowed) return operatorcheck;\n return controlchildkinds(step);\n }\n if (kind === \"whileloop\") {\n const condition = whileof(options.while);\n if (!condition) return { allowed: false, reason: \"The while step needs a reviewed condition, a mandatory positive safety bound and a non-empty body in its options; a while loop without a safety bound is refused.\" };\n const operatorcheck = validatexpressionoperators(condition.while);\n if (!operatorcheck.allowed) return operatorcheck;\n return controlchildkinds(step);\n }\n if (kind === \"foreach\") {\n const foreach = foreachof(options.foreach);\n if (!foreach) return { allowed: false, reason: \"The foreach step needs a reviewed non-empty selector, distinct item and index variables and a non-empty body in its options.\" };\n return controlchildkinds(step);\n }\n if (kind === \"parallel\") {\n const parallel = parallelof(options.parallel);\n if (!parallel) return { allowed: false, reason: \"The parallel step needs uniquely identified branches with bodies and a join policy of the first, last or fail strategy with cancel or continue on branch failure in its options.\" };\n return controlchildkinds(step);\n }\n if (kind === \"trycatch\") {\n const fragile = tryof(options.try);\n if (!fragile) return { allowed: false, reason: \"The try step needs a fragile body, a catch handler and optional retry and timeout policies in its options: attempts stay user configured with no code ceiling, backoff is fixed or exponential and budgets are positive.\" };\n return controlchildkinds(step);\n }\n return { allowed: true };\n}\n\n/** Checks every child step of a control payload against the reviewed action vocabulary so no control construct hides an unreviewed kind behind its body. */\nfunction controlchildkinds(step: toolstep): policyevaluation {\n const children = controlsteps({ id: step.id, kind: step.kind, label: step.summary, ...(step.options !== undefined ? { options: step.options } : {}) });\n for (const child of children) {\n try { actionrisk(child.kind); } catch { return { allowed: false, reason: `The ${child.kind} step inside the control payload of the ${step.kind} step is not a reviewed action kind.` }; }\n }\n return { allowed: true };\n}\n\n/** Rejects unbounded backtracking shapes of reviewed regex patterns: a quantified group whose body itself ends with an unbounded quantifier can explode on adversarial text, so the shape is refused while bounded repetitions stay user choices. */\nexport function validateregexrule(pattern: string): policyevaluation {\n try { new RegExp(pattern); } catch { return { allowed: false, reason: \"The reviewed regex pattern does not compile.\" }; }\n const nestedquantifier = /\\((?:[^()\\\\]|\\\\.)*[+*}]\\)[+*{]/.test(pattern) || /\\(\\)[+*{]/.test(pattern);\n if (nestedquantifier) return { allowed: false, reason: \"The reviewed regex pattern nests an unbounded quantifier inside a quantified group and is refused because adversarial text could explode the backtracking.\" };\n const unboundedrepeat = /\\{\\d+,\\}/.test(pattern);\n if (unboundedrepeat && /\\([^)]*\\{\\d+,\\}[^)]*\\)[+*{]/.test(pattern)) return { allowed: false, reason: \"The reviewed regex pattern repeats an unbounded group and is refused because adversarial text could explode the backtracking.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed expression operators against the operand kinds and the result kind: arithmetic needs numbers and returns numbers, logic needs booleans and returns booleans, comparison needs numbers and returns booleans, text operators return strings or booleans and length returns a number. */\nfunction validatexpressionoperators(expression: import(\"./types.js\").expressiontype): policyevaluation {\n const numeric = new Set([\"add\", \"subtract\", \"multiply\", \"divide\", \"modulo\"]);\n const logic = new Set([\"and\", \"or\", \"not\"]);\n const comparison = new Set([\"less\", \"greater\", \"lessequal\", \"greaterequal\"]);\n const text = new Set([\"concat\", \"contains\"]);\n const operator = expression.operator;\n if (numeric.has(operator)) {\n for (const operand of [expression.left, expression.right]) {\n if (operand === undefined) continue;\n if (operand.literal !== undefined && typeof operand.literal === \"boolean\") return { allowed: false, reason: `The ${operator} operator needs numeric operands; boolean literals are refused.` };\n }\n if (expression.resultkind !== \"number\" && expression.resultkind !== \"string\") return { allowed: false, reason: `The ${operator} operator needs a number result kind.` };\n }\n if (logic.has(operator)) {\n for (const operand of [expression.left, expression.right]) {\n if (operand === undefined) continue;\n if (operand.literal !== undefined && typeof operand.literal !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs boolean operands; non boolean literals are refused.` };\n }\n if (expression.resultkind !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };\n if (operator === \"not\" && expression.right !== undefined) return { allowed: false, reason: \"The not operator takes one operand only.\" };\n }\n if (comparison.has(operator) && expression.resultkind !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };\n if (text.has(operator) && expression.resultkind !== \"boolean\" && expression.resultkind !== \"string\") return { allowed: false, reason: `The ${operator} operator needs a string or boolean result kind.` };\n if (operator === \"contains\" && expression.resultkind !== \"boolean\") return { allowed: false, reason: \"The contains operator needs a boolean result kind.\" };\n if (operator === \"length\") {\n if (expression.right !== undefined) return { allowed: false, reason: \"The length operator takes one operand only.\" };\n if (expression.resultkind !== \"number\") return { allowed: false, reason: \"The length operator needs a number result kind.\" };\n }\n if ((operator === \"equal\" || operator === \"notequal\") && !new Set([\"boolean\", \"string\", \"number\"]).has(expression.resultkind)) return { allowed: false, reason: \"The equality operator needs a primitive result kind.\" };\n return { allowed: true };\n}\n\n/** The workflow consent gate: a live session, an approved plan and the explicit run review of every real run; dry runs stay read only inside the same session and plan gates. */\nexport function workflowgate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"run the workflow step\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Workflow steps need the approved plan review before they run.\" };\n if (input.step.kind === \"runworkflow\") {\n let runoptions: Record<string, unknown> = {};\n try { runoptions = parseoptions(input.step); } catch { runoptions = {}; }\n if (runoptions.reviewed !== true) return { allowed: false, reason: \"Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed trigger parameter grammar of the 1.1.52 family: every kind arms exactly one rule behind the explicit arm review, the workflow reference must name a composed workflow, the match payloads follow their family grammar \u2014 visit origins and url list entries must be HTTPS urls, url patterns must parse as HTTPS globs, cron expressions must parse as five field schedules with named weekdays and months and a resolvable timezone, interval periods stay positive with zero or positive jitter, webhook secrets must clear the documented entropy floor with a non-empty payload schema, event names must come from the observed event catalog and context menu titles stay non-empty \u2014 while cooldown windows stay user configured positive values with the documented default of the webhook and event families winning only when the review configures none. */\nfunction validatetriggergrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const family = triggerfamilyof(step.kind);\n if (family === undefined) return { allowed: false, reason: \"The trigger step is not a reviewed trigger kind.\" };\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"Every trigger rule needs the reviewed id of the composed workflow it launches.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every trigger rule needs the explicit arm review with its match fields and bound workflow shown before it arms.\" };\n if (options.label !== undefined && (typeof options.label !== \"string\" || !options.label.trim())) return { allowed: false, reason: \"The reviewed trigger label must be a non-empty string.\" };\n if (options.cooldown !== undefined && (typeof options.cooldown !== \"number\" || !Number.isFinite(options.cooldown) || options.cooldown <= 0)) return { allowed: false, reason: \"The reviewed cooldown window must be a positive number of milliseconds with no code ceiling; the webhook and event families keep the documented default when the review configures none.\" };\n const payload = options.rule;\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return { allowed: false, reason: `The ${step.kind} step needs its reviewed rule payload in options.` };\n if (triggerpayloadof(family, payload) === undefined) {\n if (family === \"visit\") return { allowed: false, reason: \"The visit rule needs a non-empty reviewed list of HTTPS origins it fires on.\" };\n if (family === \"url\") return { allowed: false, reason: \"The url rule needs a reviewed HTTPS glob url pattern; `*` spans one path segment and `**` spans across segments.\" };\n if (family === \"menu\") return { allowed: false, reason: \"The menu rule needs a reviewed non-empty context menu entry title.\" };\n if (family === \"key\") return { allowed: false, reason: \"The keyboard shortcut rule needs a reviewed lowercase command name and an optional suggested key binding.\" };\n if (family === \"cron\") return { allowed: false, reason: \"The cron rule needs a reviewed five field cron expression of minutes, hours, days, months and weekdays with named weekdays and months and an optional resolvable timezone; unparseable schedules are refused.\" };\n if (family === \"interval\") return { allowed: false, reason: \"The interval rule needs a reviewed positive period in milliseconds with an optional zero or positive jitter window.\" };\n if (family === \"urllist\") return { allowed: false, reason: \"The url list rule needs a reviewed non-empty list of HTTPS urls its workflow runs across.\" };\n if (family === \"webhook\") return { allowed: false, reason: `The webhook rule needs a reviewed shared secret of at least twenty four characters mixing letters and digits and a non-empty payload schema of named string, number or boolean fields.` };\n if (family === \"event\") return { allowed: false, reason: `The page event rule needs a reviewed non-empty list of event names of the observed event catalog: ${triggereventcatalog.join(\", \")}.` };\n return { allowed: false, reason: \"The trigger rule payload does not follow its family grammar.\" };\n }\n if (family === \"cron\") {\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.cron === \"string\" && cronparse(candidate.cron) === undefined) return { allowed: false, reason: \"The cron expression does not parse as a five field schedule and is refused.\" };\n }\n if (family === \"webhook\") {\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.secret === \"string\" && !webhooksecretok(candidate.secret)) return { allowed: false, reason: \"The webhook shared secret must hold at least twenty four characters mixing letters and digits; the entropy floor is a floor, never a cap.\" };\n }\n const armed = armrule({ family, workflowid: options.workflowid, ...(typeof options.label === \"string\" && options.label.trim() ? { label: options.label } : {}), payload, ...(typeof options.cooldown === \"number\" ? { cooldown: options.cooldown } : {}), now: 0 });\n if (armed === undefined) return { allowed: false, reason: \"The trigger rule payload does not arm as a reviewed rule.\" };\n return { allowed: true };\n}\n\n/** The trigger consent gate: a live session, an approved plan and the explicit arm review of every rule; automatic launchers never arm outside the consent gates. */\nexport function triggergate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"arm the trigger rule\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Trigger rules need the approved plan review before they arm.\" };\n let triggeroptions: Record<string, unknown> = {};\n try { triggeroptions = parseoptions(input.step); } catch { triggeroptions = {}; }\n if (triggeroptions.reviewed !== true) return { allowed: false, reason: \"Every trigger rule needs the explicit arm review with its match fields and bound workflow shown before it arms.\" };\n return { allowed: true };\n}\n\n/** Returns the match origins of one reviewed trigger rule so callers can keep every rule inside the workflow grant list; triggers on origins outside the grants are refused. */\nexport function triggerorigins(step: toolstep): string[] {\n let triggeroptions: Record<string, unknown> = {};\n try { triggeroptions = parseoptions(step); } catch { return []; }\n const family = triggerfamilyof(step.kind);\n if (family === undefined) return [];\n const armed = armrule({ family, workflowid: typeof triggeroptions.workflowid === \"string\" ? triggeroptions.workflowid : \"\", payload: triggeroptions.rule, ...(typeof triggeroptions.cooldown === \"number\" ? { cooldown: triggeroptions.cooldown } : {}), now: 0 });\n if (armed === undefined) return [];\n const origins: string[] = [];\n for (const origin of armed.origins ?? []) origins.push(origin);\n if (armed.pattern !== undefined) { try { origins.push(new URL(armed.pattern).origin); } catch { /* the pattern grammar already refused unparseable patterns */ } }\n for (const url of armed.urls ?? []) { try { origins.push(new URL(url).origin); } catch { /* the url list grammar already refused unparseable urls */ } }\n return [...new Set(origins)];\n}\n\n/** Returns the read only projection of one workflow step for dry runs: read class steps report their would be outcome while interaction and mutation steps carry no projection and the dry run refuses them; a control step projects only when every child step of its payload grades read. */\nexport function dryrunprojection(step: workflowstep): string | undefined {\n if (iscontrolflowkind(step.kind)) {\n for (const child of controlsteps(step)) {\n const childrisk = resolvedrisk({ id: child.id, kind: child.kind, summary: child.label, risk: \"read\", ...(child.target !== undefined ? { target: child.target } : {}), ...(child.value !== undefined ? { value: child.value } : {}), ...(child.options !== undefined ? { options: child.options } : {}) });\n if (childrisk !== \"read\") return undefined;\n }\n if (step.kind === \"condition\") return \"The condition step would evaluate its reviewed expression over the extracted values with no page side effect.\";\n if (step.kind === \"branch\") return \"The branch step would choose one reviewed path by page state and only the chosen path would run.\";\n if (step.kind === \"loop\") return \"The loop step would iterate its reviewed list binding the item and index variables per iteration inside the safety bound.\";\n if (step.kind === \"repeatuntil\") return \"The repeat until step would rerun its body until the convergence expression holds inside the safety bound.\";\n if (step.kind === \"whileloop\") return \"The while step would loop while its condition holds inside the reviewed safety bound.\";\n if (step.kind === \"foreach\") return \"The foreach step would iterate the elements of its reviewed selector binding the item and index variables per iteration.\";\n if (step.kind === \"parallel\") return \"The parallel step would run its branches concurrently and join their outcomes under the reviewed strategy.\";\n return \"The try step would run its fragile body and only the catch handler on failure.\";\n }\n const risk = resolvedrisk({ id: step.id, kind: step.kind, summary: step.label, risk: \"read\", ...(step.target !== undefined ? { target: step.target } : {}), ...(step.value !== undefined ? { value: step.value } : {}), ...(step.options !== undefined ? { options: step.options } : {}) });\n if (risk !== \"read\") return undefined;\n if (step.kind === \"delay\") return `The delay step would sleep its reviewed base inside the jitter window.`;\n if (step.kind === \"waitelement\") return `The element wait step would poll ${step.target ?? \"the reviewed selector\"} until appearance or the reviewed timeout.`;\n if (step.kind === \"compute\") return `The compute step would evaluate its reviewed expression into the result variable.`;\n if (step.kind === \"extractvars\") return `The variable extraction step would apply its reviewed regex rule and store the named captures.`;\n return `The ${step.kind} step would run read only and mutate nothing.`;\n}\n\n/** Validates one reviewed permission state of an override. */\nexport function permissionstatevalid(state: string): policyevaluation {\n if (!permissionstates.includes(state as permissionstate)) return { allowed: false, reason: `The reviewed permission state must be one of ${permissionstates.join(\", \")}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed devtools parameter grammar of the 1.1.46 family: enabled domains bounded by the reviewed domain grammar, the required teardown plan of every attach, raw commands of the Domain.method form, domain event rules with match filters inside the reviewed watch window, breakpoints with conditions of the reviewed expression grammar, step modes, reviewed watch expressions, and script overrides with the explicit reviewed flag and a url pattern that names its origin. */\nfunction validatecdpgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"attachcdp\") {\n if (!Array.isArray(options.domains) || options.domains.length === 0 || !options.domains.every((domain): domain is string => typeof domain === \"string\" && cdpdomains.includes(domain))) return { allowed: false, reason: `The attach needs a non-empty enabled domain list of the reviewed domain grammar: ${cdpdomains.join(\", \")}.` };\n if (teardownplanof(options.teardown) === undefined) return { allowed: false, reason: \"Every attach needs a reviewed teardown plan with its revert steps and resume policy before approval.\" };\n if (options.allowlist !== undefined) {\n const allowlist = cdpallowlistof(options.allowlist);\n if (!allowlist || !allowlist.domains.every(domain => (options.domains as string[]).includes(domain))) return { allowed: false, reason: \"The reviewed method allowlist must stay inside the enabled domains of the attach.\" };\n }\n const budgetcheck = debugwaitbudgetallowed(typeof options.wait === \"number\" ? options.wait : undefined, undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"detachcdp\") return { allowed: true };\n if (kind === \"cdpcmd\") {\n const command = options.command && typeof options.command === \"object\" && !Array.isArray(options.command) ? options.command as Record<string, unknown> : undefined;\n if (!command || typeof command.method !== \"string\" || methoddomain(command.method) === undefined) return { allowed: false, reason: \"The raw command needs a reviewed method of the Domain.method form.\" };\n if (command.params !== undefined && (typeof command.params !== \"object\" || Array.isArray(command.params))) return { allowed: false, reason: \"The raw command params must be a JSON object.\" };\n if (command.resultpath !== undefined && typeof command.resultpath !== \"string\") return { allowed: false, reason: \"The reviewed result path must be a dotted path string.\" };\n return { allowed: true };\n }\n if (kind === \"watchcdp\") {\n if (!Array.isArray(options.events) || options.events.length === 0 || !options.events.every(rule => cdpeventruleof(rule) !== undefined)) return { allowed: false, reason: \"The event watch needs a non-empty reviewed list of domain event rules of the reviewed domain grammar.\" };\n let watchwindow: number | undefined;\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed event watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined) {\n if (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0) return { allowed: false, reason: \"The reviewed event watch window must be zero or a positive number of milliseconds.\" };\n watchwindow = reviewed.window;\n }\n }\n if (watchwindow === undefined) return { allowed: false, reason: \"The event watch needs a reviewed lifetime window before any domain event is observed.\" };\n const budgetcheck = debugwaitbudgetallowed(watchwindow, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"setbreakpoint\") {\n const breakpoint = breakpointinputof(options.breakpoint);\n if (!breakpoint) return { allowed: false, reason: \"The breakpoint needs a reviewed script url and a zero based line.\" };\n if (!ishttpsurl(breakpoint.url)) return { allowed: false, reason: \"The breakpoint script url must be a reviewed HTTPS url.\" };\n if (breakpoint.condition !== undefined) {\n const conditioncheck = validatebreakpointcondition(breakpoint.condition);\n if (!conditioncheck.allowed) return conditioncheck;\n }\n return { allowed: true };\n }\n if (kind === \"stepcode\") {\n if (stepmodeof(options.mode) === undefined) return { allowed: false, reason: \"The step code mode must be one of stepover, stepinto, stepout or resume.\" };\n return { allowed: true };\n }\n if (kind === \"watchexpr\") {\n if (watchexpressionof(options.expression) === undefined) return { allowed: false, reason: \"The watch expression needs the reviewed expression text.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Watch expressions must be reviewed before evaluation; set the explicit reviewed flag on the step.\" };\n return { allowed: true };\n }\n if (kind === \"overridescript\") {\n const override = overrideinputof(options.override);\n if (!override) return { allowed: false, reason: \"The script override needs a reviewed url pattern and its full fixture source.\" };\n if (patternorigin(override.urlpattern) === undefined) return { allowed: false, reason: \"Script overrides without a named https origin pattern are refused.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The full fixture source must be reviewed before the script override runs; set the explicit reviewed flag on the step.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed profiling parameter grammar of the 1.1.47 family: flow specs of the reviewed metric set inside a reviewed watch window, heap snapshots with the user chosen interval only, growth tracking with the reviewed slope, cpu profiles bounded by the reviewed wait budget, layout shift watches with the user chosen window only, trace records bounded by the reviewed category list and byte ceiling, trace annotations that carry step ids, offline replays of stored traces and source map capture scripts of explicit https urls. */\nfunction validateprofilegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"measureflow\") {\n if (flowspecof(options.flow) === undefined) return { allowed: false, reason: `The flow measurement needs a reviewed flow spec with its mark prefix, step window and metric list of the reviewed metric set: navigation, paint, lcp, fid, interaction, blocking.` };\n const watch = options.watch && typeof options.watch === \"object\" && !Array.isArray(options.watch) ? options.watch as Record<string, unknown> : {};\n if (typeof watch.window !== \"number\" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: \"The flow measurement needs a reviewed watch window of zero or more milliseconds.\" };\n const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"heapshot\") {\n const heap = options.heap && typeof options.heap === \"object\" && !Array.isArray(options.heap) ? options.heap as Record<string, unknown> : {};\n if (heap.interval !== undefined && (typeof heap.interval !== \"number\" || !Number.isFinite(heap.interval) || heap.interval < 0)) return { allowed: false, reason: \"The reviewed heap snapshot interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"trackmemory\") {\n const growth = options.growth && typeof options.growth === \"object\" && !Array.isArray(options.growth) ? options.growth as Record<string, unknown> : undefined;\n if (!growth || typeof growth.slope !== \"number\" || !Number.isFinite(growth.slope) || growth.slope < 0) return { allowed: false, reason: \"Memory growth tracking needs the reviewed slope in bytes per millisecond before any sample is flagged.\" };\n if (growth.interval !== undefined && (typeof growth.interval !== \"number\" || !Number.isFinite(growth.interval) || growth.interval < 0)) return { allowed: false, reason: \"The reviewed sampling interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"profilecpu\") {\n const profile = options.profile && typeof options.profile === \"object\" && !Array.isArray(options.profile) ? options.profile as Record<string, unknown> : undefined;\n if (!profile || typeof profile.duration !== \"number\" || !Number.isFinite(profile.duration) || profile.duration < 0) return { allowed: false, reason: \"The cpu profile needs a reviewed duration of zero or more milliseconds.\" };\n const budgetcheck = debugwaitbudgetallowed(profile.duration, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"watchshifts\") {\n const watch = options.watch && typeof options.watch === \"object\" && !Array.isArray(options.watch) ? options.watch as Record<string, unknown> : {};\n if (typeof watch.window !== \"number\" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: \"The layout shift watch needs a reviewed observation window of zero or more milliseconds; the window stays a user choice with no code ceiling.\" };\n if (options.threshold !== undefined && (typeof options.threshold !== \"number\" || !Number.isFinite(options.threshold) || options.threshold < 0)) return { allowed: false, reason: \"The reviewed shift score threshold must be zero or a positive number.\" };\n const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"traceload\") {\n const trace = options.trace && typeof options.trace === \"object\" && !Array.isArray(options.trace) ? options.trace as Record<string, unknown> : undefined;\n if (!trace || !Array.isArray(trace.categories) || trace.categories.length === 0 || !trace.categories.every((category): category is string => typeof category === \"string\" && tracecategories.includes(category))) return { allowed: false, reason: `The trace record needs a non-empty reviewed category list of the reviewed category grammar: ${tracecategories.join(\", \")}.` };\n if (typeof trace.window !== \"number\" || !Number.isFinite(trace.window) || trace.window < 0) return { allowed: false, reason: \"The trace record needs a reviewed window of zero or more milliseconds and stops at the reviewed window end.\" };\n if (trace.exporttarget !== undefined && trace.exporttarget !== \"memory\" && trace.exporttarget !== \"download\") return { allowed: false, reason: \"The trace export target must be memory or download.\" };\n const budgetcheck = debugwaitbudgetallowed(trace.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"annotatetrace\" || kind === \"replaytrace\") {\n const trace = options.trace && typeof options.trace === \"object\" && !Array.isArray(options.trace) ? options.trace as Record<string, unknown> : undefined;\n if (!trace || typeof trace.traceid !== \"string\" || !trace.traceid.trim()) return { allowed: false, reason: `The ${kind === \"annotatetrace\" ? \"trace annotation\" : \"trace replay\"} needs the stored trace id of a recorded trace.` };\n if (kind === \"replaytrace\") return { allowed: true };\n if (!Array.isArray(options.annotations) || options.annotations.length === 0 || !options.annotations.every(annotation => annotationof(annotation) !== undefined)) return { allowed: false, reason: \"Exported traces carry their step annotations: every annotation needs a step id, a label and an optional offset from the trace start.\" };\n return { allowed: true };\n }\n if (kind === \"capturesourcemaps\") {\n if (options.scripts !== undefined) {\n if (!Array.isArray(options.scripts) || options.scripts.length === 0 || !options.scripts.every((url): url is string => typeof url === \"string\" && ishttpsurl(url))) return { allowed: false, reason: \"The source map capture scripts must be a non-empty list of reviewed HTTPS urls.\" };\n }\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Resolves the reviewed cdp allowlist of one plan: the enabled domains and method gates of its attachcdp step, the reviewable contract every later cdp kind of the plan must stay inside. */\nexport function planallowlist(steps: toolstep[]): cdpallowlist | undefined {\n const attach = steps.find(step => step.kind === \"attachcdp\");\n if (!attach) return undefined;\n let options: Record<string, unknown> = {};\n try { options = parseoptions(attach); } catch { options = {}; }\n const domains = Array.isArray(options.domains) ? options.domains.filter((domain): domain is string => typeof domain === \"string\" && cdpdomains.includes(domain)) : [];\n if (domains.length === 0) return undefined;\n const gated = cdpallowlistof(options.allowlist);\n return { domains, ...(gated?.methods !== undefined ? { methods: gated.methods } : {}) };\n}\n\n/** Resolves the reviewed outbound url of a network control step at review time: the form url of postform, the upload url of postfiles and the token url of authflow. */\nexport function controltarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n for (const key of [\"form\", \"upload\"] as const) {\n const value = options[key];\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const url = (value as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n }\n if (step.kind === \"authflow\") {\n const flow = oauthflowof(options.oauth);\n if (flow) return flow.tokenurl;\n }\n return undefined;\n}\n\n/** Resolves the reviewed channel url of a socket step at review time: the socket url of opensocket, the event stream url of subscribesse and the poll url of longpoll. */\nexport function sockettarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n for (const key of [\"socket\", \"subscription\", \"poll\"] as const) {\n const value = options[key];\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const url = (value as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n }\n return undefined;\n}\n\n/** Requires the active tab grant of the live session for every media kind: the session tab and origin must match and the origin grant must cover the active origin. */\nexport function mediagate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the media capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture media.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture media.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The media capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The media capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** Requires an approved recording consent prompt before any recording of user activity starts; every start consumes its own prompt. */\nexport function recordingconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A recording of user activity requires a reviewed consent ref in options before it starts.\" };\n return { allowed: true };\n}\n\n/** Exposes the recording duration window as a user configured choice in milliseconds; an absent window leaves the duration to the reviewed step options with no code ceiling. */\nexport function recordingwindow(settings: runsettings | undefined): number | undefined {\n const window = settings?.recordingwindow;\n return typeof window === \"number\" && Number.isFinite(window) && window > 0 ? window : undefined;\n}\n\n/** Keeps the reviewed lapse plan inside the reviewed wait budget: the whole lapse duration must fit the wait window with no code ceiling on either side. */\nexport function lapsebudgetallowed(interval: number, duration: number, wait: number | undefined): policyevaluation {\n if (!(interval > 0)) return { allowed: false, reason: \"The reviewed lapse interval must be a positive number of milliseconds.\" };\n if (!(duration > 0)) return { allowed: false, reason: \"The reviewed lapse duration must be a positive number of milliseconds.\" };\n if (wait !== undefined && !(wait >= 0)) return { allowed: false, reason: \"The reviewed wait budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && duration > wait) return { allowed: false, reason: `The lapse duration of ${duration} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter duration.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed media capture parameter grammar of the 1.1.41 family: pdf paper sizes, recording scopes and windows, image filters, lapse plans, conversion targets and thumbnail directives stay user choices with no code ceilings. */\nfunction validatemediagrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"capturepdf\") {\n const pdf = options.pdf;\n if (pdf !== undefined) {\n if (!pdf || typeof pdf !== \"object\" || Array.isArray(pdf)) return { allowed: false, reason: \"The reviewed pdf options must be an object in options.pdf.\" };\n const pdfoptions = pdf as Record<string, unknown>;\n if (pdfoptions.paperwidth !== undefined && (typeof pdfoptions.paperwidth !== \"number\" || !Number.isFinite(pdfoptions.paperwidth) || pdfoptions.paperwidth <= 0)) return { allowed: false, reason: \"The reviewed pdf paper width must be a positive number of inches with no code cap.\" };\n if (pdfoptions.paperheight !== undefined && (typeof pdfoptions.paperheight !== \"number\" || !Number.isFinite(pdfoptions.paperheight) || pdfoptions.paperheight <= 0)) return { allowed: false, reason: \"The reviewed pdf paper height must be a positive number of inches with no code cap.\" };\n if (pdfoptions.margins !== undefined) {\n const margins = pdfoptions.margins;\n if (!margins || typeof margins !== \"object\" || Array.isArray(margins)) return { allowed: false, reason: \"The reviewed pdf margins must be an object with top, right, bottom and left inches.\" };\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"]) {\n const value = (margins as Record<string, unknown>)[side];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) return { allowed: false, reason: `The reviewed pdf ${side} margin must be zero or a positive number of inches; negative margins are refused.` };\n }\n }\n if (pdfoptions.scale !== undefined && (typeof pdfoptions.scale !== \"number\" || !Number.isFinite(pdfoptions.scale) || pdfoptions.scale <= 0)) return { allowed: false, reason: \"The reviewed pdf scale must be a positive number with no code cap.\" };\n if (pdfoptions.landscape !== undefined && typeof pdfoptions.landscape !== \"boolean\") return { allowed: false, reason: \"The reviewed pdf landscape flag must be a boolean.\" };\n if (pdfoptions.paginate !== undefined && typeof pdfoptions.paginate !== \"boolean\") return { allowed: false, reason: \"The reviewed pdf paginate flag must be a boolean.\" };\n }\n if (options.breakpoints !== undefined && (!Array.isArray(options.breakpoints) || options.breakpoints.length === 0 || !options.breakpoints.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed pdf break points must be a non-empty list of selectors when present.\" };\n if (options.exporttarget !== undefined && options.exporttarget !== \"memory\" && options.exporttarget !== \"download\") return { allowed: false, reason: \"The reviewed pdf export target must be memory or download; pdf documents do not route to the clipboard.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed pdf artifact name must be a non-empty string.\" };\n }\n if (kind === \"recordscreen\" || kind === \"captureaudio\") {\n const recording = options.recording;\n if (recording !== undefined) {\n if (!recording || typeof recording !== \"object\" || Array.isArray(recording)) return { allowed: false, reason: \"The reviewed recording options must be an object in options.recording.\" };\n const recordoptions = recording as Record<string, unknown>;\n if (recordoptions.scope !== undefined && recordoptions.scope !== \"tab\" && recordoptions.scope !== \"run\") return { allowed: false, reason: \"The reviewed recording scope must be tab or run.\" };\n if (recordoptions.fps !== undefined && (typeof recordoptions.fps !== \"number\" || !Number.isFinite(recordoptions.fps) || recordoptions.fps <= 0)) return { allowed: false, reason: \"The reviewed recording fps must be a positive number with no code ceiling.\" };\n if (recordoptions.bitrate !== undefined && (typeof recordoptions.bitrate !== \"number\" || !Number.isFinite(recordoptions.bitrate) || recordoptions.bitrate <= 0)) return { allowed: false, reason: \"The reviewed recording bitrate must be a positive number with no code ceiling.\" };\n if (recordoptions.audio !== undefined && typeof recordoptions.audio !== \"boolean\") return { allowed: false, reason: \"The reviewed recording audio flag must be a boolean.\" };\n }\n if (options.duration !== undefined && (typeof options.duration !== \"number\" || !Number.isFinite(options.duration) || options.duration <= 0)) return { allowed: false, reason: \"The reviewed recording duration must be a positive number of milliseconds with no code ceiling.\" };\n const consent = recordingconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"captureframe\") {\n if (options.timestamp !== undefined && (typeof options.timestamp !== \"number\" || !Number.isFinite(options.timestamp) || options.timestamp < 0)) return { allowed: false, reason: \"The reviewed frame timestamp must be zero or a positive number of seconds.\" };\n if (options.poster !== undefined && typeof options.poster !== \"boolean\") return { allowed: false, reason: \"The reviewed poster flag must be a boolean.\" };\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"downloadimages\") {\n const filter = options.imagefilter;\n if (!filter || typeof filter !== \"object\" || Array.isArray(filter)) return { allowed: false, reason: \"A reviewed imagefilter is required in options before any image downloads.\" };\n const imagefilter = filter as Record<string, unknown>;\n if (imagefilter.selector !== undefined && !isnonempty(imagefilter.selector)) return { allowed: false, reason: \"The reviewed imagefilter selector must be a non-empty selector from the reviewed selector grammar.\" };\n if (imagefilter.minwidth !== undefined && (typeof imagefilter.minwidth !== \"number\" || !Number.isFinite(imagefilter.minwidth) || imagefilter.minwidth < 0)) return { allowed: false, reason: \"The reviewed imagefilter minimum width must be zero or a positive number of pixels.\" };\n if (imagefilter.minheight !== undefined && (typeof imagefilter.minheight !== \"number\" || !Number.isFinite(imagefilter.minheight) || imagefilter.minheight < 0)) return { allowed: false, reason: \"The reviewed imagefilter minimum height must be zero or a positive number of pixels.\" };\n if (imagefilter.formats !== undefined && (!Array.isArray(imagefilter.formats) || imagefilter.formats.length === 0 || !imagefilter.formats.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed imagefilter format list must be a non-empty list of mime or extension patterns when present.\" };\n if (options.naming !== undefined) {\n const namingcheck = validatecapturenaming(options.naming);\n if (!namingcheck.allowed) return namingcheck;\n }\n }\n if (kind === \"shotcanvas\") {\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"probestream\" && options.selector !== undefined && !isnonempty(options.selector)) return { allowed: false, reason: \"The reviewed stream probe scope selector must be a non-empty string.\" };\n if (kind === \"timelapse\") {\n const lapse = options.lapse;\n if (!lapse || typeof lapse !== \"object\" || Array.isArray(lapse)) return { allowed: false, reason: \"A reviewed lapse plan with interval, duration and format is required in options.\" };\n const plan = lapse as Record<string, unknown>;\n if (typeof plan.interval !== \"number\" || !Number.isFinite(plan.interval) || plan.interval <= 0) return { allowed: false, reason: \"The reviewed lapse interval must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof plan.duration !== \"number\" || !Number.isFinite(plan.duration) || plan.duration <= 0) return { allowed: false, reason: \"The reviewed lapse duration must be a positive number of milliseconds with no code ceiling.\" };\n if (plan.format !== undefined && plan.format !== \"png\" && plan.format !== \"jpeg\" && plan.format !== \"webp\") return { allowed: false, reason: \"The reviewed lapse format must be png, jpeg or webp.\" };\n const budget = lapsebudgetallowed(plan.interval as number, plan.duration as number, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budget.allowed) return budget;\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"convertimage\" || kind === \"makethumbs\") {\n const single = options.capture;\n const list = options.captures;\n const hasone = isnonempty(single);\n const haslist = Array.isArray(list) && list.length > 0 && list.every(item => isnonempty(item));\n if (!hasone && !haslist) return { allowed: false, reason: \"A reviewed capture id or a reviewed non-empty capture id list is required in options.\" };\n if (hasone && haslist) return { allowed: false, reason: \"The reviewed step needs one capture id or a capture id list, not both.\" };\n }\n if (kind === \"convertimage\") {\n const convert = options.convert;\n if (!convert || typeof convert !== \"object\" || Array.isArray(convert)) return { allowed: false, reason: \"A reviewed convert directive with a target format is required in options.\" };\n const directive = convert as Record<string, unknown>;\n if (directive.target !== \"png\" && directive.target !== \"jpeg\" && directive.target !== \"webp\") return { allowed: false, reason: \"The reviewed conversion target must be png, jpeg or webp.\" };\n if (directive.source !== undefined && directive.source !== \"png\" && directive.source !== \"jpeg\" && directive.source !== \"webp\") return { allowed: false, reason: \"The reviewed conversion source must be png, jpeg or webp.\" };\n if (directive.quality !== undefined && (typeof directive.quality !== \"number\" || !Number.isFinite(directive.quality) || directive.quality < 0 || directive.quality > 100)) return { allowed: false, reason: \"The reviewed conversion quality must stay between zero and one hundred with no code cap inside that range.\" };\n }\n if (kind === \"makethumbs\") {\n const thumb = options.thumb;\n if (!thumb || typeof thumb !== \"object\" || Array.isArray(thumb)) return { allowed: false, reason: \"A reviewed thumb directive with size, fit and suffix is required in options.\" };\n const directive = thumb as Record<string, unknown>;\n if (typeof directive.size !== \"number\" || !Number.isFinite(directive.size) || directive.size <= 0) return { allowed: false, reason: \"The reviewed thumbnail size must be a positive number of pixels with no fixed set.\" };\n if (directive.fit !== \"cover\" && directive.fit !== \"contain\") return { allowed: false, reason: \"The reviewed thumbnail fit must be cover or contain.\" };\n if (!isnonempty(directive.suffix)) return { allowed: false, reason: \"The reviewed thumbnail naming suffix must be a non-empty string.\" };\n }\n return { allowed: true };\n}\n\n/** Validates a single proposal against the active tab origin and local policy. */\nexport function validatestep(step: toolstep, origin: string): policyevaluation {\n if (!allowedactions.has(step.kind)) return { allowed: false, reason: \"Unsupported action kind.\" };\n if (!step.summary.trim()) return { allowed: false, reason: \"A human-readable action summary is required.\" };\n let options: Record<string, unknown>;\n try { options = parseoptions(step); } catch { return { allowed: false, reason: \"Step options must be a JSON object.\" }; }\n const hastargetref = options.targetref !== undefined;\n if (targetactions.has(step.kind) && !step.target?.trim() && !hastargetref) return { allowed: false, reason: \"A page target is required.\" };\n if (valueactions.has(step.kind) && !step.value?.trim()) return { allowed: false, reason: \"A reviewed value is required.\" };\n if (step.kind === \"select\" && !step.value?.trim()) return { allowed: false, reason: \"A reviewed option value is required.\" };\n if (step.kind === \"navigate\" && !step.value) return { allowed: false, reason: \"A navigation URL is required.\" };\n if (hastargetref) {\n const reference = validatetargetref(options.targetref);\n if (!reference.allowed) return reference;\n }\n if (step.kind === \"wait\") {\n try { waitduration(step); } catch { return { allowed: false, reason: \"Wait duration must be zero or a positive number of milliseconds.\" }; }\n }\n if (step.kind === \"navigate\") {\n try {\n if (new URL(step.value ?? \"\").origin !== origin) return { allowed: false, reason: \"Navigation must remain within the approved origin.\" };\n } catch {\n return { allowed: false, reason: \"Navigation URL is invalid.\" };\n }\n }\n if (step.kind === \"tabcreate\" || step.kind === \"windowcreate\" || step.kind === \"downloadfile\") {\n try {\n const url = new URL(step.value ?? \"\");\n if (url.protocol !== \"https:\") return { allowed: false, reason: \"The reviewed URL must use HTTPS.\" };\n } catch {\n return { allowed: false, reason: \"The reviewed URL is invalid.\" };\n }\n }\n if (step.kind === \"tabactivate\" || step.kind === \"tabclose\" || step.kind === \"tabreload\" || step.kind === \"windowclose\" || step.kind === \"windowresize\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser id is required.\" };\n }\n if (step.kind === \"zoomset\") {\n const zoom = Number(step.value);\n if (!Number.isFinite(zoom) || zoom <= 0) return { allowed: false, reason: \"The reviewed zoom must be a positive number.\" };\n }\n if (step.kind === \"setattribute\" || step.kind === \"writestorage\") {\n const keyname = step.kind === \"setattribute\" ? \"name\" : \"key\";\n if (typeof options[keyname] !== \"string\" || !(options[keyname] as string).trim()) return { allowed: false, reason: `A reviewed ${keyname} is required in options.` };\n if (typeof options.value !== \"string\") return { allowed: false, reason: \"A reviewed value is required in options.\" };\n }\n if (step.kind === \"windowresize\") {\n if (typeof options.width !== \"number\" || typeof options.height !== \"number\" || !Number.isFinite(options.width) || !Number.isFinite(options.height)) return { allowed: false, reason: \"Reviewed width and height numbers are required in options.\" };\n }\n if ((step.kind === \"scrollpage\" || step.kind === \"scrollby\") && (!numericoption(options, \"x\") || !numericoption(options, \"y\"))) return { allowed: false, reason: \"Scroll amounts must be numbers in options.\" };\n if (step.kind === \"waitfor\" && options.timeout !== undefined && (typeof options.timeout !== \"number\" || options.timeout < 0)) return { allowed: false, reason: \"The waitfor timeout must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"movepointer\") {\n const path = options.pointpath;\n if (!path || typeof path !== \"object\" || Array.isArray(path)) return { allowed: false, reason: \"A reviewed pointpath with start and end points is required in options.\" };\n const points = path as Record<string, unknown>;\n if (!ispoint(points.start) || !ispoint(points.end)) return { allowed: false, reason: \"The reviewed pointpath needs numeric start and end points.\" };\n if (points.waypoints !== undefined && (!Array.isArray(points.waypoints) || !points.waypoints.every(waypoint => ispoint(waypoint)))) return { allowed: false, reason: \"The reviewed pointpath waypoints must be numeric points.\" };\n if (!nonnegativeoption(points, \"duration\")) return { allowed: false, reason: \"The reviewed pointpath duration must be zero or a positive number of milliseconds.\" };\n const speed = options.speedprofile;\n if (speed !== undefined) {\n if (!speed || typeof speed !== \"object\" || Array.isArray(speed)) return { allowed: false, reason: \"The reviewed speed profile must be an object.\" };\n const profile = speed as Record<string, unknown>;\n if (profile.easing !== undefined && profile.easing !== \"linear\" && profile.easing !== \"easeinout\") return { allowed: false, reason: \"The reviewed easing must be linear or easeinout.\" };\n if (!nonnegativeoption(profile, \"peak\")) return { allowed: false, reason: \"The reviewed peak velocity must be zero or a positive number.\" };\n if (!nonnegativeoption(profile, \"jitter\")) return { allowed: false, reason: \"The reviewed jitter window must be zero or a positive number of milliseconds.\" };\n }\n }\n if (step.kind === \"clickpoint\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"point\")) return { allowed: false, reason: \"A reviewed point target reference is required in options.\" };\n if (step.kind === \"clicktext\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"text\")) return { allowed: false, reason: \"A reviewed text target reference is required in options.\" };\n if (step.kind === \"clickaria\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"aria\")) return { allowed: false, reason: \"A reviewed aria target reference is required in options.\" };\n if (step.kind === \"clickname\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"name\")) return { allowed: false, reason: \"A reviewed name target reference is required in options.\" };\n if (step.kind === \"resolvexpath\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"xpath\")) return { allowed: false, reason: \"A reviewed xpath target reference is required in options.\" };\n if (step.kind === \"typetime\" && options.delay !== undefined && (typeof options.delay !== \"number\" || !Number.isFinite(options.delay) || options.delay < 0)) return { allowed: false, reason: \"The reviewed per keystroke delay must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"submitsearch\") {\n if (!isnonempty(options.results)) return { allowed: false, reason: \"A reviewed results region selector is required in options.\" };\n if (options.timeout !== undefined && (typeof options.timeout !== \"number\" || !Number.isFinite(options.timeout) || options.timeout < 0)) return { allowed: false, reason: \"The submitsearch timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"selectmulti\") {\n const values = options.values;\n if (!Array.isArray(values) || values.length === 0 || !values.every(value => isnonempty(value))) return { allowed: false, reason: \"A reviewed list of option values is required in options.\" };\n }\n if (step.kind === \"setslider\") {\n const slider = Number(step.value);\n if (!Number.isFinite(slider)) return { allowed: false, reason: \"The reviewed slider value must be a number.\" };\n }\n if (step.kind === \"setdate\" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed date must use the yyyy-mm-dd form.\" };\n if (step.kind === \"setcolor\" && !/^#[0-9a-fA-F]{6}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed color must use the #rrggbb form.\" };\n if (step.kind === \"keyhold\" && options.holdid !== undefined && !isnonempty(options.holdid)) return { allowed: false, reason: \"The reviewed hold id must be a non-empty string.\" };\n if (step.kind === \"dismissdialog\") {\n const accept = options.accept;\n const answer = options.answer;\n if (accept === undefined && !isnonempty(answer)) return { allowed: false, reason: \"A reviewed accept flag or prompt answer is required in options.\" };\n if (accept !== undefined && typeof accept !== \"boolean\") return { allowed: false, reason: \"The reviewed dialog accept flag must be a boolean.\" };\n if (answer !== undefined && !isnonempty(answer)) return { allowed: false, reason: \"The reviewed prompt answer must be a non-empty string.\" };\n }\n if (step.kind === \"pierceshadow\" && options.shadow !== undefined) {\n if (!Array.isArray(options.shadow) || !options.shadow.every(item => isnonempty(item))) return { allowed: false, reason: \"The reviewed shadow path must be a list of non-empty selectors.\" };\n }\n if (step.kind === \"enterframe\") {\n const path = options.framepath;\n if (!Array.isArray(path) || path.length === 0 || !path.every(item => typeof item === \"number\" && Number.isInteger(item) && item >= 0)) return { allowed: false, reason: \"A reviewed frame path of frame indexes is required in options.\" };\n return validateinnerstep(options, origin);\n }\n if (step.kind === \"retryaction\") {\n const inner = validateinnerstep(options, origin);\n if (!inner.allowed) return inner;\n const rule = options.retryrule;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule)) return { allowed: false, reason: \"A reviewed retry rule with attempts is required in options.\" };\n const retry = rule as Record<string, unknown>;\n if (typeof retry.attempts !== \"number\" || !Number.isInteger(retry.attempts) || retry.attempts < 1) return { allowed: false, reason: \"The reviewed retry attempts must be a positive integer with no code ceiling.\" };\n if (!nonnegativeoption(retry, \"settle\")) return { allowed: false, reason: \"The reviewed retry settle window must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(retry, \"tolerance\")) return { allowed: false, reason: \"The reviewed retry movement tolerance must be zero or a positive number of pixels.\" };\n }\n if (watchactions.has(step.kind)) {\n if (typeof options.lifetime !== \"number\" || !Number.isFinite(options.lifetime) || options.lifetime <= 0) return { allowed: false, reason: \"A reviewed watch lifetime window in milliseconds is required in options.\" };\n if (options.scopes !== undefined && (!Array.isArray(options.scopes) || !options.scopes.every(scope => isnonempty(scope)))) return { allowed: false, reason: \"The reviewed watch scopes must be a list of non-empty selectors.\" };\n if (options.events !== undefined && (!Array.isArray(options.events) || !options.events.every(event => isnonempty(event)))) return { allowed: false, reason: \"The reviewed watch event kinds must be a list of non-empty strings.\" };\n if (!nonnegativeoption(options, \"poll\")) return { allowed: false, reason: \"The reviewed watch poll interval must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"waitquiet\") {\n const rule = options.quietrule;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule)) return { allowed: false, reason: \"A reviewed quietrule with an idle threshold is required in options.\" };\n const quiet = rule as Record<string, unknown>;\n if (typeof quiet.idle !== \"number\" || !Number.isFinite(quiet.idle) || quiet.idle <= 0) return { allowed: false, reason: \"The reviewed quiet idle threshold must be a positive number of milliseconds with no code ceiling.\" };\n if (!nonnegativeoption(quiet, \"poll\")) return { allowed: false, reason: \"The reviewed quiet poll interval must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(quiet, \"timeout\")) return { allowed: false, reason: \"The reviewed quiet timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"diffsnapshots\") {\n const versions = options.versions;\n if (!Array.isArray(versions) || versions.length !== 2 || !versions.every(version => typeof version === \"number\" && Number.isInteger(version) && version >= 1)) return { allowed: false, reason: \"Two reviewed observation version numbers are required in options.\" };\n }\n if (step.kind === \"openlink\" || step.kind === \"openprivate\" || step.kind === \"deeplink\") {\n const targetcheck = validatenavtarget(options.navtarget, step.kind);\n if (!targetcheck.allowed) return targetcheck;\n if (step.kind === \"deeplink\") {\n const app = options.app;\n if (!isnonempty(app)) return { allowed: false, reason: \"A reviewed deep link app pattern is required in options.\" };\n const params = options.params;\n if (params !== undefined && (!params || typeof params !== \"object\" || Array.isArray(params) || !Object.values(params).every(item => typeof item === \"string\"))) return { allowed: false, reason: \"The reviewed deep link params must be an object of string values.\" };\n }\n }\n if (step.kind === \"waitload\" && !nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The waitload timeout must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"waiturl\" || step.kind === \"spawait\") {\n if (step.kind === \"waiturl\") {\n const patterncheck = validateurlpattern(options.urlpattern);\n if (!patterncheck.allowed) return patterncheck;\n }\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The wait timeout must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(options, \"poll\")) return { allowed: false, reason: \"The wait poll interval must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"followlink\") {\n if (options.fragment !== undefined && typeof options.fragment !== \"boolean\") return { allowed: false, reason: \"The reviewed followlink fragment flag must be a boolean.\" };\n }\n if (step.kind === \"spanav\") {\n if (options.routepattern !== undefined) {\n const routecheck = validateurlpattern(options.routepattern);\n if (!routecheck.allowed) return routecheck;\n }\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The spanav route timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"rewritequery\") {\n const set = options.set;\n const remove = options.remove;\n if (set === undefined && remove === undefined) return { allowed: false, reason: \"Reviewed query parameters to set or remove are required in options.\" };\n if (set !== undefined && (!set || typeof set !== \"object\" || Array.isArray(set) || !Object.values(set).every(item => typeof item === \"string\"))) return { allowed: false, reason: \"The reviewed query parameters to set must be an object of string values.\" };\n if (remove !== undefined && (!Array.isArray(remove) || !remove.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed query parameters to remove must be a list of non-empty names.\" };\n }\n if (step.kind === \"navlist\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (step.kind === \"navprofile\") {\n const profilecheck = validatewaitprofile(options.waitprofile);\n if (!profilecheck.allowed) return profilecheck;\n }\n if (step.kind === \"handleauth\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS origin or url is required as the auth target.\" };\n if (step.kind === \"printpdf\" && options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed artifact name must be a non-empty string.\" };\n if (step.kind === \"prefetch\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (step.kind === \"preconnect\") {\n const origins = options.origins;\n if (!Array.isArray(origins) || origins.length === 0 || !origins.every(originurl => ishttpsurl(originurl))) return { allowed: false, reason: \"A reviewed non-empty list of HTTPS origins is required in options.\" };\n }\n if (step.kind === \"reopentab\" && step.value !== undefined && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed reopen url must use HTTPS.\" };\n if (step.kind === \"navrate\") {\n const limitcheck = validateratelimit(options.ratelimit);\n if (!limitcheck.allowed) return limitcheck;\n }\n if (step.kind === \"checksafe\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS url is required for the safety check.\" };\n if (step.kind === \"batchopen\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (istabscommandkind(step.kind)) {\n const tabscheck = validatetabsgrammar(step, options);\n if (!tabscheck.allowed) return tabscheck;\n }\n if (isformkind(step.kind)) {\n const formcheck = validateformgrammar(step, options);\n if (!formcheck.allowed) return formcheck;\n }\n if (isdatasetkind(step.kind)) {\n const datacheck = validatedatagrammar(step, options, origin);\n if (!datacheck.allowed) return datacheck;\n }\n if (isfileskind(step.kind)) {\n const filescheck = validatefilesgrammar(step, options);\n if (!filescheck.allowed) return filescheck;\n }\n if (iscapturekind(step.kind)) {\n const capturecheck = validatecapturegrammar(step, options);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (ismediakind(step.kind)) {\n const mediacheck = validatemediagrammar(step, options);\n if (!mediacheck.allowed) return mediacheck;\n }\n if (ishttpkind(step.kind)) {\n const httpcheck = validatehttpgrammar(step, options);\n if (!httpcheck.allowed) return httpcheck;\n }\n if (issocketkind(step.kind)) {\n const socketcheck = validatesocketgrammar(step, options);\n if (!socketcheck.allowed) return socketcheck;\n }\n if (isnetwatchkind(step.kind)) {\n const netwatchcheck = validatenetwatchgrammar(step, options);\n if (!netwatchcheck.allowed) return netwatchcheck;\n }\n if (iscontrolkind(step.kind)) {\n const controlcheck = validatecontrolgrammar(step, options);\n if (!controlcheck.allowed) return controlcheck;\n }\n if (isdebugkind(step.kind)) {\n const timelinecheck = validatetimelinegrammar(step, options);\n if (!timelinecheck.allowed) return timelinecheck;\n }\n if (iscdpkind(step.kind)) {\n const cdpcheck = validatecdpgrammar(step, options);\n if (!cdpcheck.allowed) return cdpcheck;\n }\n if (isprofilekind(step.kind)) {\n const profilecheck = validateprofilegrammar(step, options);\n if (!profilecheck.allowed) return profilecheck;\n }\n if (isemulationkind(step.kind)) {\n const emulationcheck = validateemulationgrammar(step, options);\n if (!emulationcheck.allowed) return emulationcheck;\n }\n if (issessionkind(step.kind)) {\n const sessioncheck = validatesessiongrammar(step, options);\n if (!sessioncheck.allowed) return sessioncheck;\n }\n if (isworkflowkind(step.kind)) {\n const workflowcheck = validateworkflowgrammar(step, options);\n if (!workflowcheck.allowed) return workflowcheck;\n }\n if (istriggeraction(step.kind)) {\n const triggercheck = validatetriggergrammar(step, options);\n if (!triggercheck.allowed) return triggercheck;\n }\n if (step.kind === \"tabcreate\") {\n if (options.background !== undefined && typeof options.background !== \"boolean\") return { allowed: false, reason: \"The reviewed background flag must be a boolean.\" };\n if (options.window !== undefined && (typeof options.window !== \"number\" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: \"The reviewed target window id must be a non-negative integer.\" };\n }\n if (step.kind === \"windowcreate\") {\n for (const field of [\"left\", \"top\", \"width\", \"height\"]) {\n if (options[field] !== undefined && (typeof options[field] !== \"number\" || !Number.isFinite(options[field]))) return { allowed: false, reason: `The reviewed window ${field} must be a number.` };\n }\n if (options.state !== undefined && ![\"normal\", \"maximized\", \"minimized\", \"fullscreen\"].includes(options.state as string)) return { allowed: false, reason: \"The reviewed window state must be normal, maximized, minimized or fullscreen.\" };\n }\n return { allowed: true };\n}\n\n/** Shared session gate: a live, unpaused session that still matches the active tab. */\nfunction sessiongate(input: { session: agentsession | undefined; tabid: number; origin: string; now: number; action: string }): policyevaluation {\n if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.pausedat) return { allowed: false, reason: `The browser session is paused and cannot ${input.action}.` };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: `The ${input.action} is outside the approved tab or origin.` };\n return { allowed: true };\n}\n\n/** Applies the consent gate immediately before an action reaches the page bridge. */\nexport function canexecute(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number; verdicts?: safetyverdict[]; settings?: runsettings }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"execute an action\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"The plan has not received explicit approval.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The approved plan has expired.\" };\n if ((input.step.kind === \"pierceshadow\" || input.step.kind === \"enterframe\") && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The shadow or frame step is outside the session origin grants.\" };\n if (input.step.kind === \"readjson\" && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The json state read is outside the session origin grants.\" };\n if (isexportkind(input.step.kind)) {\n const exportgate = exportgranted(input.session, input.origin);\n if (!exportgate.allowed) return exportgate;\n }\n if (input.step.kind === \"navlist\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n for (const url of Array.isArray(options.urls) ? options.urls : []) {\n if (typeof url !== \"string\") continue;\n const navigation = navigationgranted(input.session, url);\n if (!navigation.allowed) return navigation;\n }\n }\n if (islayoutkind(input.step.kind) && !layoutmutationgranted(input.session, now).allowed) return { allowed: false, reason: \"Group and layout mutations stay inside the active session.\" };\n if (input.step.kind === \"submitform\" || input.step.kind === \"retryform\") {\n if (!input.plan) return { allowed: false, reason: \"Form submission requires an asksubmit review step before it.\" };\n const reviewgate = submitreviewgranted(input.plan.steps, input.step.id);\n if (!reviewgate.allowed) return reviewgate;\n }\n if (input.step.kind === \"consentpassword\") {\n const consentgate = passwordconsentgranted(input.step);\n if (!consentgate.allowed) return consentgate;\n }\n if (input.step.kind === \"readclipboard\") {\n const clipgate = clipboardconsentgranted(input.step);\n if (!clipgate.allowed) return clipgate;\n }\n if (input.step.kind === \"interceptmime\" && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The download interception is outside the session origin grants.\" };\n if (iscapturekind(input.step.kind)) {\n const capturegatecheck = capturegate(input.session, input.tabid, input.origin, now);\n if (!capturegatecheck.allowed) return capturegatecheck;\n let captureoptions: Record<string, unknown> = {};\n try { captureoptions = parseoptions(input.step); } catch { captureoptions = {}; }\n const target = (captureoptions.capture as Record<string, unknown> | undefined)?.exporttarget;\n if (target !== undefined && target !== \"memory\" && target !== \"download\" && target !== \"clipboard\") return { allowed: false, reason: \"The capture export target must be memory, download or clipboard.\" };\n }\n if (ismediakind(input.step.kind)) {\n const mediagatecheck = mediagate(input.session, input.tabid, input.origin, now);\n if (!mediagatecheck.allowed) return mediagatecheck;\n }\n if (isrecordingkind(input.step.kind)) {\n const recordinggate = recordingconsentgranted(input.step);\n if (!recordinggate.allowed) return recordinggate;\n }\n if (ishttpkind(input.step.kind)) {\n const target = outboundtarget(input.step);\n if (target !== undefined) {\n const outboundgate = origincheck(input.session, target);\n if (!outboundgate.allowed) return outboundgate;\n }\n if (input.step.kind === \"fetchurl\" || input.step.kind === \"callrest\" || input.step.kind === \"callgraphql\") {\n const consentgate = fetchconsentrefgranted(input.step);\n if (!consentgate.allowed) return consentgate;\n }\n }\n if (issocketkind(input.step.kind)) {\n const channelurl = sockettarget(input.step);\n if (channelurl !== undefined) {\n const channelgate = socketgate(input.session, channelurl);\n if (!channelgate.allowed) return channelgate;\n }\n }\n if (input.step.kind === \"watchrequests\") {\n const watchgatecheck = watchgate(input.session, input.settings, now);\n if (!watchgatecheck.allowed) return watchgatecheck;\n }\n if (isdebugkind(input.step.kind)) {\n const timelinegatecheck = timelinegate(input.session, input.tabid, input.origin, now);\n if (!timelinegatecheck.allowed) return timelinegatecheck;\n }\n if (iscdpkind(input.step.kind)) {\n const debuggatecheck = debuggate(input.session, input.tabid, input.origin, now);\n if (!debuggatecheck.allowed) return debuggatecheck;\n if (!input.plan) return { allowed: false, reason: \"The devtools protocol steps need an approved plan.\" };\n const allowlist = planallowlist(input.plan.steps);\n if (input.step.kind !== \"attachcdp\") {\n if (allowlist === undefined) return { allowed: false, reason: \"The devtools protocol step needs the attachcdp step of the same plan with its enabled domains first.\" };\n if (input.step.kind === \"cdpcmd\") {\n let cdpoptions: Record<string, unknown> = {};\n try { cdpoptions = parseoptions(input.step); } catch { cdpoptions = {}; }\n const command = cdpoptions.command && typeof cdpoptions.command === \"object\" && !Array.isArray(cdpoptions.command) ? cdpoptions.command as Record<string, unknown> : undefined;\n const method = typeof command?.method === \"string\" ? command.method : \"\";\n if (methoddomain(method) === undefined || !allowlistcovers(allowlist, method)) return { allowed: false, reason: `The raw command ${method || \"\"} stays outside the enabled domain allowlist of the plan attach; review the attach domains or the method gates.` };\n }\n }\n let cdpoptions: Record<string, unknown> = {};\n try { cdpoptions = parseoptions(input.step); } catch { cdpoptions = {}; }\n if (input.step.kind === \"setbreakpoint\") {\n const breakpoint = breakpointinputof(cdpoptions.breakpoint);\n if (breakpoint) {\n const targetgate = origincheck(input.session, breakpoint.url);\n if (!targetgate.allowed) return targetgate;\n }\n }\n if (input.step.kind === \"overridescript\") {\n const override = overrideinputof(cdpoptions.override);\n if (override) {\n const targetgate = origincheck(input.session, override.urlpattern);\n if (!targetgate.allowed) return targetgate;\n }\n }\n }\n if (isprofilekind(input.step.kind)) {\n let profileoptions: Record<string, unknown> = {};\n try { profileoptions = parseoptions(input.step); } catch { profileoptions = {}; }\n const targets = [\n ...(attachtargetof(profileoptions.target) !== undefined ? [attachtargetof(profileoptions.target) as attachtarget] : []),\n ...(Array.isArray(profileoptions.attachtargets) ? profileoptions.attachtargets.flatMap(target => { const parsed = attachtargetof(target); return parsed !== undefined ? [parsed] : []; }) : []),\n ];\n const targetgatecheck = targetgate({ session: input.session, tabid: input.tabid, origin: input.origin, targets, grants: undefined, now });\n if (!targetgatecheck.allowed) return targetgatecheck;\n if (input.step.kind === \"capturesourcemaps\") {\n for (const url of Array.isArray(profileoptions.scripts) ? profileoptions.scripts : []) {\n if (typeof url !== \"string\") continue;\n const scriptgate = origincheck(input.session, url);\n if (!scriptgate.allowed) return scriptgate;\n }\n }\n }\n if (isemulationkind(input.step.kind)) {\n const emugatecheck = emugate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!emugatecheck.allowed) return emugatecheck;\n }\n if (issessionkind(input.step.kind)) {\n const sessiongatecheck = sessionrestoregate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!sessiongatecheck.allowed) return sessiongatecheck;\n if (input.step.kind === \"restoresession\") {\n let restoreoptions: Record<string, unknown> = {};\n try { restoreoptions = parseoptions(input.step); } catch { restoreoptions = {}; }\n for (const url of Array.isArray(restoreoptions.origins) ? restoreoptions.origins : []) {\n if (typeof url !== \"string\" || !url) continue;\n const origingate = origincheck(input.session, url);\n if (!origingate.allowed) return { allowed: false, reason: `The session restore reopens ${url} outside the session origin grants; review the restore record or grant the origin.` };\n }\n }\n }\n if (isworkflowkind(input.step.kind)) {\n const workflowgatecheck = workflowgate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!workflowgatecheck.allowed) return workflowgatecheck;\n }\n if (istriggeraction(input.step.kind)) {\n const triggergatecheck = triggergate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!triggergatecheck.allowed) return triggergatecheck;\n }\n if (iscontrolkind(input.step.kind)) {\n const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"control the network\" });\n if (!controlgate.allowed) return controlgate;\n let controloptions: Record<string, unknown> = {};\n try { controloptions = parseoptions(input.step); } catch { controloptions = {}; }\n if (input.step.kind === \"blockrequest\") {\n const blockgatecheck = blockgate(input.session, input.step, now);\n if (!blockgatecheck.allowed) return blockgatecheck;\n const rule = blockruleof(controloptions.block);\n if (rule) {\n const blockorigin = origincheck(input.session, rule.urlpattern);\n if (!blockorigin.allowed) return blockorigin;\n }\n }\n if (input.step.kind === \"mockresponse\" || input.step.kind === \"rewriteheaders\") {\n const patterns = input.step.kind === \"mockresponse\" ? [mockspecof(controloptions.mock)?.urlpattern ?? \"\"] : (Array.isArray(controloptions.rules) ? controloptions.rules.map(item => item && typeof item === \"object\" && !Array.isArray(item) ? String((item as Record<string, unknown>).urlpattern ?? \"\") : \"\") : []);\n for (const pattern of patterns) {\n const patterngate = origincheck(input.session, pattern);\n if (!patterngate.allowed) return patterngate;\n }\n }\n if (input.step.kind === \"setcookies\" || input.step.kind === \"readcookies\" || input.step.kind === \"clearcookies\") {\n const domain = typeof controloptions.domain === \"string\" && controloptions.domain.trim() ? controloptions.domain : Array.isArray(controloptions.cookies) ? String((controloptions.cookies[0] as Record<string, unknown> | undefined)?.domain ?? \"\") : \"\";\n if (!domain) return { allowed: false, reason: \"A reviewed cookie domain is required before cookie control runs.\" };\n const cookiegatecheck = cookiegate(input.session, domain, now);\n if (!cookiegatecheck.allowed) return cookiegatecheck;\n }\n if (input.step.kind === \"authflow\") {\n const authconsent = authconsentgranted(input.step);\n if (!authconsent.allowed) return authconsent;\n }\n if (input.step.kind === \"saveapikey\") {\n const keyconsent = apikeyconsentgranted(input.step);\n if (!keyconsent.allowed) return keyconsent;\n }\n if (input.step.kind === \"routeproxy\") {\n const proxygatecheck = proxygate(input.session, input.step, now);\n if (!proxygatecheck.allowed) return proxygatecheck;\n }\n const target = controltarget(input.step);\n if (target !== undefined) {\n const targetgate = origincheck(input.session, target);\n if (!targetgate.allowed) return targetgate;\n }\n }\n if (input.step.kind === \"extractapi\") {\n let replayoptions: Record<string, unknown> = {};\n try { replayoptions = parseoptions(input.step); } catch { replayoptions = {}; }\n const replay = apireplayspecof(replayoptions.replay);\n if (replay !== undefined) {\n const replaygate = origincheck(input.session, replay.endpoint);\n if (!replaygate.allowed) return replaygate;\n }\n }\n if (input.step.kind === \"openlink\" || input.step.kind === \"openprivate\" || input.step.kind === \"batchopen\" || input.step.kind === \"prefetch\" || input.step.kind === \"deeplink\" || input.step.kind === \"reopentab\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n const grammar = validatestep(input.step, input.origin);\n if (!grammar.allowed) return grammar;\n const grants = input.session?.grants ?? [input.session?.origin ?? input.origin];\n const targets: unknown[] = input.step.kind === \"batchopen\" || input.step.kind === \"prefetch\" ? (Array.isArray(options.urls) ? options.urls : []) : input.step.kind === \"reopentab\" ? [input.step.value] : [(options.navtarget as Record<string, unknown> | undefined)?.url];\n for (const target of targets) {\n if (typeof target !== \"string\" || !target) continue;\n const verified = originverified(target, grants, input.verdicts ?? []);\n if (!verified.allowed) return verified;\n }\n }\n return validatestep(input.step, input.origin);\n}\n\n/** Allows a non-mutating, temporary target preview during plan review. */\nexport function canpreview(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"preview a target\" });\n if (!gate.allowed) return gate;\n if (!input.plan || ![\"pending\", \"approved\"].includes(input.plan.state)) return { allowed: false, reason: \"Only a reviewed pending or approved plan can be previewed.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The reviewed plan has expired.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n if (!targetactions.has(input.step.kind) && options.targetref === undefined) return { allowed: false, reason: \"Only a target-based action can be previewed.\" };\n return validatestep(input.step, input.origin);\n}\n\n/** Lists every reviewed action kind of the policy table so the step library of the editor browses the whole vocabulary. */\nexport function reviewedkinds(): string[] {\n return [...allowedactions].sort();\n}\n\n/** The editor save gate: the canvas model of a save needs a live session and an approved plan like every other reviewed artifact, its nodes must be steps or block invocations with unique ids, its edges must reference existing steps and run forward only so no cycle forms, and the composed record still passes the full workflow grammar through the composition the save triggers. */\nexport function editorsavegate(input: { session: agentsession | undefined; plan: agentplan | undefined; model: editormodel; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.session?.tabid ?? 0, origin: input.session?.origin ?? \"https://example.com\", now: input.now, action: \"save the workflow editor canvas\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Editor saves need the approved plan review before a new workflow version composes.\" };\n const model = input.model;\n if (typeof model.name !== \"string\" || !model.name.trim()) return { allowed: false, reason: \"The workflow name of the canvas must be a non-empty string.\" };\n if (typeof model.version !== \"number\" || !Number.isInteger(model.version) || model.version < 1) return { allowed: false, reason: \"The workflow version of the canvas must be a positive integer.\" };\n if (!Array.isArray(model.origins) || model.origins.length === 0) return { allowed: false, reason: \"The canvas needs at least one granted HTTPS origin.\" };\n const ids = new Set<string>();\n for (const node of model.nodes) {\n if ((node.step === undefined) === (node.invocation === undefined)) return { allowed: false, reason: \"Every canvas node must be exactly one workflow step or one block invocation.\" };\n const id = node.id ?? (node.step !== undefined ? node.step.id : (node.invocation as { block: string }).block);\n if (!id || ids.has(id)) return { allowed: false, reason: `The canvas node id ${id || \"(empty)\"} must be unique.` };\n ids.add(id);\n }\n const reachable = new Set<string>();\n for (const node of model.nodes) {\n if (node.step !== undefined) { reachable.add(node.step.id); continue; }\n const walk = (entries: Array<{ id?: string; kind?: string; label?: string; block?: string }>): void => {\n for (const entry of entries) {\n if (typeof entry.id === \"string\" && typeof entry.kind === \"string\") { reachable.add(entry.id); continue; }\n if (typeof entry.block === \"string\") {\n const nested = model.blocks.find(candidate => candidate.name === entry.block);\n if (nested) walk(nested.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n }\n };\n const block = model.blocks.find(candidate => candidate.name === (node.invocation as { block: string }).block);\n if (!block) return { allowed: false, reason: `The block ${(node.invocation as { block: string }).block} of the canvas has no definition.` };\n walk(block.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n let order = 0;\n const positionof = new Map<string, number>();\n for (const node of model.nodes) {\n if (node.step !== undefined) { positionof.set(node.step.id, order); order += 1; continue; }\n const walk = (entries: Array<{ id?: string; kind?: string; label?: string; block?: string }>): void => {\n for (const entry of entries) {\n if (typeof entry.id === \"string\" && typeof entry.kind === \"string\") { positionof.set(entry.id, order); order += 1; continue; }\n if (typeof entry.block === \"string\") {\n const nested = model.blocks.find(candidate => candidate.name === entry.block);\n if (nested) walk(nested.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n }\n };\n walk((model.blocks.find(candidate => candidate.name === (node.invocation as { block: string }).block) as { steps: Array<{ id?: string; kind?: string; label?: string; block?: string }> }).steps);\n }\n for (const edge of model.edges) {\n if (!reachable.has(edge.from)) return { allowed: false, reason: `The canvas edge of ${edge.variable} references the unknown source step ${edge.from}.` };\n if (!reachable.has(edge.to)) return { allowed: false, reason: `The canvas edge of ${edge.variable} references the unknown target step ${edge.to}.` };\n if ((positionof.get(edge.from) ?? -1) >= (positionof.get(edge.to) ?? -1)) return { allowed: false, reason: `The canvas edge of ${edge.variable} runs backwards and would form a cycle.` };\n }\n return { allowed: true };\n}\n\n/** Refuses to run a workflow whose review state stays pending: an imported workflow or a version rollback stays unreviewed until the user approves its expanded step list through the import or rollback review. */\nexport function runreviewgranted(record: workflowrecord): policyevaluation {\n if (record.reviewstate === \"pending\") return { allowed: false, reason: \"The workflow stays unreviewed: the import or rollback review must approve its expanded step list before any run.\" };\n return { allowed: true };\n}\n\n/** The reviewed policy knobs a per site override may adjust: loop safety bounds, per step and per run timeout budgets, element wait timeouts and delay bases. */\nconst overrideknobs = [\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"];\n\n/** Validates one per site policy override so overrides only adjust reviewed knobs: the pattern must be an https origin or a `*` subdomain glob of one and every delta must name a reviewed knob with a positive user value and no code ceiling. */\nexport function validatesiteoverride(override: { pattern: string; deltas: Record<string, number> }): policyevaluation {\n if (typeof override.pattern !== \"string\" || !override.pattern.startsWith(\"https://\") || !/[a-z0-9.-]+/i.test(override.pattern.slice(8))) return { allowed: false, reason: \"The override pattern must be an https origin or a `*` subdomain glob of one.\" };\n if (!override.pattern.includes(\"*\")) {\n try {\n if (new URL(override.pattern).origin !== override.pattern) return { allowed: false, reason: \"The override pattern must be a bare https origin or a `*` subdomain glob, never a path.\" };\n } catch {\n return { allowed: false, reason: \"The override pattern must parse as an https origin or a `*` subdomain glob of one.\" };\n }\n }\n for (const [knob, delta] of Object.entries(override.deltas)) {\n if (!overrideknobs.includes(knob)) return { allowed: false, reason: `The override knob ${knob} is not one of the reviewed knobs: ${overrideknobs.join(\", \")}.` };\n if (typeof delta !== \"number\" || !Number.isFinite(delta) || delta <= 0) return { allowed: false, reason: `The override delta of ${knob} must be a positive user value with no code ceiling.` };\n }\n return { allowed: true };\n}\n\n/** Validates the export contents of a workflow file so secrets never leave the browser: every step options object of the workflow and of every packed template is parsed and any field that names a secret, token, api key, password or authorization header refuses the export. */\nexport function exportcontentreview(file: { workflow: workflowrecord; templates: steptemplate[] }): policyevaluation {\n const secretkeys = /(secret|token|apikey|api_key|password|authorization|credential)/i;\n const scan = (label: string, options: string | undefined): policyevaluation | undefined => {\n if (options === undefined) return undefined;\n let payload: unknown;\n try { payload = JSON.parse(options); } catch { return undefined; }\n const walk = (value: unknown, path: string): policyevaluation | undefined => {\n if (!value || typeof value !== \"object\") return undefined;\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (secretkeys.test(key)) return { allowed: false, reason: `The export of ${label} carries the secret field ${path}${key} and secrets never leave the browser.` };\n const nested = walk(entry, `${path}${key}.`);\n if (nested !== undefined) return nested;\n }\n return undefined;\n };\n return walk(payload, \"\");\n };\n for (const step of file.workflow.steps) {\n const refusal = scan(`the step ${step.id}`, step.options);\n if (refusal !== undefined) return refusal;\n }\n for (const template of file.templates) {\n const refusal = scan(`the template ${template.name}`, template.step.options);\n if (refusal !== undefined) return refusal;\n }\n return { allowed: true };\n}\n\n/** Validates one watchdog configuration: the stall threshold stays a positive user value with no code ceiling, the recovery action is one of retry, pause or cancel and the zombie window, when configured, stays positive with no ceiling. */\nexport function watchdogconfigvalid(config: watchdogconfig): policyevaluation {\n if (typeof config.enabled !== \"boolean\") return { allowed: false, reason: \"The watchdog enabled flag must be a boolean.\" };\n if (typeof config.stallthreshold !== \"number\" || !Number.isFinite(config.stallthreshold) || config.stallthreshold <= 0) return { allowed: false, reason: \"The watchdog stall threshold must be a positive number of milliseconds with no code ceiling.\" };\n if (![\"retry\", \"pause\", \"cancel\"].includes(config.action)) return { allowed: false, reason: \"The watchdog recovery action must be retry, pause or cancel.\" };\n if (config.zombiewindow !== undefined && (typeof config.zombiewindow !== \"number\" || !Number.isFinite(config.zombiewindow) || config.zombiewindow <= 0)) return { allowed: false, reason: \"The watchdog zombie window, when configured, must be a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Validates one mcp tool catalog against the action kind grammar: every tool name stays namespaced and unique, every wrapped kind belongs to the reviewed vocabulary, every namespace keeps its tools inside its domain kinds and every input schema carries typed properties with its required list. */\nexport function validatetoolcatalog(catalog: toolcatalog): policyevaluation {\n if (!Array.isArray(catalog.domains) || catalog.domains.length === 0) return { allowed: false, reason: \"The tool catalog needs its tool domains.\" };\n const seen = new Set<string>();\n for (const domain of catalog.domains) {\n if (!toolnamespaces.includes(domain.namespace)) return { allowed: false, reason: `The tool domain ${String(domain.namespace)} is not a reviewed namespace.` };\n if (!Array.isArray(domain.tools) || domain.tools.length === 0) return { allowed: false, reason: `The ${domain.namespace} domain exposes no tools.` };\n for (const tool of domain.tools) {\n if (typeof tool.name !== \"string\" || !tool.name.startsWith(`${domain.namespace}.`)) return { allowed: false, reason: `The tool ${String(tool.name)} does not carry its ${domain.namespace} namespace prefix.` };\n if (seen.has(tool.name)) return { allowed: false, reason: `The tool name ${tool.name} is not unique across the catalog.` };\n seen.add(tool.name);\n if (!allowedactions.has(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which is outside the reviewed action kind grammar.` };\n if (!domainkinds[domain.namespace].includes(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which does not belong to the ${domain.namespace} domain.` };\n if (typeof tool.description !== \"string\" || tool.description.trim() === \"\") return { allowed: false, reason: `The tool ${tool.name} needs its plain language description.` };\n const schema = tool.inputschema;\n if (!schema || schema.type !== \"object\" || schema.properties === undefined || schema.properties === null || typeof schema.properties !== \"object\" || Array.isArray(schema.properties) || Object.keys(schema.properties).length === 0) return { allowed: false, reason: `The tool ${tool.name} needs its json schema inputs of at least one typed property.` };\n for (const [name, property] of Object.entries(schema.properties)) {\n if (![\"string\", \"number\", \"boolean\", \"object\", \"array\"].includes(property.type)) return { allowed: false, reason: `The ${tool.name} input ${name} carries an untyped property.` };\n if (typeof property.description !== \"string\" || property.description.trim() === \"\") return { allowed: false, reason: `The ${tool.name} input ${name} needs its plain language description.` };\n }\n for (const name of schema.required) {\n if (!(name in schema.properties)) return { allowed: false, reason: `The tool ${tool.name} marks ${name} required outside its properties.` };\n }\n }\n }\n return { allowed: true };\n}\n\n/** Grades one tooldef with the risk class of its action kind and refuses a tool whose declared grade disagrees with the grammar. */\nexport function toolriskgrade(tool: tooldef): policyevaluation {\n const grade = actionrisk(tool.kind);\n if (grade !== tool.risk) return { allowed: false, reason: `The tool ${tool.name} declares the ${tool.risk} grade while its kind ${String(tool.kind)} grades ${grade}.` };\n return { allowed: true };\n}\n\n/** Requires consent metadata on every tool with side effects: read only tools stay free of the extra review while interaction and sensitive tools must declare their review requirement. */\nexport function toolconsentrequired(tool: tooldef): policyevaluation {\n if (tool.risk === \"read\") return { allowed: true };\n if (tool.consentmeta === undefined || typeof tool.consentmeta.review !== \"string\" || tool.consentmeta.review.trim() === \"\") return { allowed: false, reason: `The tool ${tool.name} has side effects and needs its consent metadata with the review requirement.` };\n return { allowed: true };\n}\n\n/** Grades one server bind configuration: the localhost bind stays the reviewed default while a bind outside localhost grades sensitive and needs the explicit remote review flag. */\nexport function serverbindgate(config: mcpserverconfig): policyevaluation {\n const bind = config.bind !== undefined && config.bind.trim() !== \"\" ? config.bind.trim() : \"127.0.0.1\";\n const local = bind === \"127.0.0.1\" || bind === \"localhost\" || bind === \"::1\";\n if (!local && config.remote !== true) return { allowed: false, reason: `The bind ${bind} leaves localhost and grades sensitive: the explicit remote review must approve it first.` };\n return { allowed: true };\n}\n\n/** Refuses one tool whose version stays below the negotiated compatibility floor so a client never receives a tool older than it can parse. */\nexport function toolversionfloor(tool: tooldef, floor: number): policyevaluation {\n if (typeof floor === \"number\" && Number.isFinite(floor) && tool.version < floor) return { allowed: false, reason: `The tool ${tool.name} of version ${tool.version} stays below the negotiated compatibility floor of ${floor}.` };\n return { allowed: true };\n}\n\n/** Requires the explicit user enablement before the mcp server ever starts; a disabled or unreviewed config never listens. */\nexport function serverenablementgate(config: mcpserverconfig): policyevaluation {\n if (config.enabled !== true) return { allowed: false, reason: \"The mcp server starts only after the user enables it; the protocol surface stays closed by default.\" };\n const bind = serverbindgate(config);\n if (!bind.allowed) return bind;\n if (!Array.isArray(config.transports) || config.transports.length === 0) return { allowed: false, reason: \"The mcp server needs at least one allowed transport of stdio or http.\" };\n if (!config.transports.every(transport => transport === \"stdio\" || transport === \"http\")) return { allowed: false, reason: \"The allowed transports of the mcp server are stdio and http.\" };\n if (typeof config.port !== \"number\" || !Number.isFinite(config.port) || config.port <= 0 || config.port > 65535) return { allowed: false, reason: \"The http listener port must be a valid port number.\" };\n if (config.framesize !== undefined && (typeof config.framesize !== \"number\" || !Number.isFinite(config.framesize) || config.framesize <= 0)) return { allowed: false, reason: \"The user configured frame size must stay a positive number with no code ceiling.\" };\n if (config.queuedepth !== undefined && (typeof config.queuedepth !== \"number\" || !Number.isFinite(config.queuedepth) || config.queuedepth <= 0)) return { allowed: false, reason: \"The user configured queue depth must stay a positive number with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Validates the namespace membership of one tool: the name prefix must name the domain the tool lives in and the wrapped kind must belong to that domain so no tool drifts out of its namespace. */\nexport function toolnamespacegate(tool: tooldef): policyevaluation {\n const namespace = tool.name.split(\".\")[0];\n if (!toolnamespaces.includes(namespace as never)) return { allowed: false, reason: `The tool ${tool.name} carries no reviewed namespace prefix.` };\n if (!domainkinds[namespace as keyof typeof domainkinds].includes(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which does not belong to the ${namespace} domain.` };\n return { allowed: true };\n}\n\n/** The mcp tool dispatch gate: the client must be paired, the session live, the plan approved and the origin inside the session grants; read only tools pass under the dryrun risk class without extra approval while every tool with side effects must name the approved plan step of its own kind it executes. The full canexecute gates re-run at execution time. */\nexport function tooldispatchgate(input: { client: clientrecord; tool: tooldef; session: agentsession | undefined; plan: agentplan | undefined; origin: string; stepid?: string; now: number }): policyevaluation {\n if (input.client.disconnectedat !== undefined) return { allowed: false, reason: \"The mcp client is disconnected and its tool calls are refused.\" };\n if (!input.client.paired) return { allowed: false, reason: \"The mcp client waits for the user pairing approval; unpaired clients never dispatch tools.\" };\n if (!input.session || input.session.stoppedat || input.session.pausedat) return { allowed: false, reason: \"Tool dispatch needs the live browser session behind the consent gates.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired and tool dispatch is refused.\" };\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Tool dispatch needs the approved plan review before any tool runs.\" };\n if (!origingranted(input.session, input.origin)) return { allowed: false, reason: `The tool call origin ${input.origin} stays outside the session grants and is refused.` };\n if (input.tool.risk === \"read\") return { allowed: true };\n if (input.stepid === undefined || input.stepid.trim() === \"\") return { allowed: false, reason: `The ${input.tool.name} tool has side effects and needs the id of the approved plan step it executes.` };\n const step = input.plan.steps.find(candidate => candidate.id === input.stepid);\n if (step === undefined) return { allowed: false, reason: `The tool call names the step ${input.stepid} which the approved plan does not carry.` };\n if (step.kind !== input.tool.kind) return { allowed: false, reason: `The tool call names the step ${input.stepid} whose kind ${String(step.kind)} does not match the ${input.tool.name} tool.` };\n return { allowed: true };\n}\n", "import type { actionrisk, blockinvocation, editoredge, editormodel, editornode, editorlayout, exportformat, minimapstate, nestedparam, palettecategory, palettenode, siteoverride, steplibraryentry, steptemplate, variablebinding, versiondiff, workflowfile, workflowrecord, workflowstep } from \"./types.js\";\nimport { composeworkflow, steptemplateof, validateworkflow, workflowstepof } from \"./workflow.js\";\nimport { controlflowkinds } from \"./controlflow.js\";\nimport { triggerkinds } from \"./trigger.js\";\nimport { workflowfileversion } from \"./protocol.js\";\n\n/**\n * Workflow editor of the 1.1.53 family.\n * Every pure rule of the visual builder lives in this file: the canvas model with nodes, typed binding edges and layout state, the load and save round trips against the composed workflow grammar, the drag and drop snapping to block boundaries, the reorder persistence, the grouping of a selection into a new block, the template insertion with nested parameters, the mini map projection and viewport math, the zoom that keeps step labels readable, the step search, the breakpoint markers with the debug run segmentation, the version diffing, the json and yaml file format for import, export and template sharing, the per site override application and the undo and redo stacks.\n * The module stays pure: the sidepanel renders the model and the background validates saves through the same composeworkflow grammar every other path uses, so no editor artifact bypasses review.\n */\n\n/** The five categories of the block palette: actions, control flow, waits, variables and triggers. */\nexport const palettecategories: palettecategory[] = [\"actions\", \"controlflow\", \"waits\", \"variables\", \"triggers\"];\n\n/** The curated drop blocks of the palette: one descriptor per canonical block of every category. */\nexport const palettenodes: palettenode[] = [\n { kind: \"click\", label: \"Click an element\", category: \"actions\", description: \"Clicks the reviewed selector target.\" },\n { kind: \"type\", label: \"Type text\", category: \"actions\", description: \"Types the reviewed text into the target field.\" },\n { kind: \"navigate\", label: \"Navigate\", category: \"actions\", description: \"Navigates the tab to the reviewed url.\" },\n { kind: \"readtext\", label: \"Read text\", category: \"actions\", description: \"Reads the text of the target element.\" },\n { kind: \"scrapetable\", label: \"Scrape a table\", category: \"actions\", description: \"Extracts the reviewed table into a dataset.\" },\n { kind: \"fillform\", label: \"Fill a form\", category: \"actions\", description: \"Fills the reviewed form fields from a saved profile.\" },\n { kind: \"querytabs\", label: \"Query tabs\", category: \"actions\", description: \"Lists the tabs matching the reviewed query.\" },\n { kind: \"fetchurl\", label: \"Fetch a url\", category: \"actions\", description: \"Fetches the reviewed endpoint behind the call consent.\" },\n { kind: \"condition\", label: \"Condition\", category: \"controlflow\", description: \"Evaluates one reviewed boolean expression with no page side effect.\" },\n { kind: \"branch\", label: \"Branch\", category: \"controlflow\", description: \"Chooses one reviewed path by page state with a mandatory else path.\" },\n { kind: \"loop\", label: \"Loop a list\", category: \"controlflow\", description: \"Iterates a list variable binding the item and index per pass.\" },\n { kind: \"repeatuntil\", label: \"Repeat until\", category: \"controlflow\", description: \"Reruns the body until the convergence expression holds.\" },\n { kind: \"whileloop\", label: \"While loop\", category: \"controlflow\", description: \"Loops while the condition holds inside the reviewed bound.\" },\n { kind: \"foreach\", label: \"For each element\", category: \"controlflow\", description: \"Iterates the elements of the reviewed selector.\" },\n { kind: \"parallel\", label: \"Parallel branches\", category: \"controlflow\", description: \"Runs branches concurrently and joins them under the reviewed strategy.\" },\n { kind: \"trycatch\", label: \"Try catch\", category: \"controlflow\", description: \"Wraps fragile steps with a catch handler, retries and timeouts.\" },\n { kind: \"delay\", label: \"Delay\", category: \"waits\", description: \"Sleeps the reviewed base inside the jitter window.\" },\n { kind: \"waitelement\", label: \"Wait for element\", category: \"waits\", description: \"Polls the reviewed selector until appearance or timeout.\" },\n { kind: \"wait\", label: \"Wait\", category: \"waits\", description: \"Waits the reviewed duration.\" },\n { kind: \"waitfor\", label: \"Wait for target\", category: \"waits\", description: \"Waits until the reviewed target exists.\" },\n { kind: \"waittext\", label: \"Wait for text\", category: \"waits\", description: \"Waits until the reviewed text appears.\" },\n { kind: \"waitquiet\", label: \"Wait for quiet\", category: \"waits\", description: \"Waits until the page stops mutating.\" },\n { kind: \"waitload\", label: \"Wait for load\", category: \"waits\", description: \"Waits until the navigation settles.\" },\n { kind: \"compute\", label: \"Compute\", category: \"variables\", description: \"Evaluates one reviewed expression into the result variable.\" },\n { kind: \"extractvars\", label: \"Extract variables\", category: \"variables\", description: \"Applies the reviewed regex and stores the named captures.\" },\n { kind: \"savetemplate\", label: \"Save template\", category: \"variables\", description: \"Shares the reviewed step as a reusable template.\" },\n { kind: \"visitrule\", label: \"Visit rule\", category: \"triggers\", description: \"Fires on navigations to the reviewed origins.\" },\n { kind: \"urlrule\", label: \"Url rule\", category: \"triggers\", description: \"Fires when the url matches the reviewed glob pattern.\" },\n { kind: \"cronrule\", label: \"Cron rule\", category: \"triggers\", description: \"Fires on the reviewed five field cron schedule.\" },\n { kind: \"intervalrule\", label: \"Interval rule\", category: \"triggers\", description: \"Fires every reviewed period with the jitter spread.\" },\n { kind: \"webhookrule\", label: \"Webhook rule\", category: \"triggers\", description: \"Fires on a secret verified webhook delivery.\" },\n { kind: \"eventrule\", label: \"Event rule\", category: \"triggers\", description: \"Fires on the observed page events of the catalog.\" },\n];\n\n/** The reviewed option schemas the step library documents per kind; kinds without an entry document no reviewed options of their own. */\nconst optionschemas: Record<string, Array<{ name: string; kind: \"string\" | \"number\" | \"boolean\"; required?: boolean }>> = {\n delay: [{ name: \"base\", kind: \"number\", required: true }, { name: \"jitter\", kind: \"number\" }],\n waitelement: [{ name: \"timeout\", kind: \"number\" }, { name: \"poll\", kind: \"number\" }],\n compute: [{ name: \"expression\", kind: \"string\", required: true }],\n extractvars: [{ name: \"rule\", kind: \"string\", required: true }],\n composeworkflow: [{ name: \"name\", kind: \"string\", required: true }, { name: \"version\", kind: \"number\" }],\n runworkflow: [{ name: \"workflowid\", kind: \"string\", required: true }, { name: \"reviewed\", kind: \"boolean\", required: true }, { name: \"variables\", kind: \"string\" }, { name: \"background\", kind: \"boolean\" }],\n dryrun: [{ name: \"workflowid\", kind: \"string\", required: true }],\n loop: [{ name: \"loop\", kind: \"string\", required: true }],\n repeatuntil: [{ name: \"repeatuntil\", kind: \"string\", required: true }],\n whileloop: [{ name: \"whileloop\", kind: \"string\", required: true }],\n foreach: [{ name: \"foreach\", kind: \"string\", required: true }],\n parallel: [{ name: \"parallel\", kind: \"string\", required: true }],\n trycatch: [{ name: \"trycatch\", kind: \"string\", required: true }],\n};\n\n/** Classifies one action kind into its palette category: the ten trigger kinds, the eight control flow kinds, the wait family, the variable family and everything else an action. */\nfunction stepcategory(kind: string): palettecategory {\n if (triggerkinds.includes(kind)) return \"triggers\";\n if (controlflowkinds.includes(kind)) return \"controlflow\";\n if (kind.startsWith(\"wait\") || kind === \"spawait\" || kind === \"delay\") return \"waits\";\n if (kind === \"compute\" || kind === \"extractvars\" || kind === \"savetemplate\") return \"variables\";\n return \"actions\";\n}\n\n/** Builds the step library over every reviewed action kind the policy table knows, grouped by category with the documented option schema of the kinds that carry one. */\nexport function buildsteplibrary(kinds: string[]): steplibraryentry[] {\n return [...new Set(kinds)].sort().map(kind => ({ kind, category: stepcategory(kind), optionschema: optionschemas[kind] ?? [] }));\n}\n\n/** The row height every canvas node occupies; the layout stacks steps top to bottom and block columns side by side. */\nconst noderowheight = 96;\n\n/** The column width of one block container on the canvas. */\nconst blockcolumnwidth = 280;\n\n/** The x origin of the main column of the canvas. */\nconst canvasoriginx = 40;\n\n/** Strips the undo and redo stacks of one model so a snapshot never carries nested history. */\nfunction snapshotof(model: editormodel): editormodel {\n const { undo, redo, dirty, ...rest } = model;\n void undo; void redo; void dirty;\n return { ...rest, dirty: true };\n}\n\n/** Pushes one edit onto the undo stack and clears the redo stack; every canvas edit routes through here. */\nfunction withundo(model: editormodel, next: editormodel): editormodel {\n const undo = [...(model.undo ?? []), snapshotof(model)];\n const { redo, ...rest } = next;\n void redo;\n return { ...rest, dirty: true, undo };\n}\n\n/** Returns the id of one canvas node: the explicit node id, the step id or the invoked block name. */\nfunction nodeidof(node: editornode): string {\n return node.id ?? (node.step !== undefined ? node.step.id : node.invocation !== undefined ? node.invocation.block : \"\");\n}\n\n/** Computes the layout width and height the nodes of one model occupy. */\nfunction layoutsizeof(nodes: editornode[]): { width: number; height: number } {\n const width = Math.max(640, ...nodes.map(node => node.x + blockcolumnwidth)) + 40;\n const height = Math.max(480, ...nodes.map(node => node.y + noderowheight)) + 40;\n return { width, height };\n}\n\n/** Converts one composed workflow record into the canvas model: one node per top level step, one invocation node per contiguous block region of the expanded step list with a unique id even when one block is invoked many times, the bindings of every step lifted into typed edges and the layout stacked top to bottom with the block columns side by side. */\nexport function loadworkflow(record: workflowrecord, layout?: editorlayout): editormodel {\n const blocks = record.blocks.map(block => ({ ...block, steps: block.steps.map(entry => ({ ...entry })) }));\n const blockcolumn = (blockname: string): number => {\n const index = blocks.findIndex(block => block.name === blockname);\n return index < 0 ? canvasoriginx : canvasoriginx + (index + 1) * blockcolumnwidth;\n };\n const invocationcount = new Map<string, number>();\n const nodes: editornode[] = [];\n const edges: editoredge[] = [];\n let index = 0;\n while (index < record.steps.length) {\n const step = record.steps[index] as workflowstep;\n for (const binding of step.bindings ?? []) edges.push({ from: binding.stepid, to: step.id, variable: binding.variable, kind: binding.kind, ...(binding.path !== undefined ? { path: binding.path } : {}) });\n if (step.block === undefined) {\n const { bindings, block, params, ...rest } = step;\n void bindings; void block; void params;\n nodes.push({ step: { ...rest }, x: canvasoriginx, y: 60 + nodes.length * noderowheight });\n index += 1;\n continue;\n }\n const blockname = step.block;\n let end = index;\n while (end < record.steps.length && (record.steps[end] as workflowstep).block === blockname) end += 1;\n const region = record.steps.slice(index, end) as workflowstep[];\n const count = (invocationcount.get(blockname) ?? 0) + 1;\n invocationcount.set(blockname, count);\n const params = region.flatMap(entry => entry.params ?? []);\n nodes.push({ id: count === 1 ? blockname : `${blockname}${count}`, invocation: { block: blockname, label: blockname, ...(params.length > 0 ? { params: params.map(param => ({ ...param })) } : {}) }, x: blockcolumn(blockname), y: 60 + nodes.length * noderowheight });\n index = end;\n }\n const size = layouttypeof(nodes, layout);\n const model: editormodel = { workflowid: record.id, name: record.name, version: record.version, origins: [...record.origins], nodes, edges, blocks, layout: size, minimap: emptyminimap(), dirty: false };\n return { ...model, minimap: renderminimap(model).minimap };\n}\n\n/** Merges one explicit layout with the computed node bounds so a reopened canvas keeps its size while new nodes stay visible. */\nfunction layouttypeof(nodes: editornode[], layout?: editorlayout): editorlayout {\n const size = layoutsizeof(nodes);\n if (!layout) return { width: size.width, height: size.height, viewportx: 0, viewporty: 0, zoom: 1 };\n return { width: Math.max(size.width, layout.width), height: Math.max(size.height, layout.height), viewportx: layout.viewportx, viewporty: layout.viewporty, zoom: layout.zoom };\n}\n\n/** Builds the empty mini map of a model before the first projection. */\nfunction emptyminimap(): minimapstate {\n return { width: 160, height: 100, scale: 0, zoom: 1, viewport: { x: 0, y: 0, width: 0, height: 0 } };\n}\n\n/** Validates the canvas model and converts it back into one composed workflow record: every node is a step or a block invocation, every edge links the output of an earlier node into a later node so no cycle forms, block child bindings stay inside their block and the composed record passes the full workflow grammar. */\nexport function saveworkflow(model: editormodel, input: { now: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): workflowrecord {\n if (typeof model.name !== \"string\" || !model.name.trim()) throw new Error(\"The workflow name must be a non-empty string.\");\n if (typeof model.version !== \"number\" || !Number.isInteger(model.version) || model.version < 1) throw new Error(\"The workflow version must be a positive integer.\");\n if (!Array.isArray(model.origins) || model.origins.length === 0) throw new Error(\"A workflow needs at least one granted HTTPS origin.\");\n const ids = new Set<string>();\n for (const node of model.nodes) {\n if ((node.step === undefined) === (node.invocation === undefined)) throw new Error(\"Every canvas node must be exactly one workflow step or one block invocation.\");\n const id = nodeidof(node);\n if (!id || ids.has(id)) throw new Error(`The canvas node id ${id || \"(empty)\"} must be unique.`);\n ids.add(id);\n }\n /** Walks the top level entries in execution order and maps every reachable step id onto its position so the edge check answers cycles. */\n const positionof = new Map<string, number>();\n let position = 0;\n for (const node of model.nodes) {\n if (node.step !== undefined) { positionof.set(node.step.id, position); position += 1; continue; }\n const block = model.blocks.find(entry => entry.name === node.invocation?.block);\n if (!block) throw new Error(`The block ${node.invocation?.block ?? \"\"} of the canvas has no definition.`);\n const walk = (entries: Array<workflowstep | blockinvocation>): void => {\n for (const entry of entries) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) { positionof.set(entry.id, position); position += 1; continue; }\n const nested = model.blocks.find(candidate => candidate.name === (entry as blockinvocation).block);\n if (!nested) throw new Error(`The block ${(entry as blockinvocation).block} of the canvas has no definition.`);\n walk(nested.steps);\n }\n };\n walk(block.steps);\n }\n for (const edge of model.edges) {\n if (!positionof.has(edge.from)) throw new Error(`The edge of ${edge.variable} references the unknown source step ${edge.from}.`);\n if (!positionof.has(edge.to)) throw new Error(`The edge of ${edge.variable} references the unknown target step ${edge.to}.`);\n if ((positionof.get(edge.from) as number) >= (positionof.get(edge.to) as number)) throw new Error(`The edge of ${edge.variable} runs backwards from ${edge.from} into ${edge.to} and would form a cycle.`);\n }\n /** Collects the bindings one step id receives from the canvas edges. */\n const bindingsof = (stepid: string): variablebinding[] => model.edges.filter(edge => edge.to === stepid).map(edge => ({ variable: edge.variable, kind: edge.kind, stepid: edge.from, ...(edge.path !== undefined ? { path: edge.path } : {}) }));\n const entries: Array<workflowstep | blockinvocation> = [];\n const attached = new Map<string, workflowstep[]>();\n for (const node of model.nodes) {\n if (node.invocation !== undefined) { entries.push({ ...node.invocation }); continue; }\n const step = node.step as workflowstep;\n const bindings = bindingsof(step.id);\n const { block, params, ...rest } = { ...step, ...(bindings.length > 0 ? { bindings } : {}) };\n void params;\n const carried: workflowstep = rest;\n if (block !== undefined) {\n if (!model.blocks.some(candidate => candidate.name === block)) throw new Error(`The step ${step.id} attaches to the unknown block ${block}.`);\n const list = attached.get(block) ?? [];\n list.push(carried);\n attached.set(block, list);\n continue;\n }\n entries.push(carried);\n }\n const blocks = model.blocks.map(block => {\n const snapped = attached.get(block.name) ?? [];\n const snappedids = new Set(snapped.map(step => step.id));\n const carried: Array<workflowstep | blockinvocation> = [];\n for (const entry of block.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && snappedids.has((entry as workflowstep).id)) continue;\n carried.push(entry);\n }\n const steps: Array<workflowstep | blockinvocation> = [...carried, ...snapped];\n const withbindings: Array<workflowstep | blockinvocation> = [];\n for (const entry of steps) {\n if (!(\"kind\" in entry && \"label\" in entry && !(\"block\" in entry))) { withbindings.push(entry); continue; }\n const bindings = bindingsof((entry as workflowstep).id);\n const { block: inner, params, ...rest } = { ...(entry as workflowstep), ...(bindings.length > 0 ? { bindings } : {}) };\n void inner; void params;\n withbindings.push(rest as workflowstep);\n }\n return { ...block, steps: withbindings };\n });\n const composed = composeworkflow({ id: model.workflowid, name: model.name, version: model.version, origins: [...model.origins], steps: entries, blocks: blocks.map(block => ({ ...block })), now: input.now, ...(input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {}), ...(input.riskof !== undefined ? { riskof: input.riskof } : {}) });\n const checked = validateworkflow(composed, input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {});\n if (!checked.allowed) throw new Error(checked.reason ?? \"The canvas model failed the workflow grammar.\");\n return composed;\n}\n\n/** Attaches one step to a block boundary: the dragged position snaps onto the reviewed grid and the nearest block column attaches the step into that block while the main column detaches it. */\nexport function snapnode(model: editormodel, nodeid: string, x: number, y: number, grid = 20): editormodel {\n if (!Number.isFinite(grid) || grid <= 0) throw new Error(\"The snap grid must be a positive number.\");\n const index = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (index < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n const node = model.nodes[index] as editornode;\n if (node.step === undefined) throw new Error(\"A block invocation node attaches through its own definition, not through snapping.\");\n const snappedx = Math.round(x / grid) * grid;\n const snappedy = Math.round(y / grid) * grid;\n let attached: string | undefined;\n for (const [blockindex, block] of model.blocks.entries()) {\n const columnx = canvasoriginx + (blockindex + 1) * blockcolumnwidth;\n if (Math.abs(snappedx - columnx) <= blockcolumnwidth / 2) attached = block.name;\n }\n const { block: priorblock, ...rest } = node.step;\n void priorblock;\n const step: workflowstep = { ...rest, ...(attached !== undefined ? { block: attached } : {}) };\n const nodes = model.nodes.map((candidate, position) => position === index ? { step, x: snappedx, y: snappedy } : candidate);\n const size = layouttypeof(nodes, model.layout);\n const next: editormodel = { ...model, nodes, layout: size };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Persists one drag and drop ordering: the node moves to the reviewed index of the top level list while the edges stay attached to their step ids. */\nexport function reordersteps(model: editormodel, nodeid: string, index: number): editormodel {\n const current = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (current < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n if (!Number.isInteger(index) || index < 0 || index > model.nodes.length - 1) throw new Error(\"The reorder index must address an existing position of the canvas list.\");\n const nodes = [...model.nodes];\n const [moved] = nodes.splice(current, 1);\n if (!moved) throw new Error(\"The reordered canvas node vanished.\");\n nodes.splice(index, 0, moved);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Moves many selected steps into a new block: the definition collects the selected steps in their current order and one invocation node replaces the first selected position. */\nexport function groupselect(model: editormodel, nodeids: string[], blockname: string): editormodel {\n if (!/^[a-z][a-z0-9]*$/.test(blockname)) throw new Error(\"The block name must be a unique lowercase word.\");\n if (model.blocks.some(block => block.name === blockname)) throw new Error(`The block name ${blockname} already exists on the canvas.`);\n const selected = nodeids.map(id => {\n const node = model.nodes.find(candidate => nodeidof(candidate) === id);\n if (!node || node.step === undefined) throw new Error(`The grouping selection must address step nodes; ${id} is not one.`);\n return node;\n });\n if (selected.length === 0) throw new Error(\"The grouping selection needs at least one step node.\");\n const steps = selected.map(node => node.step as workflowstep);\n const blocks = [...model.blocks, { name: blockname, label: blockname, steps: steps.map(step => ({ ...step })) }];\n const firstindex = model.nodes.findIndex(node => nodeidof(node) === nodeids[0] as string);\n const invocationnode: editornode = { id: blockname, invocation: { block: blockname, label: blockname }, x: (selected[0] as editornode).x, y: (selected[0] as editornode).y };\n const nodes: editornode[] = [];\n model.nodes.forEach((node, index) => {\n if (nodeids.includes(nodeidof(node))) {\n if (index === firstindex) nodes.push(invocationnode);\n return;\n }\n nodes.push(node);\n });\n const next: editormodel = { ...model, nodes, blocks };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Inserts one shared step template with its nested parameters: the template step becomes a canvas node at the reviewed index and the parameters ride with the step into its block scope. */\nexport function expandtemplate(model: editormodel, template: steptemplate, params: nestedparam[] = [], index?: number): editormodel {\n const parsed = steptemplateof(template);\n if (!parsed) throw new Error(\"The template does not carry one reviewed workflow step.\");\n let id = parsed.step.id;\n let suffix = 2;\n const taken = new Set(model.nodes.map(node => nodeidof(node)));\n while (taken.has(id)) { id = `${parsed.step.id}${suffix}`; suffix += 1; }\n const step: workflowstep = { ...parsed.step, id, ...(params.length > 0 ? { params: params.map(param => ({ ...param })) } : {}) };\n const position = index !== undefined && Number.isInteger(index) && index >= 0 && index <= model.nodes.length ? index : model.nodes.length;\n const nodes = [...model.nodes.slice(0, position), { step, x: canvasoriginx, y: 60 + position * noderowheight }, ...model.nodes.slice(position)];\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Inserts one new step node onto the canvas at the reviewed index: the palette and the step library drop their kinds through here so every insertion rides the undo stack. */\nexport function addnode(model: editormodel, step: workflowstep, index?: number): editormodel {\n const normalized = workflowstepof(step);\n if (!normalized) throw new Error(\"The canvas insertion needs one reviewed workflow step.\");\n let id = normalized.id;\n let suffix = 2;\n const taken = new Set(model.nodes.map(node => nodeidof(node)));\n while (taken.has(id)) { id = `${normalized.id}${suffix}`; suffix += 1; }\n const position = index !== undefined && Number.isInteger(index) && index >= 0 && index <= model.nodes.length ? index : model.nodes.length;\n const nodes = [...model.nodes.slice(0, position), { step: { ...normalized, id }, x: canvasoriginx, y: 60 + position * noderowheight }, ...model.nodes.slice(position)];\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Replaces the payload of one step node of the canvas: the step inspector edits its target, value, options, expression and extract fields through here so every edit rides the undo stack. */\nexport function editstep(model: editormodel, step: workflowstep): editormodel {\n const normalized = workflowstepof(step);\n if (!normalized) throw new Error(\"The step inspector edit needs one reviewed workflow step.\");\n const index = model.nodes.findIndex(node => node.step?.id === normalized.id);\n if (index < 0) throw new Error(`No canvas step matches ${normalized.id}.`);\n const node = model.nodes[index] as editornode;\n const nodes = model.nodes.map((candidate, position) => position === index ? { step: { ...normalized, ...(node.step?.block !== undefined ? { block: node.step.block } : {}), ...(node.step?.breakpoint === true ? { breakpoint: true } : {}) }, x: node.x, y: node.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Projects the full canvas into the mini map: the projection scale fits every node into the mini size and the viewport rectangle follows the layout viewport and zoom. */\nexport function renderminimap(model: editormodel, width = 160, height = 100): { minimap: minimapstate; nodes: Array<{ id: string; x: number; y: number }> } {\n if (!Number.isFinite(width) || width <= 0 || !Number.isFinite(height) || height <= 0) throw new Error(\"The mini map size must be positive.\");\n const canvaswidth = Math.max(1, model.layout.width);\n const canvasheight = Math.max(1, model.layout.height);\n const scale = Math.min(width / canvaswidth, height / canvasheight);\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n const visiblewidth = canvaswidth / zoom;\n const visibleheight = canvasheight / zoom;\n const viewport = {\n x: Math.max(0, Math.min(model.layout.viewportx, canvaswidth)) * scale,\n y: Math.max(0, Math.min(model.layout.viewporty, canvasheight)) * scale,\n width: visiblewidth * scale,\n height: visibleheight * scale,\n };\n const nodes = model.nodes.map(node => ({ id: nodeidof(node), x: node.x * scale, y: node.y * scale }));\n return { minimap: { width, height, scale, zoom, viewport }, nodes };\n}\n\n/** Jumps the canvas to a clicked mini map region: the click converts back into canvas coordinates and the viewport centers on it inside the canvas bounds. */\nexport function minimapfocus(model: editormodel, x: number, y: number, width = 160, height = 100): editormodel {\n const projection = renderminimap(model, width, height);\n if (projection.minimap.scale <= 0) return model;\n const canvasx = x / projection.minimap.scale;\n const canvasy = y / projection.minimap.scale;\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n const visiblewidth = model.layout.width / zoom;\n const visibleheight = model.layout.height / zoom;\n const viewportx = Math.max(0, Math.min(canvasx - visiblewidth / 2, Math.max(0, model.layout.width - visiblewidth)));\n const viewporty = Math.max(0, Math.min(canvasy - visibleheight / 2, Math.max(0, model.layout.height - visibleheight)));\n const next: editormodel = { ...model, layout: { ...model.layout, viewportx, viewporty } };\n return { ...next, minimap: renderminimap(next).minimap };\n}\n\n/** Sets the canvas zoom to any positive user value with no ceiling while the step labels compensate so they stay readable at every zoom level: the returned label scale grows the labels relative to the canvas once the zoom shrinks below the readable floor. */\nexport function zoomcanvas(model: editormodel, zoom: number): { model: editormodel; labelscale: number } {\n if (!Number.isFinite(zoom) || zoom <= 0) throw new Error(\"The canvas zoom must be a positive number with no code ceiling.\");\n const next: editormodel = { ...model, layout: { ...model.layout, zoom } };\n const labelscale = zoom < 1 ? 1 / zoom : 1;\n return { model: { ...next, minimap: renderminimap(next).minimap }, labelscale };\n}\n\n/** Finds steps by label, kind or variable name: the search answers the matching nodes with the reasons they matched, case insensitive. */\nexport function searchsteps(model: editormodel, query: string): Array<{ id: string; label: string; kind: string; matched: string[] }> {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n const results: Array<{ id: string; label: string; kind: string; matched: string[] }> = [];\n for (const node of model.nodes) {\n if (node.step === undefined) continue;\n const matched: string[] = [];\n if (node.step.label.toLowerCase().includes(needle)) matched.push(\"label\");\n if (node.step.kind.toLowerCase().includes(needle)) matched.push(\"kind\");\n const variables = [\n ...model.edges.filter(edge => edge.to === node.step?.id || edge.from === node.step?.id).map(edge => edge.variable),\n ...(node.step.expression !== undefined ? [node.step.expression.result] : []),\n ...(node.step.extract !== undefined ? node.step.extract.groups : []),\n ];\n if (variables.some(name => name.toLowerCase().includes(needle))) matched.push(\"variable\");\n if (matched.length > 0) results.push({ id: node.step.id, label: node.step.label, kind: node.step.kind, matched });\n }\n return results;\n}\n\n/** Toggles the breakpoint marker of one step for editor debugging; a debug run pauses right before a marked step, and the marker rides the steps inside block definitions too. */\nexport function markbreakpoint(model: editormodel, stepid: string): editormodel {\n const toggle = (step: workflowstep): workflowstep => {\n const { breakpoint, ...rest } = step;\n void breakpoint;\n return breakpoint === true ? rest : { ...rest, breakpoint: true };\n };\n const index = model.nodes.findIndex(node => node.step?.id === stepid);\n if (index >= 0) {\n const node = model.nodes[index] as editornode;\n const step = node.step as workflowstep;\n const nodes = model.nodes.map((candidate, position) => position === index ? { step: toggle(step), x: candidate.x, y: candidate.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n }\n const blocks = model.blocks.map(block => {\n const stepindex = block.steps.findIndex(entry => \"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && (entry as workflowstep).id === stepid);\n if (stepindex < 0) return block;\n const steps = block.steps.map((entry, position) => position === stepindex ? toggle(entry as workflowstep) : entry);\n return { ...block, steps };\n });\n if (blocks.every((block, position) => block === model.blocks[position])) throw new Error(`No canvas step matches ${stepid}.`);\n const next: editormodel = { ...model, blocks };\n return withundo(model, next);\n}\n\n/** Plans one debug run segment: the run executes the steps from the cursor up to the step before the next breakpoint, pauses at the breakpoint step id and reports the steps remaining after it; a run without breakpoints runs to the end. */\nexport function runtobreakpoint(input: { record: workflowrecord; cursor?: number; breakpoints: string[] }): { until: number; pausat: string | undefined; remaining: number } {\n const cursor = input.cursor !== undefined && Number.isInteger(input.cursor) && input.cursor >= 0 ? input.cursor : 0;\n const marked = new Set(input.breakpoints);\n for (let index = cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n if (step.breakpoint === true || marked.has(step.id)) {\n return { until: index, pausat: step.id, remaining: input.record.steps.length - index };\n }\n }\n return { until: input.record.steps.length, pausat: undefined, remaining: 0 };\n}\n\n/** Compares two workflow versions: the steps the newer version added, removed and changed with the field names that changed. */\nexport function diffversions(from: workflowrecord, to: workflowrecord, now: number): versiondiff {\n const fromsteps = new Map(from.steps.map(step => [step.id, step]));\n const tosteps = new Map(to.steps.map(step => [step.id, step]));\n const added: versiondiff[\"added\"] = [];\n const removed: versiondiff[\"removed\"] = [];\n const changed: versiondiff[\"changed\"] = [];\n for (const step of to.steps) {\n const prior = fromsteps.get(step.id);\n if (!prior) { added.push({ stepid: step.id, kind: step.kind, label: step.label }); continue; }\n const changes: string[] = [];\n if (prior.label !== step.label) changes.push(\"label\");\n if (prior.kind !== step.kind) changes.push(\"kind\");\n if (prior.target !== step.target) changes.push(\"target\");\n if (prior.value !== step.value) changes.push(\"value\");\n if (prior.options !== step.options) changes.push(\"options\");\n if (JSON.stringify(prior.expression) !== JSON.stringify(step.expression)) changes.push(\"expression\");\n if (JSON.stringify(prior.extract) !== JSON.stringify(step.extract)) changes.push(\"extract\");\n if (JSON.stringify(prior.bindings) !== JSON.stringify(step.bindings)) changes.push(\"bindings\");\n if (changes.length > 0) changed.push({ stepid: step.id, kind: step.kind, label: step.label, changes });\n }\n for (const step of from.steps) {\n if (!tosteps.has(step.id)) removed.push({ stepid: step.id, kind: step.kind, label: step.label });\n }\n return { workflowid: to.id, from: from.version, to: to.version, added, removed, changed, at: now };\n}\n\n/** Serializes one workflow record with its version metadata into a workflow file of the reviewed json or yaml format. */\nexport function exportworkflow(record: workflowrecord, format: exportformat, note?: string, now?: number): { format: exportformat; contents: string; file: workflowfile } {\n const file: workflowfile = { format: workflowfileversion, exportedat: now ?? Date.now(), workflow: record, ...(note !== undefined && note.trim() !== \"\" ? { note } : {}), templates: [] };\n return { format, contents: serializefile(file, format), file };\n}\n\n/** Packs one workflow with its shared step templates into a single shareable file so a whole library travels together. */\nexport function shareworkflow(record: workflowrecord, templates: steptemplate[], format: exportformat, note?: string, now?: number): { format: exportformat; contents: string; file: workflowfile } {\n const file: workflowfile = { format: workflowfileversion, exportedat: now ?? Date.now(), workflow: record, ...(note !== undefined && note.trim() !== \"\" ? { note } : {}), templates: templates.map(template => ({ ...template })) };\n return { format, contents: serializefile(file, format), file };\n}\n\n/** Validates and loads one workflow file: the format version must match, the workflow must compose through the full grammar and every packed template must normalize; the loaded record grades unreviewed until the user approves it. */\nexport function importworkflow(input: { contents: string; format?: exportformat; now?: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): { record: workflowrecord; templates: steptemplate[]; file: workflowfile } {\n const format = input.format ?? (input.contents.trimStart().startsWith(\"{\") ? \"json\" : \"yaml\");\n const parsed = parsefile(input.contents, format);\n if (parsed.format !== workflowfileversion) throw new Error(`The workflow file format ${String(parsed.format)} is not the reviewed format ${workflowfileversion}.`);\n const candidate = parsed.workflow;\n if (!candidate || typeof candidate !== \"object\" || Array.isArray(candidate)) throw new Error(\"The workflow file carries no workflow record.\");\n const fields = candidate as unknown as Record<string, unknown>;\n const stepsvalue = fields.steps;\n if (!Array.isArray(stepsvalue) || stepsvalue.length === 0) throw new Error(\"An imported workflow needs at least one step.\");\n const steps: Array<workflowstep | blockinvocation> = [];\n for (const entry of stepsvalue) {\n const step = workflowstepof(entry);\n if (step) { steps.push(step); continue; }\n throw new Error(\"Every imported workflow entry must be a reviewed step.\");\n }\n const composed = composeworkflow({\n id: typeof fields.id === \"string\" && fields.id.trim() !== \"\" ? fields.id : crypto.randomUUID(),\n name: typeof fields.name === \"string\" ? fields.name : \"\",\n version: typeof fields.version === \"number\" ? fields.version : 1,\n origins: Array.isArray(fields.origins) ? fields.origins.filter((origin): origin is string => typeof origin === \"string\") : [],\n steps,\n now: input.now ?? Date.now(),\n ...(input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {}),\n ...(input.riskof !== undefined ? { riskof: input.riskof } : {}),\n });\n const templatesvalue = parsed.templates;\n if (templatesvalue !== undefined && !Array.isArray(templatesvalue)) throw new Error(\"The packed templates of the workflow file must be a list.\");\n const templates: steptemplate[] = [];\n for (const entry of templatesvalue ?? []) {\n const template = steptemplateof(entry);\n if (!template) throw new Error(\"A packed template of the workflow file does not carry one reviewed step.\");\n templates.push(template);\n }\n const record: workflowrecord = { ...composed, reviewstate: \"pending\" };\n return { record, templates, file: { ...parsed, workflow: record } };\n}\n\n/** Wires one nested parameter into a block invocation of the canvas: the parameter replaces a same named one and the default binds into the block scope once the run opens it. */\nexport function bindparam(model: editormodel, blockname: string, param: nestedparam): editormodel {\n if (!/^[a-z][a-z0-9]*$/.test(param.name)) throw new Error(\"The nested parameter name must be a lowercase word.\");\n const index = model.nodes.findIndex(node => node.invocation?.block === blockname);\n if (index < 0) throw new Error(`No block invocation of ${blockname} sits on the canvas.`);\n const node = model.nodes[index] as editornode;\n const invocation = node.invocation as blockinvocation;\n const params = [...(invocation.params ?? []).filter(existing => existing.name !== param.name), { ...param }];\n const nodes = model.nodes.map((candidate, position) => position === index ? { invocation: { ...invocation, params }, x: candidate.x, y: candidate.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Answers whether one origin matches a reviewed override pattern: an exact origin or a `*` subdomain glob of an https origin. */\nfunction originmatches(pattern: string, origin: string): boolean {\n if (pattern === origin) return true;\n const glob = pattern.replace(/\\./g, \"\\\\.\").replace(/\\*/g, \"[^.]+\");\n if (!glob.startsWith(\"https://\")) return false;\n return new RegExp(`^${glob}$`).test(origin);\n}\n\n/** Applies one per site policy override to a workflow: the deltas adjust only the reviewed knobs \u2014 loop bounds, step and run timeouts, element wait timeouts and delay bases \u2014 of the steps whose workflow origins match the override pattern. */\nexport function applyoverride(record: workflowrecord, override: siteoverride): workflowrecord {\n const matching = record.origins.filter(origin => originmatches(override.pattern, origin));\n if (matching.length === 0) throw new Error(`The override pattern ${override.pattern} matches none of the workflow origins ${record.origins.join(\", \")}.`);\n const knobs = new Set([\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"]);\n for (const knob of Object.keys(override.deltas)) {\n if (!knobs.has(knob)) throw new Error(`The override knob ${knob} is not one of the reviewed knobs: ${[...knobs].join(\", \")}.`);\n if (typeof override.deltas[knob] !== \"number\" || !Number.isFinite(override.deltas[knob]) || override.deltas[knob] as number <= 0) throw new Error(`The override delta of ${knob} must be a positive number with no code ceiling.`);\n }\n const apply = (step: workflowstep): workflowstep => {\n if (Object.keys(override.deltas).length === 0) return step;\n let payload: Record<string, unknown> = {};\n try { payload = step.options !== undefined ? JSON.parse(step.options) as Record<string, unknown> : {}; } catch { payload = {}; }\n const bodyof = (key: string): Record<string, unknown> => payload[key] !== undefined && typeof payload[key] === \"object\" && !Array.isArray(payload[key]) ? payload[key] as Record<string, unknown> : {};\n if (override.deltas.loopbound !== undefined && [\"loop\", \"repeatuntil\", \"whileloop\"].includes(step.kind)) {\n const body = bodyof(step.kind);\n body.bound = override.deltas.loopbound;\n payload[step.kind] = body;\n }\n if ((override.deltas.stepms !== undefined || override.deltas.runms !== undefined) && step.kind === \"trycatch\") {\n const body = bodyof(\"trycatch\");\n const timeout = body.timeout !== undefined && typeof body.timeout === \"object\" && !Array.isArray(body.timeout) ? body.timeout as Record<string, unknown> : {};\n if (override.deltas.stepms !== undefined) timeout.stepms = override.deltas.stepms;\n if (override.deltas.runms !== undefined) timeout.runms = override.deltas.runms;\n body.timeout = timeout;\n payload.trycatch = body;\n }\n if (override.deltas.waitms !== undefined && step.kind === \"waitelement\") {\n payload.timeout = override.deltas.waitms;\n }\n if (override.deltas.delaybase !== undefined && step.kind === \"delay\") {\n payload.base = override.deltas.delaybase;\n }\n const changed = Object.keys(payload).length > 0;\n return changed ? { ...step, options: JSON.stringify(payload) } : step;\n };\n return { ...record, steps: record.steps.map(apply) };\n}\n\n/** Wires one typed binding edge from the output socket of an earlier step into the input socket of a later step; a backwards edge refuses so no cycle forms. */\nexport function addedge(model: editormodel, edge: editoredge): editormodel {\n const from = model.nodes.findIndex(node => nodeidof(node) === edge.from);\n const to = model.nodes.findIndex(node => nodeidof(node) === edge.to);\n if (from < 0) throw new Error(`The canvas edge references the unknown source step ${edge.from}.`);\n if (to < 0) throw new Error(`The canvas edge references the unknown target step ${edge.to}.`);\n if (from >= to) throw new Error(`The canvas edge of ${edge.variable} would run backwards from ${edge.from} into ${edge.to} and form a cycle.`);\n if (!/^[a-z][a-z0-9]*$/.test(edge.variable)) throw new Error(\"The bound variable name must be a lowercase word.\");\n const edges = [...model.edges.filter(candidate => !(candidate.from === edge.from && candidate.to === edge.to && candidate.variable === edge.variable)), { ...edge, ...(edge.path !== undefined ? { path: edge.path } : {}) }];\n const next: editormodel = { ...model, edges };\n return withundo(model, next);\n}\n\n/** Removes one typed binding edge of the canvas by its source, target and variable. */\nexport function removeedge(model: editormodel, from: string, to: string, variable: string): editormodel {\n const edges = model.edges.filter(candidate => !(candidate.from === from && candidate.to === to && candidate.variable === variable));\n if (edges.length === model.edges.length) throw new Error(`No canvas edge of ${variable} links ${from} into ${to}.`);\n const next: editormodel = { ...model, edges };\n return withundo(model, next);\n}\n\n/** Removes one canvas node with every edge attached to it; the undo stack keeps the removal reversible. */\nexport function removenode(model: editormodel, nodeid: string): editormodel {\n const index = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (index < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n const nodes = model.nodes.filter((_, position) => position !== index);\n const edges = model.edges.filter(edge => edge.from !== nodeid && edge.to !== nodeid);\n const next: editormodel = { ...model, nodes, edges };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Steps one canvas edit back: the last undo snapshot becomes the current model and the edited model waits on the redo stack. */\nexport function undoedit(model: editormodel): editormodel {\n const undo = model.undo ?? [];\n if (undo.length === 0) return model;\n const previous = undo[undo.length - 1] as editormodel;\n const current = snapshotof(model);\n return { ...previous, undo: undo.slice(0, -1), redo: [...(model.redo ?? []), current] };\n}\n\n/** Steps one canvas edit forward again after an undo: the newest redo snapshot returns as the current model. */\nexport function redoedit(model: editormodel): editormodel {\n const redo = model.redo ?? [];\n if (redo.length === 0) return model;\n const next = redo[redo.length - 1] as editormodel;\n const current = snapshotof(model);\n return { ...next, redo: redo.slice(0, -1), undo: [...(model.undo ?? []), current] };\n}\n\n/** Serializes one workflow file into the reviewed json or yaml format; the yaml writer emits the documented subset of quoted scalars, mappings and block sequences the reader parses back. */\nfunction serializefile(file: workflowfile, format: exportformat): string {\n if (format === \"json\") return JSON.stringify(file, null, 2);\n return yamlvalue(file, 0).join(\"\\n\") + \"\\n\";\n}\n\n/** Parses one workflow file from json or the documented yaml subset; every structural violation refuses the import. */\nfunction parsefile(contents: string, format: exportformat): workflowfile {\n if (format === \"json\") {\n const parsed: unknown = JSON.parse(contents);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"The workflow file is not a json object.\");\n return parsed as workflowfile;\n }\n const lines = contents.split(/\\r?\\n/).map(line => line.replace(/\\t/g, \" \")).filter(line => line.trim() !== \"\" && !line.trim().startsWith(\"#\"));\n if (lines.length === 0) throw new Error(\"The yaml workflow file is empty.\");\n const { value, next } = yamlblock(lines, 0, indentof(lines[0] as string));\n if (next < lines.length) throw new Error(\"The yaml workflow file carries content outside the documented subset.\");\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"The yaml workflow file is not a mapping.\");\n return value as workflowfile;\n}\n\n/** Measures the leading spaces of one line. */\nfunction indentof(line: string): number {\n const match = /^ */.exec(line);\n return match ? match[0].length : 0;\n}\n\n/** Renders one scalar of the yaml subset: strings quote with json escaping so no scalar ever confuses the reader. */\nfunction yamlscalar(value: unknown): string {\n if (value === null || value === undefined) return \"null\";\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n return JSON.stringify(String(value));\n}\n\n/** Renders any value of a workflow file into yaml lines of the documented subset. */\nfunction yamlvalue(value: unknown, indent: number): string[] {\n const pad = \" \".repeat(indent);\n if (value === null || value === undefined || typeof value !== \"object\") return [`${pad}${yamlscalar(value)}`];\n if (Array.isArray(value)) {\n if (value.length === 0) return [`${pad}[]`];\n const lines: string[] = [];\n for (const item of value) {\n if (item !== null && typeof item === \"object\") {\n lines.push(`${pad}-`);\n lines.push(...yamlvalue(item, indent + 2));\n } else {\n lines.push(`${pad}- ${yamlscalar(item)}`);\n }\n }\n return lines;\n }\n const entries = Object.entries(value as Record<string, unknown>);\n if (entries.length === 0) return [`${pad}{}`];\n const lines: string[] = [];\n for (const [key, entry] of entries) {\n if (entry !== null && typeof entry === \"object\") {\n if (Array.isArray(entry) && entry.length === 0) { lines.push(`${pad}${key}: []`); continue; }\n if (!Array.isArray(entry) && Object.keys(entry as Record<string, unknown>).length === 0) { lines.push(`${pad}${key}: {}`); continue; }\n lines.push(`${pad}${key}:`);\n lines.push(...yamlvalue(entry, indent + 2));\n } else {\n lines.push(`${pad}${key}: ${yamlscalar(entry)}`);\n }\n }\n return lines;\n}\n\n/** Parses one yaml block of the documented subset into its value starting at the reviewed line index and indentation. */\nfunction yamlblock(lines: string[], start: number, indent: number): { value: unknown; next: number } {\n const first = lines[start] as string;\n if (/^\\s*-\\s/.test(first) || /^\\s*-$/.test(first)) {\n const items: unknown[] = [];\n let index = start;\n while (index < lines.length) {\n const line = lines[index] as string;\n if (indentof(line) !== indent || !/^\\s*-\\s?/.test(line)) break;\n const rest = line.slice(indent + 1).trim();\n if (rest !== \"\") {\n items.push(yamlscalarvalue(rest));\n index += 1;\n continue;\n }\n const nested = yamlblock(lines, index + 1, indent + 2);\n items.push(nested.value);\n index = nested.next;\n }\n return { value: items, next: index };\n }\n const mapping: Record<string, unknown> = {};\n let index = start;\n while (index < lines.length) {\n const line = lines[index] as string;\n if (indentof(line) !== indent) break;\n const match = /^([A-Za-z][A-Za-z0-9]*):(?:\\s(.*))?$/.exec(line.slice(indent));\n if (!match) break;\n const key = match[1] as string;\n const rest = match[2];\n if (rest !== undefined && rest !== \"\") {\n if (rest === \"[]\" ) { mapping[key] = []; index += 1; continue; }\n if (rest === \"{}\") { mapping[key] = {}; index += 1; continue; }\n mapping[key] = yamlscalarvalue(rest);\n index += 1;\n continue;\n }\n const nested = yamlblock(lines, index + 1, indent + 2);\n mapping[key] = nested.value;\n index = nested.next;\n }\n if (index === start) throw new Error(\"The yaml workflow file left the documented subset.\");\n return { value: mapping, next: index };\n}\n\n/** Parses one quoted, numeric, boolean or null scalar of the yaml subset. */\nfunction yamlscalarvalue(text: string): unknown {\n if (text.startsWith(\"\\\"\")) {\n const parsed: unknown = JSON.parse(text);\n return typeof parsed === \"string\" ? parsed : text;\n }\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n if (/^-?\\d+(?:\\.\\d+)?$/.test(text)) return Number(text);\n return text;\n}\n", "import type { tabgrouprecord, tablayout, tabquery, tabwatchevent, toolstep } from \"../types.js\";\nimport { parseoptions } from \"../policy.js\";\nimport { assigntasktab, tasktabs } from \"../progress.js\";\nimport type { planprogress } from \"../types.js\";\n\n/**\n * Tabs and windows command logics for reviewed steps.\n * Every correlated rule for tab queries, clone detection, group membership, layouts, snapshots, watchers, badges, discard candidates, switcher order, zoom steps and the task tab budget lives in this file.\n */\n\n/** One serializable live tab shape resolved against the browser tab set. */\nexport interface tabshape {\n tabid: number;\n url: string;\n title: string;\n index: number;\n windowid: number;\n active: boolean;\n pinned: boolean;\n audible: boolean;\n muted: boolean;\n discarded: boolean;\n}\n\n/** One serializable live window shape with bounds, state and profile kind. */\nexport interface windowshape {\n windowid: number;\n left: number;\n top: number;\n width: number;\n height: number;\n state: \"normal\" | \"maximized\" | \"minimized\" | \"fullscreen\";\n incognito: boolean;\n focused: boolean;\n}\n\n/** Reads the reviewed tabquery of a tabs and windows command step; null when the step reviews none. */\nexport function parsetabquery(step: toolstep): tabquery | null {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const value = options.tabquery;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const query = value as Record<string, unknown>;\n return {\n ...(typeof query.url === \"string\" && query.url ? { url: query.url } : {}),\n ...(typeof query.title === \"string\" && query.title ? { title: query.title } : {}),\n ...(typeof query.id === \"number\" && Number.isInteger(query.id) && query.id >= 0 ? { id: query.id } : {}),\n ...(typeof query.pattern === \"string\" && query.pattern ? { pattern: query.pattern } : {}),\n };\n}\n\n/** Matches one reviewed wildcard pattern against a url; `*` spans one path segment and `**` spans any part. */\nexport function tabpatternmatches(pattern: string, url: string): boolean {\n const source = pattern.split(\"**\").map(part => part.split(\"*\").map(piece => piece.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"[^/]*\")).join(\".*\");\n return new RegExp(`^${source}$`).test(url);\n}\n\n/** Resolves one reviewed tabquery against the live tab set: every matcher that exists must hold. */\nexport function querymatches(query: tabquery, tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => {\n if (query.id !== undefined && tab.tabid !== query.id) return false;\n if (query.url !== undefined && tab.url !== query.url) return false;\n if (query.title !== undefined && !tab.title.toLowerCase().includes(query.title.toLowerCase())) return false;\n if (query.pattern !== undefined && !tabpatternmatches(query.pattern, tab.url)) return false;\n return true;\n });\n}\n\n/** Normalizes one url for clone comparison by dropping the fragment and trailing slashes. */\nexport function normalizedtaburl(url: string): string {\n let normalized = url;\n const hash = normalized.indexOf(\"#\");\n if (hash >= 0) normalized = normalized.slice(0, hash);\n while (normalized.length > 1 && normalized.endsWith(\"/\")) normalized = normalized.slice(0, -1);\n return normalized;\n}\n\n/** One clone warning: a normalized url shared by more than one open tab. */\nexport interface clonewarning {\n url: string;\n tabids: number[];\n}\n\n/** Detects duplicate tabs by normalized url comparison and returns every url held by more than one tab. */\nexport function clonetabs(tabs: tabshape[]): clonewarning[] {\n const groups = new Map<string, number[]>();\n for (const tab of tabs) {\n if (!tab.url) continue;\n const key = normalizedtaburl(tab.url);\n groups.set(key, [...(groups.get(key) ?? []), tab.tabid]);\n }\n return [...groups.entries()].filter(([, tabids]) => tabids.length > 1).map(([url, tabids]) => ({ url, tabids }));\n}\n\n/** Searches across open tabs by title and url, case insensitive, returning matches in live order. */\nexport function searchtabmatches(tabs: tabshape[], text: string): tabshape[] {\n const needle = text.trim().toLowerCase();\n if (!needle) return [];\n return tabs.filter(tab => tab.title.toLowerCase().includes(needle) || tab.url.toLowerCase().includes(needle));\n}\n\n/** Lists the tabs that are playing audio: audible or muted but still playing. */\nexport function audiotabs(tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => tab.audible || (tab.muted && tab.audible));\n}\n\n/** Returns the inactive, unpinned and not yet discarded tabs a discardtab step may release. */\nexport function discardcandidates(tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => !tab.active && !tab.pinned && !tab.discarded && tab.url.length > 0);\n}\n\n/** Restores discarded tabs on demand without losing their urls; every discarded tab keeps its url for reload. */\nexport function restorediscarded(tabs: tabshape[]): Array<{ tabid: number; url: string }> {\n return tabs.filter(tab => tab.discarded && tab.url.length > 0).map(tab => ({ tabid: tab.tabid, url: tab.url }));\n}\n\n/** Captures one tab layout with name, tabs, groups, positions and window bounds from the live browser state. */\nexport function buildlayout(name: string, tabs: tabshape[], windows: windowshape[], groups: tabgrouprecord[], scratchwindowids: number[], at: number): tablayout {\n return {\n name,\n tabs: tabs.map(tab => ({ url: tab.url, title: tab.title, pinned: tab.pinned, index: tab.index, windowid: tab.windowid })),\n groups: groups.map(group => ({ name: group.name, color: group.color, tabids: group.tabids.filter(tabid => tabs.some(tab => tab.tabid === tabid)), collapsed: group.collapsed })),\n windows: windows.map(item => ({ windowid: item.windowid, state: { bounds: { left: item.left, top: item.top, width: item.width, height: item.height }, maximized: item.state === \"maximized\", profile: item.incognito ? \"incognito\" : scratchwindowids.includes(item.windowid) ? \"scratch\" : \"normal\" } })),\n savedat: at,\n };\n}\n\n/** Plans the restore of one saved layout: only urls that are not already open come back, in layout order. */\nexport function layoutrestoreplan(layout: tablayout, openurls: string[]): string[] {\n const open = new Set(openurls.map(url => normalizedtaburl(url)));\n return layout.tabs.map(tab => tab.url).filter(url => url.length > 0 && !open.has(normalizedtaburl(url)));\n}\n\n/** Keeps tabgroup membership through moves: member ids survive, their order follows the live tab order and closed members drop out. */\nexport function regroupaftermoves(groups: tabgrouprecord[], tabs: tabshape[], at: number): tabgrouprecord[] {\n const order = new Map(tabs.map(tab => [tab.tabid, tab.index]));\n return groups.map(group => {\n const members = group.tabids.filter(tabid => order.has(tabid));\n if (members.length === 0) return group;\n const ordered = [...members].sort((left, right) => (order.get(left) ?? 0) - (order.get(right) ?? 0));\n return ordered.length === group.tabids.length && ordered.every((tabid, index) => tabid === group.tabids[index]) ? group : { ...group, tabids: ordered, savedat: at };\n });\n}\n\n/** Renames one stored tab group while keeping its color choice, member tabs and collapse state. */\nexport function renamegroup(groups: tabgrouprecord[], name: string, newname: string, at: number): tabgrouprecord[] {\n return groups.map(group => group.name === name ? { ...group, name: newname, savedat: at } : group);\n}\n\n/** Counts the task tabs that live inside one window so the close gate can demand review. */\nexport function tasktabsinwindow(tabs: tabshape[], windowid: number, tasktabids: number[]): number {\n const tasks = new Set(tasktabids);\n return tabs.filter(tab => tab.windowid === windowid && tasks.has(tab.tabid)).length;\n}\n\n/** Selects the tabs a reviewed closepattern may close; the session tab itself is always refused protection. */\nexport function closeselection(query: tabquery, tabs: tabshape[], sessiontabid: number): { targets: tabshape[]; refused: tabshape[] } {\n const matches = querymatches(query, tabs);\n return {\n targets: matches.filter(tab => tab.tabid !== sessiontabid),\n refused: matches.filter(tab => tab.tabid === sessiontabid),\n };\n}\n\n/** Applies one reviewed zoom step with no code ceiling; a step never crosses zero, so it keeps the current zoom instead. */\nexport function zoomstep(current: number, direction: \"in\" | \"out\", step: number): number {\n const next = direction === \"in\" ? current + step : current - step;\n return next > 0 ? Number(next.toFixed(4)) : current;\n}\n\n/** Resolves the neighbor tab index a switchtab step activates, wrapping at both ends of the window. */\nexport function switchtarget(tabs: tabshape[], direction: \"next\" | \"previous\", currentindex: number): number | undefined {\n if (tabs.length === 0) return undefined;\n const offset = direction === \"next\" ? 1 : -1;\n return (currentindex + offset + tabs.length) % tabs.length;\n}\n\n/** Orders the quick switcher list by recency with filter keys; unseen tabs follow in live index order. */\nexport function switcherlist(tabs: tabshape[], recency: Array<{ tabid: number; at: number }>, filter: string): tabshape[] {\n const needle = filter.trim().toLowerCase();\n const matches = needle ? tabs.filter(tab => tab.title.toLowerCase().includes(needle) || tab.url.toLowerCase().includes(needle)) : [...tabs];\n const lastrun = new Map(recency.map(entry => [entry.tabid, entry.at]));\n return [...matches].sort((left, right) => {\n const leftat = lastrun.get(left.tabid) ?? -1;\n const rightat = lastrun.get(right.tabid) ?? -1;\n if (leftat !== rightat) return rightat - leftat;\n return left.index - right.index;\n });\n}\n\n/** Dispatches the tab events of one watchtab registration into the step result, honoring the reviewed event filters. */\nexport function watchtabdispatch(events: tabwatchevent[], watchid: string, filters: string[]): tabwatchevent[] {\n const allowed = filters.length > 0 ? new Set(filters) : undefined;\n return events.filter(event => event.watchid === watchid && (allowed === undefined || allowed.has(event.event)));\n}\n\n/** Computes the per task badge from the live progress state of the task. */\nexport function badgefromprogress(completed: number, total: number): { label: string; done: boolean } {\n if (total <= 0) return { label: \"idle\", done: false };\n if (completed >= total) return { label: \"done\", done: true };\n return { label: `${completed}/${total}`, done: false };\n}\n\n/** Grades the concurrent task tab budget: a user configured ceiling refuses, an absent ceiling never refuses. */\nexport function tasktabgauge(used: number, ceiling: number | undefined): { used: number; ceiling: number | undefined; over: boolean } {\n return { used, ceiling, over: ceiling !== undefined && used > ceiling };\n}\n\n/** True when a window profile inherits the session origin grants; incognito windows stay separated. */\nexport function windowprofilegrants(profile: \"normal\" | \"incognito\" | \"scratch\"): boolean {\n return profile !== \"incognito\";\n}\n\n/** Assigns every task tab of the plan progress, used when tabmeta routing records a tab for the plan steps. */\nexport function assigntasktabs(progress: planprogress | undefined, planid: string, tabids: number[], now: number): planprogress {\n let next = progress;\n for (const tabid of tabids) next = assigntasktab(next, planid, tabid, now);\n return next ?? { planid, completedsteps: [], tasktabs: [], updatedat: now };\n}\n\n/** Returns the task tabs tracked by one plan progress, used for window close review and badge refresh. */\nexport function trackedtasktabs(progress: planprogress | undefined, planid: string): number[] {\n return tasktabs(progress, planid);\n}\n", "import type { fielderror, fieldkind, fieldmatch, formrecord, formentry, formreport, toolstep } from \"../types.js\";\nimport { parseoptions } from \"../policy.js\";\nimport type { stepresult } from \"./pageactions.js\";\nimport { clean, elementlabel as label, elementselector as selector } from \"./pageresolve.js\";\n\n/**\n * Form field logics for reviewed steps.\n * Every correlated rule for field matching, field kind classification, seeded value generation, native value fills, honeypot detection, login and template detection, error association and form record parsing lives in this file.\n */\n\n/** One serializable form field shape resolved against the page controls. */\nexport interface fieldshape {\n selector: string;\n tag: string;\n type: string;\n name: string;\n label: string;\n placeholder: string;\n arialabel: string;\n autocomplete: string;\n options?: string[];\n}\n\n/** One surveyed field shape carrying the visibility, geometry and timing evidence the honeypot detector reads. */\nexport interface fieldsurvey extends fieldshape {\n hidden: boolean;\n offscreen: boolean;\n createdat?: number;\n}\n\n/** One honeypot field flagged by hidden, offscreen or time trap evidence. */\nexport interface honeypotevidence {\n selector: string;\n reason: \"hidden\" | \"offscreen\" | \"timetrap\";\n}\n\n/** One surveyed field with the aria describedby ref and the sibling message texts the error reader associates. */\nexport interface errorcontext extends fieldshape {\n describedby?: string;\n siblings: string[];\n}\n\n/** Resolves controls by label, placeholder, aria label and name attributes; matches are case insensitive substrings. */\nexport function matchfield(fields: fieldshape[], match: fieldmatch): fieldshape[] {\n const key = match.mode === \"label\" ? \"label\" : match.mode === \"placeholder\" ? \"placeholder\" : match.mode === \"arialabel\" ? \"arialabel\" : \"name\";\n const needle = (match[key] ?? \"\").trim().toLowerCase();\n if (!needle) return [];\n return fields.filter(field => {\n const primary = (field[key] as string).toLowerCase();\n const secondary = match.mode === \"label\" || match.mode === \"name\" ? field.name.toLowerCase() : match.mode === \"placeholder\" ? field.arialabel.toLowerCase() : field.placeholder.toLowerCase();\n return primary.includes(needle) || secondary.includes(needle);\n });\n}\n\n/** Infers the field kind of one control from its input type, autocomplete hint and label text. */\nexport function classifyfield(input: { type: string; autocomplete: string; label: string }): fieldkind {\n const type = input.type.toLowerCase();\n const autocomplete = input.autocomplete.toLowerCase();\n const label = input.label.toLowerCase();\n if (type === \"password\") return \"password\";\n if (autocomplete.startsWith(\"cc-\") || label.includes(\"card number\") || label.includes(\"credit card\") || label.includes(\"cardholder\")) return \"card\";\n if (autocomplete.includes(\"one-time-code\") || autocomplete.includes(\"otp\") || label.includes(\"one time code\") || label.includes(\"verification code\") || label.includes(\"otp\")) return \"code\";\n if (type === \"email\" || autocomplete.includes(\"email\") || label.includes(\"email\")) return \"email\";\n if (type === \"tel\" || autocomplete.includes(\"tel\") || label.includes(\"phone\") || label.includes(\"telephone\")) return \"phone\";\n if (type === \"date\") return \"date\";\n if (type === \"number\") return \"number\";\n if (type === \"checkbox\") return \"check\";\n if (type === \"radio\") return \"radio\";\n if (type === \"file\") return \"file\";\n if (type === \"select\" || type === \"select-one\") return \"select\";\n return \"text\";\n}\n\nconst firstnames: Record<string, string[]> = { en: [\"alex\", \"jordan\", \"taylor\", \"morgan\", \"casey\"], pt: [\"ana\", \"bruno\", \"carla\", \"diego\", \"helena\"] };\nconst lastnames: Record<string, string[]> = { en: [\"brooks\", \"carter\", \"diaz\", \"evans\", \"reyes\"], pt: [\"alves\", \"costa\", \"lima\", \"souza\", \"moraes\"] };\n\nfunction localekey(locale: string): string {\n const normalized = locale.toLowerCase();\n if (normalized.startsWith(\"pt\")) return \"pt\";\n return \"en\";\n}\n\n/** Generates one realistic value for a field kind, deterministically seeded and locale aware for names, emails and phones. */\nexport function generatevalue(kind: fieldkind, rule: { locale?: string; seed?: number }): string {\n const seed = typeof rule.seed === \"number\" && Number.isFinite(rule.seed) ? Math.abs(Math.floor(rule.seed)) : 1;\n const names = firstnames[localekey(rule.locale ?? \"en\")] ?? firstnames.en ?? [\"alex\"];\n const surnames = lastnames[localekey(rule.locale ?? \"en\")] ?? lastnames.en ?? [\"brooks\"];\n let state = seed * 1103515245 + 12345;\n const next = (): number => { state = (state * 1103515245 + 12345) % 2147483648; return state / 2147483648; };\n const pick = <T>(items: T[]): T => items[Math.floor(next() * items.length) % items.length] ?? items[0] as T;\n const digits = (count: number): string => Array.from({ length: count }, () => String(Math.floor(next() * 10))).join(\"\");\n const person = `${pick(names)} ${pick(surnames)}`;\n switch (kind) {\n case \"email\": return `${person.replace(\" \", \".\")}${digits(2)}@example.com`;\n case \"phone\": return localekey(rule.locale ?? \"en\") === \"pt\" ? `+55 (11) 9${digits(4)}-${digits(4)}` : `+1 (555) 010-${digits(4)}`;\n case \"date\": return `${2024 + Math.floor(next() * 2)}-${String(1 + Math.floor(next() * 12)).padStart(2, \"0\")}-${String(1 + Math.floor(next() * 28)).padStart(2, \"0\")}`;\n case \"number\": return String(Math.floor(next() * 1000));\n case \"select\": return `option ${1 + Math.floor(next() * 5)}`;\n case \"check\": return next() > 0.5 ? \"true\" : \"false\";\n case \"radio\": return `choice ${1 + Math.floor(next() * 4)}`;\n case \"file\": return `sample${digits(2)}.pdf`;\n case \"password\": return `pw-${digits(6)}-${pick(names)}`;\n case \"card\": return `4111 ${digits(4)} ${digits(4)} ${digits(4)}`;\n case \"code\": return digits(6);\n default: return person;\n }\n}\n\n/** Builds a deterministic values hash of the reviewed field values a submission ticket records. */\nexport function valueshash(values: Array<{ label: string; value: string }>): string {\n const source = values.map(entry => `${entry.label}=${entry.value}`).join(\"|\");\n let hash = 5381;\n for (let index = 0; index < source.length; index += 1) hash = ((hash * 33) ^ source.charCodeAt(index)) >>> 0;\n return hash.toString(16);\n}\n\n/** Parses the reviewed structured form record of a step; null when the step reviews none or the shape is invalid. */\nexport function parseformrecord(value: unknown): formrecord | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n if (!Array.isArray(record.entries)) return null;\n const entries: formentry[] = [];\n for (const item of record.entries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n const entry = item as Record<string, unknown>;\n const match = entry.match;\n if (!match || typeof match !== \"object\" || Array.isArray(match)) continue;\n const shapes = match as Record<string, unknown>;\n if (typeof shapes.mode !== \"string\") continue;\n const fieldmatch: fieldmatch = {\n mode: shapes.mode as fieldmatch[\"mode\"],\n ...(typeof shapes.label === \"string\" ? { label: shapes.label } : {}),\n ...(typeof shapes.placeholder === \"string\" ? { placeholder: shapes.placeholder } : {}),\n ...(typeof shapes.arialabel === \"string\" ? { arialabel: shapes.arialabel } : {}),\n ...(typeof shapes.name === \"string\" ? { name: shapes.name } : {}),\n };\n if (typeof entry.kind !== \"string\" || typeof entry.value !== \"string\") continue;\n entries.push({ match: fieldmatch, kind: entry.kind as fieldkind, value: entry.value });\n }\n if (entries.length === 0) return null;\n return { ...(typeof record.form === \"string\" && record.form ? { form: record.form } : {}), entries };\n}\n\n/** Builds form record entries from reviewed label or placeholder value pairs. */\nexport function pairentries(pairs: Array<{ label?: string; placeholder?: string; value: string }>, mode: \"label\" | \"placeholder\"): formrecord {\n return { entries: pairs.map(pair => ({ match: mode === \"label\" ? { mode, label: pair.label ?? \"\" } : { mode, placeholder: pair.placeholder ?? \"\" }, kind: \"text\", value: pair.value })) };\n}\n\n/** One fill operation outcome: the entry, the matched control, the honeypot skip flag or the refusal reason. */\nexport interface filloutcome {\n entry: formentry;\n matched?: fieldshape;\n skipped?: boolean;\n reason?: string;\n}\n\n/** Resolves every entry of a form record against the surveyed fields, skipping honeypots and refusing unmatched or ambiguous entries. */\nexport function filloperations(record: formrecord, fields: fieldshape[], skippedselectors: string[] = []): filloutcome[] {\n return record.entries.map(entry => {\n const matches = matchfield(fields, entry.match);\n if (matches.length === 0) return { entry, reason: \"unmatched\" };\n if (matches.length > 1) return { entry, reason: \"ambiguous\" };\n const matched = matches[0] as fieldshape;\n if (skippedselectors.includes(matched.selector)) return { entry, matched, skipped: true };\n return { entry, matched };\n });\n}\n\n/** Masks one card segment so side panels can render card fills without exposing the full value. */\nexport function cardmask(value: string): string {\n const trimmed = value.trim();\n if (/^\\d[\\d\\s-]{11,18}$/.test(trimmed)) {\n const compact = trimmed.replace(/[\\s-]/g, \"\");\n const last = compact.slice(-4);\n return `${\"\u2022\".repeat(Math.max(0, compact.length - 4))}${last}`;\n }\n return \"\u2022\".repeat(trimmed.length);\n}\n\n/** Flags hidden, offscreen and time trap fields so fill steps skip them instead of tripping anti bot defenses. */\nexport function detecthoneypots(surveys: fieldsurvey[], loadedat: number): honeypotevidence[] {\n const traps: honeypotevidence[] = [];\n for (const field of surveys) {\n if (field.hidden) traps.push({ selector: field.selector, reason: \"hidden\" });\n else if (field.offscreen) traps.push({ selector: field.selector, reason: \"offscreen\" });\n else if (field.createdat !== undefined && loadedat > 0 && field.createdat > loadedat) traps.push({ selector: field.selector, reason: \"timetrap\" });\n }\n return traps;\n}\n\n/** Detects a login form: a password field plus an identifier field with session links nearby. */\nexport function detectlogin(fields: fieldshape[], links: string[]): { login: boolean; markers: string[] } {\n const markers: string[] = [];\n const password = fields.find(field => classifyfield(field) === \"password\");\n if (password) markers.push(\"password field\");\n const identifier = fields.find(field => {\n const kind = classifyfield(field);\n return kind === \"email\" || (kind === \"text\" && /user|login|account|identifier/i.test(`${field.name} ${field.label}`));\n });\n if (identifier) markers.push(\"identifier field\");\n const sessionlink = links.some(link => /sign in|log in|log on|forgot|create account|sign up/i.test(link));\n if (sessionlink) markers.push(\"session link\");\n return { login: Boolean(password && identifier && sessionlink), markers };\n}\n\nconst signupmarkers = [\"sign up\", \"create account\", \"register\", \"confirm password\", \"terms\"];\nconst checkoutmarkers = [\"checkout\", \"payment\", \"billing\", \"shipping\", \"card number\", \"place order\", \"cart\"];\n\n/** Detects signup and checkout templates by matching the field labels, autocompletes and page text against known markers. */\nexport function detecttemplate(fields: fieldshape[], text: string): { template: \"signup\" | \"checkout\" | \"unknown\"; markers: string[] } {\n const corpus = [text, ...fields.map(field => `${field.label} ${field.name} ${field.placeholder} ${field.arialabel} ${field.autocomplete}`)].join(\" \").toLowerCase();\n const signup = signupmarkers.filter(marker => corpus.includes(marker));\n const checkout = checkoutmarkers.filter(marker => corpus.includes(marker));\n if (signup.length >= 2 && signup.length >= checkout.length) return { template: \"signup\", markers: signup };\n if (checkout.length >= 2) return { template: \"checkout\", markers: checkout };\n return { template: \"unknown\", markers: [...signup, ...checkout] };\n}\n\n/** Associates validation messages with fields through aria describedby refs and the sibling text next to each field. */\nexport function associateerrors(contexts: errorcontext[], messages: Array<{ id?: string; text: string }>): fielderror[] {\n const errors: fielderror[] = [];\n for (const field of contexts) {\n const byref = field.describedby ? messages.find(message => message.id === field.describedby && message.text.trim()) : undefined;\n if (byref) { errors.push({ field: field.selector, message: byref.text.trim() }); continue; }\n const sibling = field.siblings.map(text => text.trim()).find(text => text.length > 0);\n if (sibling) errors.push({ field: field.selector, message: sibling });\n }\n return errors;\n}\n\n/** Resolves one reviewed artifact name against the run store before a file input is filled. */\nexport function attachplan(name: string, artifacts: Array<{ id: string; name: string; kind: string }>): { artifact?: { id: string; name: string; kind: string }; reason?: string } {\n const artifact = artifacts.find(item => item.name === name || item.id === name);\n if (!artifact) return { reason: \"The reviewed artifact name is not part of the run store.\" };\n return { artifact };\n}\n\n/** Selectors the captcha detector probes; a hit hands control back to the user instead of forcing the page. */\nexport const captchamarkers = ['iframe[src*=\"recaptcha\"]', 'iframe[title*=\"recaptcha\" i]', '.g-recaptcha', '[data-sitekey]', 'iframe[title*=\"captcha\" i]', '.h-captcha'];\n\n/** True when any captcha marker matched, so the plan pauses and hands control to the user. */\nexport function captchadetected(matched: string[]): boolean {\n return matched.length > 0;\n}\n\nfunction events(target: Element): void {\n target.dispatchEvent(new Event(\"input\", { bubbles: true }));\n target.dispatchEvent(new Event(\"change\", { bubbles: true }));\n}\n\n/** Fills one control through the native setter with input and change events; checks, radios and selects use their own grammar. */\nexport function fillcontrol(element: Element, entry: formentry): boolean {\n if (element instanceof HTMLInputElement && (entry.kind === \"check\" || element.type === \"checkbox\")) { element.checked = entry.value === \"true\" || entry.value === \"on\" || entry.value === \"checked\"; events(element); return true; }\n if (element instanceof HTMLInputElement && (entry.kind === \"radio\" || element.type === \"radio\")) { element.checked = true; events(element); return true; }\n if (element instanceof HTMLSelectElement) {\n const option = [...element.options].find(candidate => candidate.value === entry.value || candidate.textContent?.trim() === entry.value);\n if (!option) return false;\n element.value = option.value;\n events(element);\n return true;\n }\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n if (element instanceof HTMLInputElement && element.type === \"file\") return false;\n element.focus();\n const setter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), \"value\")?.set;\n if (setter) setter.call(element, entry.value); else element.value = entry.value;\n events(element);\n return true;\n }\n return false;\n}\n\nfunction controlshape(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): fieldshape {\n return {\n selector: selector(element),\n tag: element.tagName.toLowerCase(),\n type: element instanceof HTMLSelectElement ? \"select\" : element.getAttribute(\"type\") || \"text\",\n name: element.getAttribute(\"name\") || \"\",\n label: label(element),\n placeholder: element.getAttribute(\"placeholder\") || \"\",\n arialabel: element.getAttribute(\"aria-label\") || \"\",\n autocomplete: element.getAttribute(\"autocomplete\") || \"\",\n ...(element instanceof HTMLSelectElement ? { options: [...element.options].map(option => option.value) } : {}),\n };\n}\n\n/** Collects the serializable field shapes of one form scope; absent scopes survey the whole document. */\nfunction collectfields(root: Document, formscope?: string): Array<{ shape: fieldshape; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n const scope = formscope ? root.querySelector(formscope) : root;\n if (!scope) return [];\n const controls = [...scope.querySelectorAll<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>(\"input, select, textarea\")];\n return controls.filter(element => element.type !== \"hidden\").map(element => ({ shape: controlshape(element), element }));\n}\n\n/** Surveys the visibility and geometry evidence the honeypot detector reads for one form scope. */\nfunction surveyfields(root: Document, formscope?: string): Array<{ survey: fieldsurvey; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n const viewport = { left: 0, top: 0, right: window.innerWidth || 0, bottom: window.innerHeight || 0 };\n return collectfields(root, formscope).map(({ shape, element }) => {\n const rect = element.getBoundingClientRect();\n const hidden = element.getAttribute(\"aria-hidden\") === \"true\" || element.tabIndex < 0 && (element as HTMLElement).offsetParent === null || (element as HTMLElement).offsetParent === null && rect.width === 0 && rect.height === 0;\n const offscreen = rect.width > 0 && rect.height > 0 && (rect.bottom < viewport.top || rect.top > viewport.bottom || rect.right < viewport.left || rect.left > viewport.right);\n return { survey: { ...shape, hidden, offscreen }, element };\n });\n}\n\n/** Reads the error context of one form scope: describedby refs and the sibling texts after each field. */\nfunction collecterrorcontext(root: Document, formscope?: string): Array<{ context: errorcontext; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n return collectfields(root, formscope).map(({ shape, element }) => {\n const siblings: string[] = [];\n let neighbor = element.nextElementSibling;\n for (let index = 0; neighbor && index < 3; index += 1) {\n const text = clean(neighbor.textContent || \"\");\n if (text && text !== shape.label) siblings.push(text);\n neighbor = neighbor.nextElementSibling;\n }\n const describedby = element.getAttribute(\"aria-describedby\");\n return { context: { ...shape, ...(describedby ? { describedby } : {}), siblings }, element };\n });\n}\n\n/** Runs one reviewed forms and data step inside the page: fills, surveys, detects and reads errors without leaving the form scope. */\nexport function runpageform(step: toolstep, target: Element | null, root: Document = document): stepresult | Promise<stepresult> {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const formscope = typeof options.form === \"string\" && options.form ? options.form : step.target;\n switch (step.kind) {\n case \"fillform\": {\n const record = parseformrecord(options.formrecord);\n if (!record) return { ok: false, summary: \"A reviewed form record with entries is required in options.\" };\n const surveys = surveyfields(root, record.form);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const operations = filloperations(record, surveys.map(entry => entry.survey), honeypots.map(trap => trap.selector));\n let filled = 0;\n const skipped: string[] = [];\n const failures: string[] = [];\n const values: Array<{ label: string; value: string }> = [];\n for (const operation of operations) {\n if (operation.skipped && operation.matched) { skipped.push(operation.matched.selector); continue; }\n if (!operation.matched) { failures.push(`${operation.reason}: ${operation.entry.match.label ?? operation.entry.match.name ?? operation.entry.match.placeholder ?? \"field\"}`); continue; }\n const element = surveys.find(entry => entry.survey.selector === operation.matched?.selector)?.element;\n if (!element || !fillcontrol(element, operation.entry)) { failures.push(`unfillable: ${operation.matched.selector}`); continue; }\n filled += 1;\n values.push({ label: operation.matched.label || operation.matched.name, value: operation.entry.kind === \"password\" ? \"\" : operation.entry.value });\n }\n const report: formreport = { form: record.form ?? \"\", fields: operations.map(operation => ({ selector: operation.matched?.selector ?? \"\", label: operation.matched?.label ?? operation.entry.match.label ?? \"\", kind: operation.entry.kind, matched: Boolean(operation.matched) })) };\n return {\n ok: failures.length === 0,\n summary: failures.length === 0 ? `Filled ${filled} reviewed field${filled === 1 ? \"\" : \"s\"} from the structured record${skipped.length > 0 ? ` and skipped ${skipped.length} honeypot field${skipped.length === 1 ? \"\" : \"s\"}` : \"\"}.` : `Filled ${filled} of ${record.entries.length} reviewed fields; ${failures.length} refusals: ${failures.join(\"; \")}.`,\n details: { filled, skipped, failures, values, report },\n };\n }\n case \"filllabel\":\n case \"fillplaceholder\": {\n const mode = step.kind === \"filllabel\" ? \"label\" : \"placeholder\";\n const pairs = Array.isArray(options.fields) ? (options.fields as Array<Record<string, unknown>>).filter(item => item && typeof item === \"object\") : [];\n const record = pairentries(pairs.map(pair => ({ label: typeof pair.label === \"string\" ? pair.label : \"\", placeholder: typeof pair.placeholder === \"string\" ? pair.placeholder : \"\", value: typeof pair.value === \"string\" ? pair.value : \"\" })), mode);\n if (record.entries.length === 0) return { ok: false, summary: \"A reviewed non-empty list of field pairs is required in options.\" };\n const surveys = surveyfields(root, formscope);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const operations = filloperations(record, surveys.map(entry => entry.survey), honeypots.map(trap => trap.selector));\n let filled = 0;\n const failures: string[] = [];\n for (const operation of operations) {\n if (operation.skipped) continue;\n if (!operation.matched) { failures.push(`${operation.reason}: ${mode === \"label\" ? operation.entry.match.label : operation.entry.match.placeholder}`); continue; }\n const element = surveys.find(entry => entry.survey.selector === operation.matched?.selector)?.element;\n const refined: formentry = { ...operation.entry, kind: classifyfield(operation.matched) };\n if (!element || !fillcontrol(element, refined)) { failures.push(`unfillable: ${operation.matched.selector}`); continue; }\n filled += 1;\n }\n return { ok: failures.length === 0, summary: failures.length === 0 ? `Filled ${filled} field${filled === 1 ? \"\" : \"s\"} matched by ${mode}.` : `Filled ${filled} of ${record.entries.length} fields matched by ${mode}; ${failures.join(\"; \")}.`, details: { filled, failures, mode } };\n }\n case \"detectfields\": {\n const collected = collectfields(root, formscope);\n const report: formreport = { form: formscope ?? \"\", fields: collected.map(entry => ({ selector: entry.shape.selector, label: entry.shape.label || entry.shape.name, kind: classifyfield(entry.shape), matched: Boolean(entry.shape.label || entry.shape.name) })) };\n return { ok: true, summary: `Detected ${collected.length} form field${collected.length === 1 ? \"\" : \"s\"} with their kinds.`, details: { report, count: collected.length } };\n }\n case \"generatevalues\": {\n const rule = options.valuegen && typeof options.valuegen === \"object\" && !Array.isArray(options.valuegen) ? options.valuegen as Record<string, unknown> : {};\n const locale = typeof rule.locale === \"string\" ? rule.locale : \"en\";\n const seed = typeof rule.seed === \"number\" && Number.isFinite(rule.seed) ? rule.seed : 1;\n const surveys = surveyfields(root, formscope);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const skippedselectors = new Set(honeypots.map(trap => trap.selector));\n const candidates = surveys.filter(entry => !skippedselectors.has(entry.survey.selector));\n const values = candidates.map(entry => ({ label: entry.survey.label || entry.survey.name || entry.survey.selector, kind: classifyfield(entry.survey), value: generatevalue(classifyfield(entry.survey), { locale, seed }) }));\n const single = values.length === 0 && typeof rule.kind === \"string\" ? [{ label: rule.kind, kind: rule.kind, value: generatevalue(rule.kind as fieldkind, { locale, seed }) }] : values;\n return { ok: true, summary: `Generated ${single.length} realistic value${single.length === 1 ? \"\" : \"s\"} for the detected field kinds.`, details: { values: single, locale, seed } };\n }\n case \"readerrors\": {\n const contexts = collecterrorcontext(root, formscope);\n const messages = [...root.querySelectorAll<HTMLElement>(\"[id]\")].map(element => ({ id: element.id, text: clean(element.textContent || \"\") })).filter(message => message.text.length > 0);\n const errors = associateerrors(contexts.map(entry => entry.context), messages);\n return { ok: true, summary: errors.length === 0 ? \"No validation error was found next to the reviewed fields.\" : `Collected ${errors.length} inline validation message${errors.length === 1 ? \"\" : \"s\"}.`, details: { errors, form: formscope ?? \"\" } };\n }\n case \"skiphoneypot\": {\n const surveys = surveyfields(root, formscope);\n const traps = detecthoneypots(surveys.map(entry => entry.survey), 0);\n return { ok: true, summary: traps.length === 0 ? \"No honeypot field was detected.\" : `Skipped ${traps.length} honeypot field${traps.length === 1 ? \"\" : \"s\"}: ${traps.map(trap => `${trap.selector} (${trap.reason})`).join(\", \")}.`, details: { skipped: traps } };\n }\n case \"detectlogin\": {\n const collected = collectfields(root, formscope);\n const links = [...(formscope ? root.querySelectorAll(formscope) : [root] as unknown as Element[])].flatMap(scope => [...scope.querySelectorAll(\"a[href], button\")]).map(element => clean(element.textContent || \"\"));\n const detection = detectlogin(collected.map(entry => entry.shape), links);\n return { ok: true, summary: detection.login ? `Login form detected with ${detection.markers.join(\", \")}.` : \"No login form was detected.\", details: { login: detection.login, markers: detection.markers } };\n }\n case \"detecttemplate\": {\n const collected = collectfields(root, formscope);\n const text = clean(root.body?.innerText || \"\");\n const detection = detecttemplate(collected.map(entry => entry.shape), text);\n return { ok: true, summary: detection.template === \"unknown\" ? \"No signup or checkout template was detected.\" : `${detection.template} template detected with markers ${detection.markers.join(\", \")}.`, details: { template: detection.template, markers: detection.markers } };\n }\n case \"handoffcaptcha\": {\n const matched = captchamarkers.filter(marker => root.querySelector(marker) !== null);\n return { ok: true, summary: captchadetected(matched) ? `Captcha presence detected (${matched.join(\", \")}); control hands back to the user.` : \"No captcha was detected.\", details: { captcha: captchadetected(matched), markers: matched } };\n }\n case \"asksubmit\": {\n const collected = collectfields(root, step.value || undefined);\n const values = collected.map(entry => ({ label: entry.shape.label || entry.shape.name || entry.shape.selector, value: entry.element instanceof HTMLSelectElement ? entry.element.value : (entry.element as HTMLInputElement).value }));\n return { ok: true, summary: `Read ${values.length} field value${values.length === 1 ? \"\" : \"s\"} for the submission review.`, details: { values } };\n }\n case \"submitform\": {\n const form = target instanceof HTMLFormElement ? target : target instanceof HTMLElement ? target.closest(\"form\") : null;\n if (!form) return { ok: false, summary: \"No owning form was found for the reviewed submission.\" };\n form.requestSubmit();\n return { ok: true, summary: \"Form submitted programmatically through its owning form.\" };\n }\n case \"consentpassword\": {\n if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return { ok: false, summary: \"The reviewed password target cannot receive text.\" };\n const entry: formentry = { match: { mode: \"name\", name: target.name || target.getAttribute(\"id\") || \"\" }, kind: \"password\", value: step.value ?? \"\" };\n if (!fillcontrol(target, entry)) return { ok: false, summary: \"The password field refused the native setter fill.\" };\n return { ok: true, summary: \"Password field filled after the reviewed consent; the value never appears in the audit trail.\" };\n }\n case \"attachfile\": {\n if (!(target instanceof HTMLInputElement) || target.type !== \"file\") return { ok: false, summary: \"The reviewed target is not a file input.\" };\n const artifactname = typeof options.artifactname === \"string\" && options.artifactname ? options.artifactname : \"artifact\";\n try {\n const file = new File([new Blob([\"devthink artifact\"], { type: \"application/octet-stream\" })], artifactname);\n const transfer = new DataTransfer();\n transfer.items.add(file);\n target.files = transfer.files;\n events(target);\n return { ok: true, summary: `Artifact ${artifactname} attached to the reviewed file input.`, details: { artifact: options.artifact, artifactname } };\n } catch {\n return { ok: false, summary: \"The reviewed file input refused the artifact attachment.\" };\n }\n }\n default: return { ok: false, summary: \"Unsupported forms and data action.\" };\n }\n}\n", "import type { artifactrecord, columnspec, dataset, datasetrow, exportedartifact, extractsession, provenancerecord, streamstate, toolstep, transformrule } from \"../types.js\";\nimport { tocsv, toexcel, tojson } from \"./pagedata.js\";\n\n/**\n * Dataset command logics for the background executors.\n * Every correlated rule for dataset records, artifact exports with checksums, chunked streaming with backpressure, extraction cursors, loop row variables, provenance records and artifact retention lives in this file.\n */\n\n/** Builds one dataset record from a scraped grid result. */\nexport function builddataset(id: string, name: string, grid: { columns: columnspec[]; rows: datasetrow[]; children?: Array<{ parentrow: number; selector: string; columns: columnspec[]; rows: datasetrow[] }> }, at: number): dataset {\n return { id, name: name || id, columns: grid.columns, rows: grid.rows, sources: [], at };\n}\n\n/** Computes the deterministic checksum of an exported artifact's content. */\nexport function checksum(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) hash = ((hash * 33) ^ value.charCodeAt(index)) >>> 0;\n return `fnv1a-${hash.toString(16)}`;\n}\n\n/** Serializes one dataset into the reviewed export format. */\nexport function exportcontent(datasetvalue: dataset, format: \"csv\" | \"json\" | \"excel\", delimiter = \",\"): string {\n if (format === \"json\") return tojson(datasetvalue.columns, datasetvalue.rows);\n if (format === \"excel\") return toexcel(datasetvalue.columns, datasetvalue.rows, datasetvalue.name);\n return tocsv(datasetvalue.columns, datasetvalue.rows, delimiter);\n}\n\n/** Builds one exported artifact record with its content and checksum for the task artifact store. */\nexport function exportartifact(id: string, datasetvalue: dataset, format: \"csv\" | \"json\" | \"excel\", stepid: string, content: string, at: number): exportedartifact {\n const extension = format === \"excel\" ? \"xml\" : format;\n return { id, kind: format, name: `${datasetvalue.name || datasetvalue.id}.${extension}`, stepid, rowcount: datasetvalue.rows.length, content, checksum: checksum(content), at };\n}\n\n/** Converts one exported artifact into the artifact record shape the run store keeps. */\nexport function artifactrecordof(artifact: exportedartifact): artifactrecord {\n return { id: artifact.id, kind: artifact.kind, name: artifact.name, stepid: artifact.stepid, at: artifact.at };\n}\n\n/** Plans the chunk boundaries of a streaming export from a user configured chunk size with no code ceiling. */\nexport function chunkplan(rows: number, chunk: number): Array<{ index: number; from: number; to: number }> {\n const size = Math.max(1, Math.floor(chunk));\n const chunks: Array<{ index: number; from: number; to: number }> = [];\n for (let from = 0; from < rows || chunks.length === 0; from += size) {\n const to = Math.min(rows, from + size);\n chunks.push({ index: chunks.length, from, to });\n if (to >= rows) break;\n }\n return chunks;\n}\n\n/** True when the stream writer must wait for acknowledgements: pending writes reached the in-flight budget of one. */\nexport function backpressure(written: number, acknowledged: number): boolean {\n return written - acknowledged >= 1;\n}\n\n/** Advances one stream state by one acknowledged chunk of rows. */\nexport function advancestream(state: streamstate, chunk: { index: number; to: number }, at: number, done: boolean): streamstate {\n return { datasetid: state.datasetid, name: state.name, chunk: chunk.index + 1, chunks: state.chunks, written: chunk.to, ...(done ? { done: true } : {}), at };\n}\n\n/** Returns the first unwritten row index of a stream, starting a fresh stream at zero. */\nexport function streamfrom(state: streamstate | undefined, rows: number): number {\n if (!state || state.done) return 0;\n return Math.min(state.written, rows);\n}\n\n/** Builds the initial stream state of one dataset. */\nexport function newstream(datasetvalue: dataset, chunks: number, at: number): streamstate {\n return { datasetid: datasetvalue.id, name: datasetvalue.name, chunk: 0, chunks, written: 0, at };\n}\n\n/** Advances one extraction session by one extracted page with its row count. */\nexport function advancecursor(sessionvalue: extractsession, page: string, rows: number, at: number, done: boolean): extractsession {\n return {\n id: sessionvalue.id,\n datasetid: sessionvalue.datasetid,\n name: sessionvalue.name,\n target: sessionvalue.target,\n next: sessionvalue.next,\n planned: sessionvalue.planned,\n pages: [...sessionvalue.pages, page],\n rows: sessionvalue.rows + rows,\n cursor: sessionvalue.cursor + 1,\n ...(done || sessionvalue.cursor + 1 >= sessionvalue.planned ? { done: true } : {}),\n startedat: sessionvalue.startedat,\n updatedat: at,\n };\n}\n\n/** Builds the initial extraction session of one dataset extraction. */\nexport function newextractsession(id: string, datasetid: string, name: string, target: string, next: string, planned: number, at: number): extractsession {\n return { id, datasetid, name, target, next, planned, pages: [], rows: 0, cursor: 0, startedat: at, updatedat: at };\n}\n\n/** Returns the pages an interrupted extraction still owes after its stored cursor. */\nexport function remainingpages(sessionvalue: extractsession, planned: number): number {\n if (sessionvalue.done) return 0;\n return Math.max(0, Math.max(sessionvalue.planned, planned) - sessionvalue.cursor);\n}\n\n/** Builds one provenance record of an exported artifact with its source url, step ref, row range and checksum. */\nexport function provenancefor(artifact: { id: string; name: string; rowcount: number; checksum: string }, url: string, stepid: string, at: number): provenancerecord {\n return { artifact: artifact.id, name: artifact.name, url, stepid, rowstart: artifact.rowcount > 0 ? 1 : 0, rowend: artifact.rowcount, checksum: artifact.checksum, at };\n}\n\n/** Applies the user configured artifact retention to exported artifacts; an absent setting keeps everything. */\nexport function retainedexports<T>(records: T[], retention: number | undefined): T[] {\n return retention === undefined ? records : records.slice(0, retention);\n}\n\n/** Interpolates one text through the {{column}} tokens of a dataset row. */\nexport function interpolate(text: string, row: datasetrow): string {\n return text.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key: string) => row[key.trim()] ?? \"\");\n}\n\n/** Substitutes the row variables of one looprows iteration into the target, value and options of the inner step. */\nexport function loopstep(step: toolstep, row: datasetrow): toolstep {\n return {\n ...step,\n ...(step.target !== undefined ? { target: interpolate(step.target, row) } : {}),\n ...(step.value !== undefined ? { value: interpolate(step.value, row) } : {}),\n ...(step.options !== undefined ? { options: interpolate(step.options, row) } : {}),\n };\n}\n\n/** Exposes one dataset row as the step variables of a looprows iteration. */\nexport function loopvariables(row: datasetrow): datasetrow {\n return { ...row };\n}\n\n/** Builds the grid preview of a dataset with its column order, total rows and sampled rows. */\nexport function gridpreview(datasetvalue: dataset, sample: number): { datasetid: string; columns: string[]; rows: number; sample: datasetrow[] } {\n return { datasetid: datasetvalue.id, columns: datasetvalue.columns.map(column => column.key), rows: datasetvalue.rows.length, sample: datasetvalue.rows.slice(0, Math.max(0, Math.floor(sample))) };\n}\n\n/** Sorts dataset rows by one column key in the reviewed direction with a stable fallback for equal values. */\nexport function sortrows(rows: datasetrow[], key: string, direction: \"asc\" | \"desc\"): datasetrow[] {\n const sign = direction === \"desc\" ? -1 : 1;\n return [...rows].sort((left, right) => {\n const a = left[key] ?? \"\";\n const b = right[key] ?? \"\";\n const numeric = Number(a);\n const numericb = Number(b);\n if (Number.isFinite(numeric) && Number.isFinite(numericb) && a.trim() !== \"\" && b.trim() !== \"\") return (numeric - numericb) * sign;\n return a.localeCompare(b) * sign;\n });\n}\n\n/** Builds the sheet push payload of one dataset for a reviewed sheet endpoint. */\nexport function sheetpayload(datasetvalue: dataset, sheet: string): { sheet: string; columns: string[]; rows: datasetrow[] } {\n return { sheet, columns: datasetvalue.columns.map(column => column.key), rows: datasetvalue.rows };\n}\n\n/** Merges reviewed transform rules and dedupe keys into the task rules record of one task. */\nexport function mergetaskrules(existing: { taskid: string; transforms: transformrule[]; dedupekeys: string[] } | undefined, taskid: string, transforms: transformrule[], dedupekeys: string[], at: number): { taskid: string; transforms: transformrule[]; dedupekeys: string[]; at: number } {\n return {\n taskid,\n transforms: transforms.length > 0 ? transforms : (existing?.transforms ?? []),\n dedupekeys: dedupekeys.length > 0 ? dedupekeys : (existing?.dedupekeys ?? []),\n at,\n };\n}\n", "import type { a11ycapture, a11ynode, agentplan, artifactinventoryentry, artifactrecord, auditevent, autosnapshotstate, bannerreport, capabilityreport, captchahandoff, capturepolicy, cleanuprule, cleanuprun, clipboardconsentrecord, clipentry, clickablemap, closedtab, columnspec, consolediff, consoleconsentrecord, controltabstate, curatedlist, dataset, datasetrow, derivedselector, detectionrecord, diagnosticreport, downloadrecord, errorrecord, errorreport, extractsession, fielderror, focusevent, formprofile, listpattern, longtaskentry, mimefilter, mutationevent, navcontrol, navrecord, navqueues, netlogrecord, planprogress, provenancerecord, quarantineentry, ratelimitstate, readercapture, rejectionrecord, resolvedtarget, retryoutcome, safetyverdict, sessiondiff, sessionevent, sessionfolder, sessionrecord, sessionsnapshot, shotpair, snapshotdiff, stepoutcome, streamstate, submitticket, tabbadge, tabgrouprecord, tablayout, tabmeta, tableshape, taskrules, taskstate, timelineentry, toolstep, trailentry, transformrule, typeaheadpick, waitprofilerecord, wizardstate , actionkind, runlogentry, steptemplate, variablescope, workflowprovenance, workflowrecord, workflowrun, editormodel, editornode, editorlayout, exportformat, nestedparam, palettenode, runhistoryentry, siteoverride, steplibraryentry, variablekind, versiondiff, watchdogconfig, watchdogrecord, workflowversion} from \"../types.js\";\nimport { addedge, addnode, bindparam, buildsteplibrary, editstep, groupselect, markbreakpoint, minimapfocus, palettecategories, palettenodes, redoedit, removenode, removeedge, renderminimap, reordersteps, searchsteps, snapnode, undoedit, zoomcanvas } from \"../workfloweditor.js\";\nimport { switcherlist, type tabshape, type windowshape } from \"./tabscommand.js\";\nimport { cardmask } from \"./pageforms.js\";\nimport { sortrows } from \"./datacommand.js\";\n\nconst objective = document.querySelector<HTMLTextAreaElement>(\"#objective\");\nconst localbutton = document.querySelector<HTMLButtonElement>(\"#localplan\");\nconst remotebutton = document.querySelector<HTMLButtonElement>(\"#remoteplan\");\nconst diagnosticbutton = document.querySelector<HTMLButtonElement>(\"#diagnostic\");\nconst planroot = document.querySelector<HTMLElement>(\"#plan\");\nconst auditroot = document.querySelector<HTMLElement>(\"#audit\");\nconst diagnosticroot = document.querySelector<HTMLElement>(\"#diagnostics\");\nconst maproot = document.querySelector<HTMLElement>(\"#map\");\nconst a11yroot = document.querySelector<HTMLElement>(\"#a11y\");\nconst readerroot = document.querySelector<HTMLElement>(\"#reader\");\nconst detectionsroot = document.querySelector<HTMLElement>(\"#detections\");\nconst streamroot = document.querySelector<HTMLElement>(\"#stream\");\nconst diffsroot = document.querySelector<HTMLElement>(\"#diffs\");\nconst bannersroot = document.querySelector<HTMLElement>(\"#banners\");\nconst selectorsroot = document.querySelector<HTMLElement>(\"#selectors\");\nconst trailroot = document.querySelector<HTMLElement>(\"#trail\");\nconst navigationroot = document.querySelector<HTMLElement>(\"#navigation\");\nconst tabswindowsroot = document.querySelector<HTMLElement>(\"#tabswindows\");\nconst formsroot = document.querySelector<HTMLElement>(\"#forms\");\nconst datasetsroot = document.querySelector<HTMLElement>(\"#datasets\");\nconst filesroot = document.querySelector<HTMLElement>(\"#files\");\nconst capturesroot = document.querySelector<HTMLElement>(\"#captures\");\nconst mediaroot = document.querySelector<HTMLElement>(\"#media\");\nconst callsroot = document.querySelector<HTMLElement>(\"#calls\");\nconst trafficroot = document.querySelector<HTMLElement>(\"#traffic\");\nconst timelineroot = document.querySelector<HTMLElement>(\"#timeline\");\nconst consolediffroot = document.querySelector<HTMLElement>(\"#consolediff\");\nconst debuggerroot = document.querySelector<HTMLElement>(\"#debugger\");\nconst profilingroot = document.querySelector<HTMLElement>(\"#profiling\");\nconst emulationroot = document.querySelector<HTMLElement>(\"#emulation\");\nconst netviewroot = document.querySelector<HTMLElement>(\"#netview\");\nconst sessionsroot = document.querySelector<HTMLElement>(\"#sessions\");\nconst workflowsroot = document.querySelector<HTMLElement>(\"#workflows\");\nconst workfloweditorroot = document.querySelector<HTMLElement>(\"#workfloweditor\");\nconst triggersroot = document.querySelector<HTMLElement>(\"#triggers\");\nconst agentprotocolroot = document.querySelector<HTMLElement>(\"#agentprotocol\");\nconst triggerview = { manual: undefined as { id: string; workflowid: string; preview: Array<{ stepid: string; kind: string; label: string; block?: string; control?: Record<string, unknown> }>; at: number } | undefined, history: undefined as Array<{ id: string; ruleid: string; at: number; cause: string; url?: string; title?: string }> | undefined };\n/** Sessions view state: the search term and time window, the two diff selections, the pending restore review and the pending import review. */\nconst sessionsview = { term: \"\", window: \"all\" as \"all\" | \"hour\" | \"day\" | \"week\", diffselection: [] as string[], restorereview: undefined as sessionrecord | undefined, importreview: undefined as { records: Array<{ id: string; name: string; tabs: number }>; file: unknown } | undefined };\nconst workflowview = { review: undefined as { workflowid: string; name: string; risk: string; steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string; bindings?: unknown[]; expression?: { operator: string; result: string }; extract?: { groups: string[] }; control?: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } }> } | undefined, selected: \"\" as string };\n/** Workflow editor view state: the open canvas model with its undo and redo stacks, the node selection, the open step inspector, the palette and step library search terms, the run history filters with the last report, the pending import review and the version diff selection. */\nconst editorview = {\n workflowid: \"\" as string,\n model: undefined as editormodel | undefined,\n selected: [] as string[],\n inspector: \"\" as string,\n palettesearch: \"\",\n librarysearch: \"\",\n stepsearch: \"\",\n historyfilter: { workflowid: \"\", outcome: \"\" },\n history: undefined as runhistoryentry[] | undefined,\n importreview: undefined as { importid: string; workflowid: string; name: string; version: number; risk: string; steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> } | undefined,\n diff: undefined as versiondiff | undefined,\n library: undefined as steplibraryentry[] | undefined,\n palette: undefined as palettenode[] | undefined,\n};\nconst statusnode = document.querySelector<HTMLElement>(\"#status\");\nconst progressnode = document.querySelector<HTMLProgressElement>(\"#planprogress\");\nconst capabilitiestext = document.querySelector<HTMLElement>(\"#capabilitiestext\");\n\ntype previewresult = { ok: boolean; summary: string; resolvedtarget?: resolvedtarget; candidates?: string[] };\nconst previews = new Map<string, previewresult>();\n\n/** Live timeline view filters: level, source and step id; the filters stay user choices of the review panel. */\nconst timelinefilter = { level: \"\", source: \"\", stepid: \"\" };\n\n/** The last console diff result rendered by the diff view. */\nlet lastdiff: consolediff | undefined;\n\n/** Safely reads the reviewed options object of one step. */\nfunction options(step: toolstep): Record<string, unknown> {\n if (!step.options) return {};\n try {\n const parsed = JSON.parse(step.options);\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : {};\n } catch { return {}; }\n}\n\nfunction status(message: string, error = false): void { if (statusnode) { statusnode.textContent = message; statusnode.dataset.state = error ? \"error\" : \"ready\"; } }\nasync function request(message: unknown): Promise<unknown> { const response = await chrome.runtime.sendMessage(message) as { ok: boolean; value?: unknown; error?: string }; if (!response.ok) throw new Error(response.error); return response.value; }\nfunction button(label: string, action: () => Promise<void>, disabled = false): HTMLButtonElement { const element = document.createElement(\"button\"); element.type = \"button\"; element.textContent = label; element.disabled = disabled; element.addEventListener(\"click\", () => action().catch(error => status(error instanceof Error ? error.message : String(error), true))); return element; }\n\n/** Kinds addressable by a css target or a reviewed targetref; only these can be previewed. */\nconst previewkinds = [\"focus\", \"inspect\", \"click\", \"type\", \"scroll\", \"select\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"highlight\", \"setattribute\", \"removeattribute\", \"waitfor\", \"shiftclick\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\", \"verifyvisible\", \"verifyenabled\", \"pierceshadow\", \"clickpoint\", \"clicktext\", \"clickaria\", \"clickname\", \"resolvexpath\", \"deriveselector\", \"fingerprintsection\", \"submitform\", \"retryform\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\"];\n\n/** Topic rows that group the new interaction and observation kinds inside each risk class. */\nconst topictags: Array<{ topic: string; kinds: string[] }> = [\n { topic: \"pointer\", kinds: [\"movepointer\", \"clickpoint\", \"shiftclick\", \"clicktext\", \"clickaria\", \"clickname\", \"pierceshadow\"] },\n { topic: \"typing\", kinds: [\"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\"] },\n { topic: \"keys\", kinds: [\"keyhold\", \"keyrelease\"] },\n { topic: \"controls\", kinds: [\"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\"] },\n { topic: \"dialogs\", kinds: [\"dismissdialog\"] },\n { topic: \"frames\", kinds: [\"enterframe\"] },\n { topic: \"retry\", kinds: [\"retryaction\"] },\n { topic: \"reads\", kinds: [\"mapclicks\", \"verifyvisible\", \"verifyenabled\", \"resolvexpath\"] },\n { topic: \"observation\", kinds: [\"a11ytree\", \"readvisible\", \"readertree\", \"readoutline\", \"readselection\", \"readopengraph\", \"readlang\", \"detectlanguage\", \"listshadow\", \"listframes\", \"readscrollpos\"] },\n { topic: \"detection\", kinds: [\"detectlists\", \"detecttables\", \"detectinfinitescroll\", \"detectvirtual\", \"detectlazy\", \"detectsticky\", \"detectscrolllock\", \"countpages\", \"classifypage\", \"fingerprintsection\"] },\n { topic: \"watch\", kinds: [\"watchmutate\", \"watchbanner\", \"watchfocus\", \"waitquiet\", \"readjson\", \"diffsnapshots\", \"deriveselector\"] },\n { topic: \"navigation\", kinds: [\"openlink\", \"openprivate\", \"reloadcache\", \"stopnav\", \"waitload\", \"waiturl\", \"followlink\", \"spanav\", \"spawait\", \"rewritequery\", \"setfragment\", \"navlist\", \"navprofile\", \"detecthttp\", \"readredirects\", \"readfinalurl\", \"handleauth\", \"printpdf\", \"prefetch\", \"preconnect\", \"deeplink\", \"reopentab\", \"trailaudit\", \"pausenav\", \"navintent\", \"navrate\", \"openclipboard\", \"checksafe\", \"batchopen\"] },\n { topic: \"tabs\", kinds: [\"querytabs\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"watchtab\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"savelayout\", \"restorelayout\", \"findclones\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"listaudio\", \"reopenrun\", \"snapshotsession\"] },\n { topic: \"forms\", kinds: [\"fillform\", \"filllabel\", \"fillplaceholder\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"submitform\", \"readerrors\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"handoffcaptcha\", \"fillcard\", \"fillcode\", \"consentpassword\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\"] },\n];\n\nfunction steptopic(kind: string): string | undefined {\n return topictags.find(tag => tag.kinds.includes(kind))?.topic;\n}\n\n/** Renders plan completion as a live progress ratio. */\nfunction renderprogress(plan: agentplan, completed: string[]): void {\n if (!progressnode) return;\n const total = plan.steps.length || 1;\n progressnode.max = total;\n progressnode.value = completed.length;\n progressnode.textContent = `${completed.length} of ${plan.steps.length} reviewed steps executed`;\n}\n\n/** Renders the latest structured outcome of one step beside its review entry. */\nfunction renderoutcome(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n const outcome = [...outcomes].reverse().find(item => item.stepid === step.id && item.ok) ?? [...outcomes].reverse().find(item => item.stepid === step.id);\n if (!outcome) return null;\n const node = document.createElement(\"details\");\n node.className = \"outcome\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `${outcome.ok ? \"result\" : \"failure\"}: ${outcome.summary}`;\n node.append(summary);\n if (outcome.details && Object.keys(outcome.details).length > 0) {\n const payload = document.createElement(\"pre\");\n payload.textContent = JSON.stringify(outcome.details, null, 2).slice(0, 4000);\n node.append(payload);\n }\n return node;\n}\n\n/** Renders the hold id of a key hold or release step beside its summary. */\nfunction holddetail(step: toolstep): string {\n if (step.kind === \"keyhold\") {\n const holdid = options(step).holdid;\n return typeof holdid === \"string\" && holdid ? ` \u00B7 hold id ${holdid}` : \"\";\n }\n if (step.kind === \"keyrelease\") return step.value ? ` \u00B7 releases hold id ${step.value}` : \"\";\n return \"\";\n}\n\n/** Renders the retry attempts of one retry step on the step timeline. */\nfunction retrydetail(step: toolstep, retries: retryoutcome[]): HTMLElement | null {\n const latest = [...retries].reverse().find(item => item.stepid === step.id);\n if (!latest) return null;\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `retry timeline: ${latest.attempts} attempt${latest.attempts === 1 ? \"\" : \"s\"} \u00B7 ${latest.movement.toFixed(1)} px movement \u00B7 ${latest.ok ? \"succeeded\" : \"failed\"}`;\n return node;\n}\n\n/** Renders the network quiet progress of one waitquiet step from its outcome evidence. */\nfunction quietdetail(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n if (step.kind !== \"waitquiet\") return null;\n const latest = [...outcomes].reverse().find(outcome => outcome.stepid === step.id);\n if (!latest) return null;\n const samples = Array.isArray(latest.details?.samples) ? latest.details?.samples as Array<{ at: number; quietfor: number }> : [];\n const idle = typeof latest.details?.idle === \"number\" ? latest.details?.idle : 0;\n const last = samples[samples.length - 1];\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `network quiet: ${samples.length} sample${samples.length === 1 ? \"\" : \"s\"} \u00B7 quiet for ${Math.round(last?.quietfor ?? 0)} ms \u00B7 idle threshold ${idle} ms \u00B7 ${latest.ok ? \"quiet reached\" : \"still busy\"}`;\n return node;\n}\n\n/** Renders the per iteration row variables of one looprows step on the step timeline. */\nfunction loopdetail(step: toolstep, progress: planprogress | undefined): HTMLElement | null {\n if (step.kind !== \"looprows\") return null;\n const iterations = (progress?.outcomes ?? []).filter(outcome => outcome.stepid === step.id && outcome.details?.iteration !== undefined);\n if (iterations.length === 0) return null;\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n const latest = iterations[iterations.length - 1];\n if (!latest) return null;\n const variables = latest.details?.variables as Record<string, string> | undefined;\n const shown = variables ? Object.entries(variables).slice(0, 4).map(([key, value]) => `${key}=${value}`).join(\", \") : \"\";\n node.textContent = `loop timeline: ${iterations.length} iteration${iterations.length === 1 ? \"\" : \"s\"} \u00B7 ${String(latest.details?.variable ?? \"row\")} variables ${shown}`;\n return node;\n}\n\n/** Renders the navlist progress of one navlist step with the current url and the remaining count. */\nfunction navlistdetail(step: toolstep, progress: planprogress | undefined, outcomes: stepoutcome[]): HTMLElement | null {\n if (step.kind !== \"navlist\") return null;\n const entries = (progress?.outcomes ?? []).filter(outcome => outcome.stepid === step.id && outcome.details?.naventry !== undefined).map(outcome => outcome.details?.naventry as { index: number; url: string; ok: boolean });\n const total = entries.length > 0 ? Math.max(...entries.map(entry => entry.index)) + 1 : 0;\n const latestoutcome = [...outcomes].reverse().find(outcome => outcome.stepid === step.id);\n const remaining = typeof latestoutcome?.details?.remaining === \"number\" ? latestoutcome.details?.remaining : 0;\n const current = entries[entries.length - 1];\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = entries.length === 0\n ? \"navigation list: no entry completed yet\"\n : `navigation list: ${entries.filter(entry => entry.ok).length} of ${total} entries completed \u00B7 current url ${current?.url ?? \"\"} \u00B7 ${remaining} remaining`;\n return node;\n}\n\n/** Renders the redirect chain and final url of one navigation step from its outcome evidence. */\nfunction redirectdetail(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n if (![\"navigate\", \"followlink\", \"spanav\", \"navlist\", \"openlink\", \"reloadcache\"].includes(step.kind)) return null;\n const latest = [...outcomes].reverse().find(outcome => outcome.stepid === step.id && outcome.details?.hops !== undefined);\n if (!latest) return null;\n const hops = typeof latest.details?.hops === \"number\" ? latest.details?.hops : 0;\n const final = typeof latest.details?.finalurl === \"string\" ? latest.details?.finalurl : \"\";\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `redirects: ${Math.max(0, hops - 1)} hop${hops - 1 === 1 ? \"\" : \"s\"} \u00B7 final url ${final || \"unknown\"}`;\n return node;\n}\n\n/** Renders the resolved target details of one previewed interaction step before approval. */\nfunction renderpreview(step: toolstep): HTMLElement | null {\n const preview = previews.get(step.id);\n if (!preview) return null;\n const node = document.createElement(\"details\");\n node.className = \"outcome\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `preview: ${preview.summary}`;\n node.append(summary);\n if (preview.resolvedtarget) {\n const payload = document.createElement(\"pre\");\n payload.textContent = JSON.stringify(preview.resolvedtarget, null, 2);\n node.append(payload);\n }\n if (preview.candidates && preview.candidates.length > 1) {\n const chooser = document.createElement(\"p\");\n chooser.textContent = \"Ambiguous resolution; choose one candidate as the target hint:\";\n node.append(chooser);\n for (const candidate of preview.candidates) {\n node.append(\" \", button(`Choose \"${candidate}\"`, async () => { pickhint(`target hint: ${candidate}`); }));\n }\n }\n return node;\n}\n\nfunction stepitem(plan: agentplan, step: toolstep, completed: string[], outcomes: stepoutcome[], retries: retryoutcome[], progress?: planprogress): HTMLLIElement {\n const item = document.createElement(\"li\");\n const done = completed.includes(step.id);\n item.textContent = `${done ? \"\u2713\" : \"\"} ${step.summary}${holddetail(step)}`;\n const outcome = renderoutcome(step, outcomes);\n if (outcome) item.append(outcome);\n const timeline = step.kind === \"retryaction\" ? retrydetail(step, retries) : quietdetail(step, outcomes);\n if (timeline) item.append(timeline);\n const navlist = navlistdetail(step, progress, outcomes);\n if (navlist) item.append(navlist);\n const loopvars = loopdetail(step, progress);\n if (loopvars) item.append(loopvars);\n const redirects = redirectdetail(step, outcomes);\n if (redirects) item.append(redirects);\n const preview = renderpreview(step);\n if (preview) item.append(preview);\n const hastarget = Boolean(step.target) || options(step).targetref !== undefined;\n if (!done && hastarget && previewkinds.includes(step.kind) && [\"pending\", \"approved\"].includes(plan.state)) item.append(\" \", button(\"Preview current target\", async () => { const result = await request({ kind: \"preview\", stepid: step.id }) as previewresult; previews.set(step.id, result); status(result.summary); await refresh(); }));\n if (!done && plan.state === \"approved\") item.append(\" \", button(\"Run this reviewed step\", async () => { const result = await request({ kind: \"execute\", stepid: step.id }) as { summary: string }; status(result.summary); await refresh(); }));\n return item;\n}\n\nfunction steplist(plan: agentplan, steps: toolstep[], completed: string[], outcomes: stepoutcome[], retries: retryoutcome[], risk: toolstep[\"risk\"], progress?: planprogress): HTMLElement | null {\n const group = steps.filter(step => step.risk === risk);\n if (group.length === 0) return null;\n const section = document.createElement(\"section\");\n const heading = document.createElement(\"h3\");\n heading.textContent = `${risk} steps`;\n section.append(heading);\n const general = group.filter(step => steptopic(step.kind) === undefined);\n if (general.length > 0) {\n const list = document.createElement(\"ol\");\n for (const step of general) list.append(stepitem(plan, step, completed, outcomes, retries, progress));\n section.append(list);\n }\n for (const tag of topictags) {\n const tagged = group.filter(step => steptopic(step.kind) === tag.topic);\n if (tagged.length === 0) continue;\n const row = document.createElement(\"h4\");\n row.textContent = `${tag.topic} steps`;\n section.append(row);\n const list = document.createElement(\"ol\");\n for (const step of tagged) list.append(stepitem(plan, step, completed, outcomes, retries, progress));\n section.append(list);\n }\n return section;\n}\n\nfunction renderplan(plan?: agentplan, progress?: planprogress, outcomes: stepoutcome[] = [], retries: retryoutcome[] = []): void {\n if (!planroot) return;\n planroot.replaceChildren();\n if (!plan) { planroot.textContent = \"Start a session, then request a local or endpoint plan. No task runs before review.\"; if (progressnode) progressnode.value = 0; return; }\n const title = document.createElement(\"h2\"); title.textContent = `${plan.state}: ${plan.objective}`; planroot.append(title);\n const completed = progress?.planid === plan.id ? progress.completedsteps : [];\n renderprogress(plan, completed);\n const sensitive = steplist(plan, plan.steps, completed, outcomes, retries, \"sensitive\", progress);\n const interaction = steplist(plan, plan.steps, completed, outcomes, retries, \"interaction\", progress);\n const read = steplist(plan, plan.steps, completed, outcomes, retries, \"read\", progress);\n for (const group of [sensitive, interaction, read]) if (group) planroot.append(group);\n if (plan.state === \"pending\") { planroot.append(button(\"Approve reviewed plan\", async () => { await request({ kind: \"approve\" }); await refresh(); }), button(\"Reject plan\", async () => { await request({ kind: \"reject\" }); await refresh(); })); }\n if (plan.state === \"completed\" && plan.completedat) { const note = document.createElement(\"p\"); note.textContent = \"Every reviewed step has executed and the plan is closed.\"; planroot.append(note); }\n}\n\n/** Records one clickable map entry or candidate as the target hint for the next plan. */\nfunction pickhint(hint: string): void {\n if (objective) objective.value = objective.value ? `${objective.value}\\n${hint}` : hint;\n status(`${hint} recorded as the target hint for the next plan.`);\n}\n\n/** Renders the clickable map as a numbered list beside the plan and lets the user pick entries. */\nfunction rendermap(map?: clickablemap): void {\n if (!maproot) return;\n maproot.replaceChildren();\n if (!map || map.entries.length === 0) { maproot.textContent = \"Run a mapclicks step to number every clickable element on the page.\"; return; }\n for (const entry of map.entries) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `${entry.number}. ${entry.label || entry.selector} (${entry.role})`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${entry.selector} (map entry ${entry.number}, ${entry.label || entry.role})`));\n item.append(pick);\n maproot.append(item);\n }\n}\n\n/** Renders the latest accessibility tree beside the dom snapshot as indented role lines. */\nfunction rendera11y(capture?: a11ycapture): void {\n if (!a11yroot) return;\n a11yroot.replaceChildren();\n if (!capture) { a11yroot.textContent = \"Run an a11ytree step to capture the accessibility tree beside the dom snapshot.\"; return; }\n const lines: string[] = [];\n const walk = (node: a11ynode, depth: number): void => {\n if (lines.length >= 80) return;\n const states = node.states.length > 0 ? ` [${node.states.join(\", \")}]` : \"\";\n const value = node.value !== undefined ? ` = ${node.value}` : \"\";\n lines.push(`${\"\u00B7 \".repeat(depth)}${node.role}: ${node.name || \"(unnamed)\"}${states}${value}`);\n for (const child of node.children) walk(child, depth + 1);\n };\n walk(capture.tree, 0);\n const payload = document.createElement(\"pre\");\n payload.textContent = lines.join(\"\\n\");\n a11yroot.append(payload);\n}\n\n/** Renders the latest reader view text with heading blocks highlighted. */\nfunction renderreader(capture?: readercapture): void {\n if (!readerroot) return;\n readerroot.replaceChildren();\n if (!capture) { readerroot.textContent = \"Run a readertree step to extract the reader view.\"; return; }\n const title = document.createElement(\"p\");\n title.textContent = `${capture.article.title || \"Untitled\"}${capture.article.byline ? ` \u00B7 ${capture.article.byline}` : \"\"} \u00B7 ${capture.article.words} words \u00B7 ${capture.article.blocks.length} blocks`;\n readerroot.append(title);\n for (const block of capture.article.blocks.slice(0, 40)) {\n const line = document.createElement(\"p\");\n line.className = /^h\\d$/.test(block.kind) ? \"readerblock heading\" : \"readerblock\";\n line.textContent = `${block.kind}: ${block.text.slice(0, 200)}`;\n readerroot.append(line);\n }\n}\n\n/** Shows detected lists, tables and pagination shapes as plan suggestions the user can pick. */\nfunction renderdetections(plan: agentplan | undefined, outcomes: stepoutcome[]): void {\n if (!detectionsroot) return;\n detectionsroot.replaceChildren();\n if (!plan) { detectionsroot.textContent = \"Detection steps list their detected lists, tables and pagination shapes here as suggestions.\"; return; }\n const kindof = (stepid: string): string | undefined => plan.steps.find(step => step.id === stepid)?.kind;\n const latest = (kind: string): stepoutcome | undefined => [...outcomes].reverse().find(outcome => outcome.ok && kindof(outcome.stepid) === kind);\n let shown = 0;\n const listoutcome = latest(\"detectlists\");\n const lists = Array.isArray(listoutcome?.details?.lists) ? listoutcome?.details?.lists as listpattern[] : [];\n for (const pattern of lists.slice(0, 6)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `list of ${pattern.repeat} items \u00B7 ${pattern.itemselector}`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${pattern.itemselector} (repeated list item of ${pattern.container})`));\n item.append(pick);\n detectionsroot.append(item);\n shown += 1;\n }\n const tableoutcome = latest(\"detecttables\");\n const tables = Array.isArray(tableoutcome?.details?.tables) ? tableoutcome?.details?.tables as tableshape[] : [];\n for (const table of tables.slice(0, 6)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `table of ${table.rows} rows \u00B7 ${table.columns.length} columns \u00B7 ${table.selector}`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${table.selector} (detected data table)`));\n item.append(pick);\n detectionsroot.append(item);\n shown += 1;\n }\n const paginationoutcome = latest(\"countpages\");\n if (paginationoutcome) {\n const item = document.createElement(\"li\");\n const current = typeof paginationoutcome.details?.current === \"number\" ? paginationoutcome.details?.current : 0;\n const total = typeof paginationoutcome.details?.total === \"number\" ? paginationoutcome.details?.total : 0;\n const text = document.createElement(\"span\");\n text.textContent = `pagination: current page ${current} \u00B7 estimated total ${total}`;\n item.append(text);\n detectionsroot.append(item);\n shown += 1;\n }\n if (shown === 0) detectionsroot.textContent = \"Detected lists, tables and pagination shapes appear here as plan suggestions.\";\n}\n\n/** Shows the live mutation and focus stream observed during watched steps. */\nfunction renderstream(mutationevents: mutationevent[], focusevents: focusevent[]): void {\n if (!streamroot) return;\n streamroot.replaceChildren();\n if (mutationevents.length === 0 && focusevents.length === 0) { streamroot.textContent = \"Watched steps stream their mutation and focus events here.\"; return; }\n for (const event of mutationevents.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 mutation ${event.event} \u00B7 ${event.targetpath}`;\n streamroot.append(item);\n }\n for (const event of focusevents.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 focus ${event.kind} \u00B7 ${event.targetpath}`;\n streamroot.append(item);\n }\n}\n\n/** Renders the latest snapshot diff with added, removed and changed rows. */\nfunction renderdiffs(diffs: snapshotdiff[]): void {\n if (!diffsroot) return;\n diffsroot.replaceChildren();\n const latest = diffs[0];\n if (!latest) { diffsroot.textContent = \"Diff two captured observation versions with a diffsnapshots step.\"; return; }\n const heading = document.createElement(\"p\");\n heading.textContent = `version ${latest.baseversion} \u2192 ${latest.targetversion}: ${latest.added.length} added \u00B7 ${latest.removed.length} removed \u00B7 ${latest.changed.length} changed`;\n diffsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const entry of [...latest.added, ...latest.removed, ...latest.changed].slice(0, 12)) {\n const item = document.createElement(\"li\");\n item.className = `diffrow ${entry.kind}`;\n item.textContent = `${entry.kind} \u00B7 ${entry.selector} \u00B7 ${entry.summary}`;\n list.append(item);\n }\n diffsroot.append(list);\n}\n\n/** Flags consent banners with a review card before any interaction. */\nfunction renderbanners(banners: bannerreport[]): void {\n if (!bannersroot) return;\n bannersroot.replaceChildren();\n if (banners.length === 0) { bannersroot.textContent = \"No consent banner has been observed yet.\"; return; }\n for (const banner of banners.slice(0, 3)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `${banner.kind} banner detected \u2014 review it before any interaction.`;\n const text = document.createElement(\"p\");\n text.textContent = banner.text.slice(0, 160) || \"(no banner text)\";\n const controls = document.createElement(\"p\");\n controls.textContent = `controls: ${banner.controls.length > 0 ? banner.controls.join(\", \") : \"none\"}`;\n card.append(title, text, controls);\n bannersroot.append(card);\n }\n}\n\n/** Shows derived selector candidates with their stability scores for reuse. */\nfunction renderselectors(selectors: derivedselector[]): void {\n if (!selectorsroot) return;\n selectorsroot.replaceChildren();\n if (selectors.length === 0) { selectorsroot.textContent = \"Run a deriveselector step to rank stable selectors.\"; return; }\n for (const record of selectors.slice(0, 8)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `${record.selector} (${record.strategy} \u00B7 stability ${record.score})`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${record.selector} (derived ${record.strategy} selector)`));\n item.append(pick);\n selectorsroot.append(item);\n }\n}\n\n/** Renders the navigation trail of the session as a timeline of visited urls. */\nfunction rendertrail(trail: trailentry[]): void {\n if (!trailroot) return;\n trailroot.replaceChildren();\n if (trail.length === 0) { trailroot.textContent = \"No page has been visited inside a reviewed navigation step yet.\"; return; }\n for (const entry of [...trail].reverse().slice(0, 12)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(entry.at).toLocaleTimeString()} \u00B7 ${entry.url}${entry.title ? ` \u00B7 ${entry.title}` : \"\"}${entry.stepid ? ` \u00B7 step ${entry.stepid}` : \"\"}`;\n trailroot.append(item);\n }\n}\n\n/** Renders the navigation state: paused navigation, rate limit windows per domain, wait profiles, redirect chains, curated lists, safety verdicts, artifacts and the basic auth prompt behind the consent gate. */\nfunction rendernavigation(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; navcontrol?: navcontrol; ratestates?: ratelimitstate[]; waitprofiles?: waitprofilerecord[]; navrecords?: navrecord[]; curated?: curatedlist[]; safeties?: safetyverdict[]; auths?: Array<{ origin: string; username: string; reviewedat: number }>; navqueues?: navqueues; artifacts?: artifactrecord[] }): void {\n if (!navigationroot) return;\n navigationroot.replaceChildren();\n const paused = document.createElement(\"p\");\n if (context.navcontrol?.pausedat) {\n paused.className = \"bannercard\";\n paused.textContent = `Navigation is paused while ${context.navcontrol.reason ?? \"a consent prompt is open\"}; reviewed navigation steps are blocked until it resumes.`;\n } else {\n paused.textContent = \"Navigation is live; no consent prompt holds it.\";\n }\n navigationroot.append(paused);\n const rates = context.ratestates ?? [];\n if (rates.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"rate limit windows per domain:\";\n navigationroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const state of rates.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${state.domain}: ${state.count} of ${state.limit.ceiling} navigations inside the reviewed window of ${state.limit.window} ms`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const records = context.navrecords ?? [];\n const record = records[0];\n if (record) {\n const chain = document.createElement(\"p\");\n chain.textContent = `latest navigation: ${Math.max(0, record.chain.hops.length - 1)} redirect${record.chain.hops.length - 1 === 1 ? \"\" : \"s\"} \u00B7 final url ${record.finalurl}`;\n navigationroot.append(chain);\n const hops = document.createElement(\"ul\");\n for (const hop of record.chain.hops.slice(0, 6)) {\n const item = document.createElement(\"li\");\n let path = hop.url;\n try { path = new URL(hop.url).pathname; } catch { path = hop.url; }\n item.textContent = `hop ${path} \u00B7 status ${hop.status} \u00B7 ${new Date(hop.at).toLocaleTimeString()}`;\n hops.append(item);\n }\n navigationroot.append(hops);\n }\n const curatedlists = context.curated ?? [];\n if (curatedlists.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"curated link lists with per url safety states:\";\n navigationroot.append(heading);\n for (const list of curatedlists.slice(0, 3)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `${list.links.length} curated url${list.links.length === 1 ? \"\" : \"s\"}${list.reviewedat ? \" \u00B7 opened after review\" : \" \u00B7 waiting for review\"}`;\n card.append(title);\n for (const link of list.links.slice(0, 8)) {\n const line = document.createElement(\"p\");\n line.textContent = `${link.verdict === \"safe\" ? \"\u2713\" : \"\u2717\"} ${link.url}${link.reasons.length > 0 ? ` \u00B7 ${link.reasons.join(\"; \")}` : \"\"}`;\n card.append(line);\n }\n navigationroot.append(card);\n }\n }\n const safeties = context.safeties ?? [];\n const runner = document.createElement(\"p\");\n const checkinput = document.createElement(\"input\");\n checkinput.type = \"url\";\n checkinput.placeholder = \"https://external.example/link\";\n checkinput.setAttribute(\"aria-label\", \"url to verify with checksafe\");\n const checkbutton = button(\"Run checksafe\", async () => {\n const verdict = await request({ kind: \"checksafe\", url: checkinput.value }) as safetyverdict;\n status(verdict.safe ? `${verdict.url} passed every safety check.` : `${verdict.url} is unsafe: ${verdict.reasons.join(\"; \")}.`);\n await refresh();\n });\n runner.append(checkinput, \" \", checkbutton);\n navigationroot.append(runner);\n if (safeties.length > 0) {\n const list = document.createElement(\"ul\");\n for (const verdict of safeties.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${verdict.safe ? \"safe\" : \"unsafe\"} \u00B7 ${verdict.url}${verdict.reasons.length > 0 ? ` \u00B7 ${verdict.reasons.join(\"; \")}` : \"\"}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const authcard = document.createElement(\"div\");\n authcard.className = \"bannercard\";\n const authtitle = document.createElement(\"p\");\n authtitle.textContent = active ? \"basic auth credentials (stored only after your explicit review):\" : \"basic auth credentials need an active session before they can be reviewed.\";\n authcard.append(authtitle);\n if (active) {\n const origininput = document.createElement(\"input\");\n origininput.type = \"url\";\n origininput.placeholder = context.session?.origin ?? \"https://example.com\";\n origininput.setAttribute(\"aria-label\", \"auth origin\");\n const userinput = document.createElement(\"input\");\n userinput.type = \"text\";\n userinput.placeholder = \"username\";\n userinput.setAttribute(\"aria-label\", \"auth username\");\n const passinput = document.createElement(\"input\");\n passinput.type = \"password\";\n passinput.placeholder = \"password\";\n passinput.setAttribute(\"aria-label\", \"auth password\");\n const storebutton = button(\"Store reviewed credentials\", async () => {\n const stored = await request({ kind: \"storeauth\", origin: origininput.value, username: userinput.value, password: passinput.value }) as { origin: string };\n status(`Reviewed basic auth credentials stored for ${stored.origin}.`);\n await refresh();\n });\n authcard.append(origininput, \" \", userinput, \" \", passinput, \" \", storebutton);\n }\n navigationroot.append(authcard);\n const auths = context.auths ?? [];\n if (auths.length > 0) {\n const list = document.createElement(\"ul\");\n for (const record of auths.slice(0, 4)) {\n const item = document.createElement(\"li\");\n item.textContent = `basic auth for ${record.origin} as ${record.username}, reviewed ${new Date(record.reviewedat).toLocaleString()}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const artifacts = context.artifacts ?? [];\n if (artifacts.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"task artifacts:\";\n navigationroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const artifact of artifacts.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${artifact.kind}: ${artifact.name} \u00B7 step ${artifact.stepid}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n}\n\n/** Renders the tabs and windows command surface: quick switcher, groups, badges, audio state, layouts, snapshots, clone warnings, the task tab budget gauge and the pinned control tab feed. */\nfunction rendertabswindows(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; progress?: planprogress; tabs?: tabshape[]; windows?: windowshape[]; tabgroups?: tabgrouprecord[]; badges?: tabbadge[]; tabmetas?: tabmeta[]; clones?: Array<{ url: string; tabids: number[] }>; layouts?: tablayout[]; snapshots?: sessionsnapshot[]; closedtabs?: closedtab[]; tasktabgauge?: { used: number; ceiling?: number; over: boolean }; controltab?: controltabstate }): void {\n if (!tabswindowsroot) return;\n tabswindowsroot.replaceChildren();\n const tabs = context.tabs ?? [];\n const badges = context.badges ?? [];\n const metas = context.tabmetas ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const gauge = context.tasktabgauge ?? { used: 0, ceiling: undefined, over: false };\n const budget = document.createElement(\"p\");\n budget.className = gauge.over ? \"bannercard\" : \"\";\n budget.textContent = `task tab budget: ${gauge.used} tab${gauge.used === 1 ? \"\" : \"s\"} with active tasks${gauge.ceiling !== undefined ? ` of the user configured ceiling ${gauge.ceiling}` : \" with no user ceiling configured\"}${gauge.over ? \" \u2014 over the reviewed budget\" : \"\"}`;\n tabswindowsroot.append(budget);\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.type = \"number\";\n ceilinginput.min = \"0\";\n ceilinginput.placeholder = gauge.ceiling !== undefined ? String(gauge.ceiling) : \"no ceiling\";\n ceilinginput.setAttribute(\"aria-label\", \"concurrent task tab ceiling\");\n const ceilingbutton = button(\"Save task tab ceiling\", async () => {\n await request({ kind: \"settasktabceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) });\n status(`Task tab ceiling saved as ${ceilinginput.value === \"\" ? \"no ceiling\" : ceilinginput.value}; the value stays a user choice.`);\n await refresh();\n });\n tabswindowsroot.append(ceilinginput, \" \", ceilingbutton);\n const switcherheading = document.createElement(\"p\");\n switcherheading.textContent = \"quick switcher (ordered by recency, filter by title or url):\";\n tabswindowsroot.append(switcherheading);\n const filterinput = document.createElement(\"input\");\n filterinput.type = \"search\";\n filterinput.placeholder = \"filter open tabs\";\n filterinput.setAttribute(\"aria-label\", \"quick switcher filter\");\n const switchlist = document.createElement(\"ul\");\n const renderswitchlist = (): void => {\n switchlist.replaceChildren();\n const ordered = switcherlist(tabs, [], filterinput.value).slice(0, 10);\n for (const tab of ordered) {\n const item = document.createElement(\"li\");\n const jump = document.createElement(\"button\");\n jump.type = \"button\";\n const badge = badges.find(entry => entry.tabid === tab.tabid);\n const meta = metas.find(entry => entry.tabid === tab.tabid);\n jump.textContent = `${tab.title || tab.url}${tab.pinned ? \" \uD83D\uDCCC\" : \"\"}${tab.audible || tab.muted ? ` ${tab.muted ? \"\uD83D\uDD07\" : \"\uD83D\uDD0A\"}` : \"\"}${badge ? ` [${badge.label}]` : \"\"}${meta && meta.labels.length > 0 ? ` (${meta.labels.join(\", \")})` : \"\"}`;\n jump.addEventListener(\"click\", () => request({ kind: \"jumptotab\", tabid: tab.tabid }).then(() => status(`Jumped to tab ${tab.tabid}.`)).catch(error => status(error instanceof Error ? error.message : String(error), true)));\n item.append(jump);\n switchlist.append(item);\n }\n if (ordered.length === 0) { const empty = document.createElement(\"li\"); empty.textContent = \"no open tab matches the filter\"; switchlist.append(empty); }\n };\n filterinput.addEventListener(\"input\", renderswitchlist);\n tabswindowsroot.append(filterinput, switchlist);\n renderswitchlist();\n const searchinput = document.createElement(\"input\");\n searchinput.type = \"search\";\n searchinput.placeholder = \"search across open tabs by title and url\";\n searchinput.setAttribute(\"aria-label\", \"searchtabs text\");\n const searchresults = document.createElement(\"ul\");\n const searchbutton = button(\"Run searchtabs\", async () => {\n const result = await request({ kind: \"tabsearch\", text: searchinput.value }) as { matches: tabshape[] };\n searchresults.replaceChildren();\n for (const tab of result.matches.slice(0, 10)) {\n const item = document.createElement(\"li\");\n const jump = document.createElement(\"button\");\n jump.type = \"button\";\n jump.textContent = `${tab.title || tab.url} \u00B7 ${tab.url}`;\n jump.addEventListener(\"click\", () => request({ kind: \"jumptotab\", tabid: tab.tabid }).then(() => status(`Jumped to tab ${tab.tabid}.`)).catch(error => status(error instanceof Error ? error.message : String(error), true)));\n item.append(jump);\n searchresults.append(item);\n }\n status(`searchtabs matched ${result.matches.length} open tab${result.matches.length === 1 ? \"\" : \"s\"}.`);\n });\n tabswindowsroot.append(searchinput, \" \", searchbutton, searchresults);\n const clones = context.clones ?? [];\n for (const clone of clones.slice(0, 3)) {\n const warning = document.createElement(\"p\");\n warning.className = \"bannercard\";\n warning.textContent = `duplicate tab warning: ${clone.tabids.length} open tabs share the url ${clone.url} (tabs ${clone.tabids.join(\", \")})`;\n tabswindowsroot.append(warning);\n }\n const groups = context.tabgroups ?? [];\n if (groups.length > 0) {\n const groupsheading = document.createElement(\"p\");\n groupsheading.textContent = \"tab groups with colors and collapse states:\";\n tabswindowsroot.append(groupsheading);\n const grouplist = document.createElement(\"ul\");\n for (const group of groups.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${group.name} \u00B7 ${group.color} \u00B7 ${group.collapsed ? \"collapsed\" : \"expanded\"} \u00B7 ${group.tabids.length} member tab${group.tabids.length === 1 ? \"\" : \"s\"}`;\n grouplist.append(item);\n }\n tabswindowsroot.append(grouplist);\n }\n const windows = context.windows ?? [];\n if (windows.length > 0) {\n const windowsheading = document.createElement(\"p\");\n windowsheading.textContent = \"windows with layouts and bounds:\";\n tabswindowsroot.append(windowsheading);\n const windowlist = document.createElement(\"ul\");\n for (const item of windows.slice(0, 6)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `window ${item.windowid} \u00B7 ${item.state} \u00B7 bounds ${item.left}\u00D7${item.top} ${item.width}\u00D7${item.height}${item.incognito ? \" \u00B7 incognito, grants not inherited\" : \"\"}${item.focused ? \" \u00B7 focused\" : \"\"}`;\n const closebutton = button(\"Close window\", async () => {\n const tasktabids = (context.progress?.tasktabs ?? []);\n const tabsoftask = (context.tabs ?? []).filter(tab => tab.windowid === item.windowid && tasktabids.includes(tab.tabid));\n const reviewed = tabsoftask.length > 1 ? window.confirm(`This window holds ${tabsoftask.length} task tabs. Close it anyway under explicit review?`) : true;\n await request({ kind: \"closewindow\", windowid: item.windowid, reviewed });\n status(`Closed window ${item.windowid}.`);\n await refresh();\n });\n entry.append(\" \", closebutton);\n windowlist.append(entry);\n }\n tabswindowsroot.append(windowlist);\n }\n const layoutcontrols = document.createElement(\"p\");\n const layoutname = document.createElement(\"input\");\n layoutname.type = \"text\";\n layoutname.placeholder = \"layout name\";\n layoutname.setAttribute(\"aria-label\", \"layout name\");\n const savebutton = button(\"Save layout\", async () => {\n if (!active) { status(\"Layout save stays inside an active session.\", true); return; }\n await request({ kind: \"savelayout\", name: layoutname.value });\n status(`Saved the tab layout ${layoutname.value}.`);\n await refresh();\n });\n const restorebutton = button(\"Restore layout\", async () => {\n if (!active) { status(\"Layout restore stays inside an active session.\", true); return; }\n const result = await request({ kind: \"restorelayout\", name: layoutname.value }) as { reopened: number };\n status(`Restored the tab layout ${layoutname.value}: ${result.reopened} tab${result.reopened === 1 ? \"\" : \"s\"} reopened.`);\n await refresh();\n });\n layoutcontrols.append(layoutname, \" \", savebutton, \" \", restorebutton);\n tabswindowsroot.append(layoutcontrols);\n const layouts = context.layouts ?? [];\n if (layouts.length > 0) {\n const layoutlist = document.createElement(\"ul\");\n for (const layout of layouts.slice(0, 4)) {\n const item = document.createElement(\"li\");\n item.textContent = `${layout.name} \u00B7 ${layout.tabs.length} tab${layout.tabs.length === 1 ? \"\" : \"s\"} \u00B7 ${layout.groups.length} group${layout.groups.length === 1 ? \"\" : \"s\"} \u00B7 ${layout.windows.length} window bound${layout.windows.length === 1 ? \"\" : \"s\"} \u00B7 saved ${new Date(layout.savedat).toLocaleString()}`;\n layoutlist.append(item);\n }\n tabswindowsroot.append(layoutlist);\n }\n const snapshots = context.snapshots ?? [];\n if (snapshots.length > 0) {\n const snapcard = document.createElement(\"div\");\n snapcard.className = \"bannercard\";\n const snaptitle = document.createElement(\"p\");\n snaptitle.textContent = `session snapshot card: ${snapshots.length} snapshot${snapshots.length === 1 ? \"\" : \"s\"} stored`;\n snapcard.append(snaptitle);\n for (const snapshot of snapshots.slice(0, 3)) {\n const row = document.createElement(\"p\");\n row.textContent = `${snapshot.layout.tabs.length} tabs \u00B7 captured ${new Date(snapshot.capturedat).toLocaleString()}`;\n const restore = button(\"Restore snapshot\", async () => {\n const result = await request({ kind: \"restoresnapshot\", id: snapshot.id }) as { reopened: number };\n status(`Restored the session snapshot: ${result.reopened} tab${result.reopened === 1 ? \"\" : \"s\"} reopened.`);\n await refresh();\n });\n row.append(\" \", restore);\n snapcard.append(row);\n }\n tabswindowsroot.append(snapcard);\n }\n const controlcard = document.createElement(\"div\");\n controlcard.className = \"bannercard\";\n const controlstate = context.controltab;\n const completed = context.progress?.completedsteps.length ?? 0;\n const total = context.plan?.steps.length ?? 0;\n controlcard.textContent = `pinned control tab feed: ${controlstate?.enabled ? `open as tab ${controlstate.tabid} with the live task status ${completed} of ${total} reviewed steps executed` : \"disabled\"}${context.plan ? ` \u00B7 ${context.plan.state}` : \" \u00B7 no plan\"}`;\n const controlbutton = button(controlstate?.enabled ? \"Close pinned control tab\" : \"Open pinned control tab\", async () => {\n await request({ kind: \"controltab\", enabled: !controlstate?.enabled });\n status(controlstate?.enabled ? \"The pinned control tab was closed.\" : \"The pinned control tab was opened with the live task feed.\");\n await refresh();\n });\n controlcard.append(\" \", controlbutton);\n tabswindowsroot.append(controlcard);\n}\n\n/** Renders the forms and data surface: the form map, generated values, saved profiles, asksubmit cards with the values diff, wizard progress, inline error reports, honeypot skips, template badges, the consent gated code entry and masked card fills. */\nfunction renderforms(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; plan?: agentplan; outcomes?: stepoutcome[]; profiles?: formprofile[]; tickets?: submitticket[]; wizards?: { wizards: wizardstate[]; picks: typeaheadpick[] }; errorreports?: errorreport[]; captchas?: captchahandoff[]; detections?: detectionrecord[]; codeentry?: boolean }): void {\n if (!formsroot) return;\n formsroot.replaceChildren();\n const outcomes = context.outcomes ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const opencaptcha = (context.captchas ?? []).find(handoff => !handoff.resolved);\n if (opencaptcha) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n card.textContent = `Captcha handoff open on ${opencaptcha.origin}: control is yours and the plan waits until you resolve it.`;\n card.append(\" \", button(\"Captcha resolved\", async () => { await request({ kind: \"resolvecaptcha\" }); status(\"Captcha handoff resolved; the plan continues.\"); await refresh(); }));\n formsroot.append(card);\n }\n const detections = context.detections ?? [];\n if (detections.length > 0) {\n const badges = document.createElement(\"p\");\n badges.textContent = `template badges: ${detections.slice(0, 6).map(record => `${record.kind} on ${record.origin}${record.markers.length > 0 ? ` (${record.markers.join(\", \")})` : \"\"}`).join(\" \u00B7 \")}`;\n formsroot.append(badges);\n }\n const mapoutcome = [...outcomes].reverse().find(outcome => outcome.details?.report !== undefined && outcome.details?.count !== undefined);\n const skippedselectors = new Set(outcomes.flatMap(outcome => Array.isArray(outcome.details?.skipped) ? outcome.details?.skipped as Array<{ selector: string }> : []).map(trap => trap.selector));\n if (mapoutcome) {\n const report = mapoutcome.details?.report as { form: string; fields: Array<{ selector: string; label: string; kind: string; matched: boolean }> };\n const heading = document.createElement(\"p\");\n heading.textContent = `form map${report.form ? ` of ${report.form}` : \"\"}: ${report.fields.length} detected field${report.fields.length === 1 ? \"\" : \"s\"} with their kinds${skippedselectors.size > 0 ? `; ${skippedselectors.size} honeypot field${skippedselectors.size === 1 ? \"\" : \"s\"} highlighted as skipped` : \"\"}`;\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const field of report.fields.slice(0, 10)) {\n const item = document.createElement(\"li\");\n const skipped = skippedselectors.has(field.selector);\n item.textContent = `${field.label || field.selector} \u00B7 ${field.kind}${field.matched ? \"\" : \" \u00B7 unmatched\"}${skipped ? \" \u00B7 honeypot, skipped\" : \"\"}`;\n list.append(item);\n }\n formsroot.append(list);\n }\n const valuesoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.values) && outcome.details?.locale !== undefined);\n if (valuesoutcome) {\n const values = valuesoutcome.details?.values as Array<{ label: string; kind: string; value: string }>;\n const locale = typeof valuesoutcome.details?.locale === \"string\" ? valuesoutcome.details.locale : \"en\";\n const seed = typeof valuesoutcome.details?.seed === \"number\" ? valuesoutcome.details.seed : 1;\n const heading = document.createElement(\"p\");\n heading.textContent = `generated values (locale ${locale}, seed ${seed}) with a regenerate button per field:`;\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const entry of values.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.label} \u00B7 ${entry.kind} \u00B7 ${entry.value}`;\n item.append(\" \", button(\"Regenerate\", async () => {\n const regenerated = await request({ kind: \"regeneratevalue\", field: entry.kind, locale, seed: seed + 1 }) as { value: string };\n status(`Regenerated ${entry.label}: ${regenerated.value}.`);\n }));\n list.append(item);\n }\n formsroot.append(list);\n }\n const cardoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.segments));\n if (cardoutcome) {\n const segments = cardoutcome.details?.segments as Array<{ label: string; masked: string }>;\n const cardline = document.createElement(\"p\");\n cardline.textContent = `card fill segments (masked): ${segments.map(segment => `${segment.label} ${cardmask(segment.masked)}`).join(\" \u00B7 \")}`;\n formsroot.append(cardline);\n }\n const profiles = context.profiles ?? [];\n if (profiles.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"saved form profiles with origin grants:\";\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const profile of profiles.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${profile.name} \u00B7 ${profile.fields.length} field${profile.fields.length === 1 ? \"\" : \"s\"} \u00B7 grants ${profile.grants.join(\", \")} \u00B7 saved ${new Date(profile.savedat).toLocaleString()}`;\n item.append(\" \", button(\"Apply\", async () => {\n const applied = await request({ kind: \"applyprofile\", name: profile.name }) as { profile: { fields: unknown[] } };\n pickhint(`profile hint: ${profile.name} with ${applied.profile.fields.length} reviewed field entries`);\n }), \" \", button(\"Remove\", async () => {\n await request({ kind: \"removeprofile\", name: profile.name });\n status(`Form profile ${profile.name} removed.`);\n await refresh();\n }));\n list.append(item);\n }\n formsroot.append(list);\n }\n const pending = (context.tickets ?? []).filter(ticket => ticket.approved === undefined);\n for (const ticket of pending) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `asksubmit for form ${ticket.form || \"the reviewed form\"} \u00B7 values hash ${ticket.valueshash}`;\n card.append(title);\n const askoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.values) && outcome.details?.ticket !== undefined);\n const values = askoutcome?.details?.values as Array<{ label: string; value: string }> | undefined;\n if (values) {\n const diff = document.createElement(\"ul\");\n for (const entry of values.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.label}: ${entry.value}`;\n diff.append(item);\n }\n card.append(diff);\n } else {\n const note = document.createElement(\"p\");\n note.textContent = \"The full values diff appears here once the asksubmit step reads the form.\";\n card.append(note);\n }\n card.append(button(\"Approve submission\", async () => { await request({ kind: \"approvesubmit\", id: ticket.id, approved: true }); status(\"Submission approved; the reviewed submitform step may run.\"); await refresh(); }), \" \", button(\"Decline\", async () => { await request({ kind: \"approvesubmit\", id: ticket.id, approved: false }); status(\"Submission declined.\"); await refresh(); }));\n formsroot.append(card);\n }\n const wizards = context.wizards?.wizards ?? [];\n if (wizards.length > 0) {\n const wizard = wizards[0] as wizardstate;\n const heading = document.createElement(\"p\");\n const indicators = Array.from({ length: wizard.steps }, (_, index) => `${index < wizard.index ? (wizard.completed[index] ? \"\u2713\" : \"\u00B7\") : \"\u25CB\"}`).join(\" \");\n heading.textContent = `wizard progress: step ${Math.min(wizard.index + 1, wizard.steps)} of ${wizard.steps} ${indicators}`;\n formsroot.append(heading);\n }\n const picks = context.wizards?.picks ?? [];\n if (picks.length > 0) {\n const pickline = document.createElement(\"p\");\n pickline.textContent = `typeahead picks: ${picks.slice(0, 6).map(pick => `\"${pick.pick}\" for \"${pick.query}\"`).join(\" \u00B7 \")}`;\n formsroot.append(pickline);\n }\n const reports = context.errorreports ?? [];\n if (reports.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"inline error reports with field refs for correction loops:\";\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const report of reports.slice(0, 3)) {\n const item = document.createElement(\"li\");\n item.textContent = `${report.form || \"the reviewed form\"}: ${report.errors.map((error: fielderror) => `${error.field} \u2014 ${error.message}`).join(\"; \") || \"no message\"}`;\n list.append(item);\n }\n formsroot.append(list);\n }\n const codecard = document.createElement(\"div\");\n codecard.className = \"bannercard\";\n const codetitle = document.createElement(\"p\");\n codetitle.textContent = active ? \"one time code entry (stored behind the consent gate of the active session):\" : \"one time code entry needs an active session first.\";\n codecard.append(codetitle);\n if (active) {\n const codeinput = document.createElement(\"input\");\n codeinput.type = \"text\";\n codeinput.inputMode = \"numeric\";\n codeinput.placeholder = context.codeentry ? \"a reviewed code is stored\" : \"one time code\";\n codeinput.setAttribute(\"aria-label\", \"one time code\");\n const storebutton = button(\"Store reviewed code\", async () => {\n await request({ kind: \"storecode\", code: codeinput.value });\n status(\"The reviewed one time code is stored behind the consent gate.\");\n await refresh();\n });\n codecard.append(codeinput, \" \", storebutton);\n }\n formsroot.append(codecard);\n}\n\n/** Renders the dataset surfaces: the preview grid with sortable columns, extraction progress cards with resume prompts, export actions per dataset, transform rule previews, dedupe results, provenance records, import pickers and sheet endpoint grant states. */\nfunction renderdatasets(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; outcomes?: stepoutcome[]; datasets?: dataset[]; imports?: dataset[]; extractsessions?: extractsession[]; streams?: streamstate[]; exports?: Array<{ id: string; kind: string; name: string; rowcount: number; checksum: string; at: number }>; provenances?: provenancerecord[]; taskrules?: taskrules[]; sheetendpoints?: Array<{ endpoint: string; origin: string; configuredat: number; granted: boolean }> }): void {\n if (!datasetsroot) return;\n datasetsroot.replaceChildren();\n const outcomes = context.outcomes ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const extractsessions = context.extractsessions ?? [];\n for (const extract of extractsessions.slice(0, 4)) {\n const card = document.createElement(\"p\");\n const interrupted = extract.done !== true;\n card.textContent = `extraction ${extract.name}: ${extract.pages.length} page${extract.pages.length === 1 ? \"\" : \"s\"} visited \u00B7 ${extract.rows} row${extract.rows === 1 ? \"\" : \"s\"} collected \u00B7 cursor ${extract.cursor} of ${extract.planned}${extract.done ? \" \u00B7 complete\" : \" \u00B7 interrupted\"}`;\n datasetsroot.append(card);\n }\n const interrupted = extractsessions.find(extract => extract.done !== true);\n if (interrupted && active) {\n const prompt = document.createElement(\"div\");\n prompt.className = \"bannercard\";\n prompt.textContent = `Extraction ${interrupted.name} was interrupted at cursor ${interrupted.cursor}; run its resumeextract reviewed step to continue from the stored cursor.`;\n datasetsroot.append(prompt);\n }\n const streams = context.streams ?? [];\n if (streams.length > 0) {\n const stream = streams[0]!;\n const card = document.createElement(\"p\");\n card.textContent = `stream state: ${stream.name} chunk ${stream.chunk} of ${stream.chunks} \u00B7 ${stream.written} row${stream.written === 1 ? \"\" : \"s\"} written${stream.done ? \" \u00B7 complete\" : \" \u00B7 resumable\"}`;\n datasetsroot.append(card);\n }\n const rules = (context.taskrules ?? [])[0];\n if (rules && rules.transforms.length > 0) {\n const transforms = document.createElement(\"p\");\n transforms.textContent = `transform rules: ${rules.transforms.map(rule => `${rule.sources.join(\"+\")} \u2192 ${rule.target} (${rule.expression})`).join(\" \u00B7 \")}`;\n datasetsroot.append(transforms);\n }\n if (rules && rules.dedupekeys.length > 0) {\n const keys = document.createElement(\"p\");\n keys.textContent = `dedupe keys: ${rules.dedupekeys.join(\", \")}`;\n datasetsroot.append(keys);\n }\n const dedupeoutcome = [...outcomes].reverse().find(outcome => outcome.details?.dedupe !== undefined);\n if (dedupeoutcome) {\n const dedupe = dedupeoutcome.details?.dedupe as { removed: number; kept: number; keys: string[] };\n const card = document.createElement(\"p\");\n card.textContent = `last dedupe: removed ${dedupe.removed} duplicate row${dedupe.removed === 1 ? \"\" : \"s\"}, kept ${dedupe.kept} by ${dedupe.keys.join(\", \")}`;\n datasetsroot.append(card);\n }\n for (const datasetvalue of (context.datasets ?? []).slice(0, 4)) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `dataset ${datasetvalue.name}: ${datasetvalue.rows.length} row${datasetvalue.rows.length === 1 ? \"\" : \"s\"} \u00B7 ${datasetvalue.columns.length} column${datasetvalue.columns.length === 1 ? \"\" : \"s\"}${(context.imports ?? []).some(item => item.id === datasetvalue.id) ? \" \u00B7 imported csv\" : \"\"}`;\n card.append(head);\n const grid = document.createElement(\"table\");\n const headerrow = document.createElement(\"tr\");\n for (const column of datasetvalue.columns.slice(0, 6)) {\n const cell = document.createElement(\"th\");\n cell.textContent = `${column.label || column.key} ${column.kind === \"number\" ? \"#\" : \"\"}`;\n cell.addEventListener(\"click\", () => {\n const body = grid.querySelector(\"tbody\");\n if (!body) return;\n const sorted = sortrows(datasetvalue.rows.slice(0, 5), column.key, cell.dataset.sorted === \"asc\" ? \"desc\" : \"asc\");\n cell.dataset.sorted = cell.dataset.sorted === \"asc\" ? \"desc\" : \"asc\";\n body.replaceChildren(...sorted.map(row => {\n const line = document.createElement(\"tr\");\n for (const columnspec of datasetvalue.columns.slice(0, 6)) {\n const value = document.createElement(\"td\");\n value.textContent = row[columnspec.key] ?? \"\";\n line.append(value);\n }\n return line;\n }));\n });\n headerrow.append(cell);\n }\n grid.append(headerrow);\n const body = document.createElement(\"tbody\");\n for (const row of datasetvalue.rows.slice(0, 5)) {\n const line = document.createElement(\"tr\");\n for (const column of datasetvalue.columns.slice(0, 6)) {\n const cell = document.createElement(\"td\");\n cell.textContent = row[column.key] ?? \"\";\n line.append(cell);\n }\n body.append(line);\n }\n grid.append(body);\n card.append(grid);\n if (active) {\n const actions = document.createElement(\"p\");\n for (const format of [\"csv\", \"json\", \"excel\"] as const) {\n actions.append(\" \", button(`Export ${format}`, async () => {\n const artifact = await request({ kind: \"exportdataset\", datasetid: datasetvalue.id, format }) as { name: string; checksum: string };\n status(`Exported ${datasetvalue.name} to ${artifact.name} with checksum ${artifact.checksum}.`);\n await refresh();\n }));\n }\n card.append(actions);\n }\n datasetsroot.append(card);\n }\n const provenances = context.provenances ?? [];\n if (provenances.length > 0) {\n const list = document.createElement(\"ul\");\n for (const record of provenances.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.name}: rows ${record.rowstart}\u2013${record.rowend} \u00B7 checksum ${record.checksum} \u00B7 source ${record.url}`;\n list.append(item);\n }\n datasetsroot.append(list);\n }\n const sheetendpoints = context.sheetendpoints ?? [];\n if (sheetendpoints.length > 0) {\n const sheets = document.createElement(\"p\");\n sheets.textContent = `sheet endpoints: ${sheetendpoints.map(config => `${config.origin} ${config.granted ? \"granted\" : \"not granted\"}`).join(\" \u00B7 \")}`;\n datasetsroot.append(sheets);\n }\n if (active) {\n const importer = document.createElement(\"div\");\n importer.className = \"panel\";\n const csvinput = document.createElement(\"textarea\");\n csvinput.rows = 3;\n csvinput.placeholder = \"Paste reviewed csv content for a fill loop (header line first).\";\n const nameinput = document.createElement(\"input\");\n nameinput.placeholder = \"dataset name (optional)\";\n const mappinginput = document.createElement(\"input\");\n mappinginput.placeholder = \"column mapping json (optional, csv header \u2192 target)\";\n importer.append(csvinput, nameinput, mappinginput, \" \", button(\"Import csv\", async () => {\n let mapping: Record<string, string> = {};\n if (mappinginput.value.trim()) {\n try { mapping = JSON.parse(mappinginput.value) as Record<string, string>; } catch { status(\"The column mapping must be a json object.\", true); return; }\n }\n const imported = await request({ kind: \"importcsv\", csv: csvinput.value, name: nameinput.value, mapping }) as { name: string; rows: number };\n status(`Imported ${imported.rows} rows as dataset ${imported.name} for fill loops.`);\n await refresh();\n }));\n datasetsroot.append(importer);\n }\n}\n\n/** Renders the files, clipboard and downloads surface: the batch download queue with per file states and pause, resume and verify actions, mime interception rules with origin grants, clipboard consent prompts with the requesting step, the netlog viewer with step correlation filters and redaction notices, the quarantine list with scan verdicts and release actions, capture naming previews, cleanup policy editing, artifact inventories and copyscreen results. */\nfunction renderfiles(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; plan?: agentplan; downloads?: downloadrecord[]; mimefilters?: mimefilter[]; clipconsents?: clipboardconsentrecord[]; clips?: clipentry[]; netlogs?: netlogrecord[]; quarantines?: quarantineentry[]; capturecounters?: Array<{ taskid: string; counters: Record<string, number>; at: number }>; cleanuprules?: cleanuprule[]; cleanupruns?: cleanuprun[]; inventory?: artifactinventoryentry[]; scanhooks?: Array<{ scanner: string; endpoint: string; origin: string; configuredat: number; granted: boolean }> }): void {\n if (!filesroot) return;\n filesroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const downloads = context.downloads ?? [];\n if (downloads.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n const states = [\"queued\", \"running\", \"paused\", \"complete\", \"failed\"] as const;\n head.textContent = `batch download queue: ${downloads.length} file${downloads.length === 1 ? \"\" : \"s\"} (${states.map(state => `${downloads.filter(item => item.state === state).length} ${state}`).filter(part => !part.startsWith(\"0 \")).join(\" \u00B7 \") || \"none\"})`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const record of downloads.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.filename} \u00B7 ${record.state}${record.bytes !== undefined ? ` \u00B7 ${record.bytes} bytes` : \"\"}${record.checksum !== undefined ? ` \u00B7 checksum ${record.checksum}` : \"\"}${record.path !== undefined ? ` \u00B7 ${record.path}` : \"\"}`;\n if (active) {\n item.append(\" \", button(\"Pause\", () => request({ kind: \"downloadaction\", id: record.id, action: \"pause\" }).then(() => refresh()).then(() => status(`Paused the download of ${record.filename}.`)), record.state !== \"running\"));\n item.append(\" \", button(\"Resume\", () => request({ kind: \"downloadaction\", id: record.id, action: \"resume\" }).then(() => refresh()).then(() => status(`Resumed the download of ${record.filename}.`)), record.state !== \"paused\"));\n item.append(\" \", button(\"Verify\", () => request({ kind: \"downloadaction\", id: record.id, action: \"verify\" }).then(value => { const output = value as { summary: string }; status(output.summary); return refresh(); })));\n }\n list.append(item);\n }\n card.append(list);\n filesroot.append(card);\n }\n const filters = context.mimefilters ?? [];\n if (filters.length > 0) {\n const filter = filters[0]!;\n const card = document.createElement(\"p\");\n card.textContent = `mime interception: include ${filter.include.join(\", \")} \u00B7 exclude ${filter.exclude.join(\", \") || \"none\"} \u00B7 ${filter.default} default for unlisted mime types${context.session?.origin ? ` \u00B7 armed inside the ${context.session.origin} origin grants` : \"\"}`;\n filesroot.append(card);\n }\n const consents = (context.clipconsents ?? []).filter(record => record.approved === undefined);\n for (const consent of consents.slice(0, 4)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n card.textContent = `Clipboard read consent ${consent.id} waits for your approval: step ${consent.stepid} on ${consent.origin} asked to read the clipboard \u2014 \"${consent.prompt}\".`;\n if (active) {\n card.append(\" \", button(\"Approve read\", async () => { await request({ kind: \"approveclipconsent\", id: consent.id, approved: true }); status(`Clipboard read consent ${consent.id} approved; run the step again to read once.`); await refresh(); }));\n card.append(\" \", button(\"Decline\", async () => { await request({ kind: \"approveclipconsent\", id: consent.id, approved: false }); status(`Clipboard read consent ${consent.id} declined.`); await refresh(); }));\n }\n filesroot.append(card);\n }\n const netlogs = context.netlogs ?? [];\n if (netlogs.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n const steps = [...new Set(netlogs.map(record => record.stepid))];\n head.textContent = `network log: ${netlogs.length} record${netlogs.length === 1 ? \"\" : \"s\"} correlated with ${steps.length} step${steps.length === 1 ? \"\" : \"s\"} (${steps.slice(0, 4).join(\", \")}${steps.length > 4 ? \"\u2026\" : \"\"})`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const record of netlogs.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.method} ${record.url} \u00B7 ${record.status} \u00B7 ${record.timing}ms \u00B7 request ${record.requestid ?? \"?\"} \u00B7 step ${record.stepid}`;\n list.append(item);\n }\n card.append(list);\n if (active) card.append(button(\"Export netlog (header values redacted)\", async () => { const exported = await request({ kind: \"exportnetlog\" }) as { records: unknown[]; redaction: string }; status(`Exported ${exported.records.length} netlog records; ${exported.redaction}.`); }));\n filesroot.append(card);\n }\n const quarantines = context.quarantines ?? [];\n if (quarantines.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `quarantine: ${quarantines.length} file${quarantines.length === 1 ? \"\" : \"s\"} outside the downloads folder (${quarantines.filter(entry => entry.scan === \"pending\").length} awaiting scan verdicts)`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const entry of quarantines.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.path} \u00B7 scan ${entry.scan}${entry.release !== undefined ? ` \u00B7 released under ${entry.release}` : \"\"} \u00B7 ${entry.reason}`;\n if (active && entry.release === undefined && entry.scan === \"clean\") item.append(\" \", button(\"Release\", async () => { await request({ kind: \"releasequarantine\", id: entry.id }); status(`Released ${entry.path} from quarantine under the clean scan verdict.`); await refresh(); }));\n list.append(item);\n }\n card.append(list);\n filesroot.append(card);\n }\n const planid = context.plan?.id;\n const counters = (context.capturecounters ?? []).find(item => item.taskid === planid);\n if (counters) {\n const card = document.createElement(\"p\");\n card.textContent = `capture naming for task ${counters.taskid}: ${Object.entries(counters.counters).map(([step, sequence]) => `${step} \u2192 ${counters.taskid}-${step}-${sequence}`).join(\" \u00B7 \")}`;\n filesroot.append(card);\n }\n const rules = context.cleanuprules ?? [];\n const rulecard = document.createElement(\"div\");\n rulecard.className = \"panel\";\n const rulehead = document.createElement(\"p\");\n rulehead.textContent = `cleanup policy: ${rules.length > 0 ? rules.map(rule => `older than ${rule.age}ms of kind ${rule.kind} keep ${rule.keep}`).join(\" \u00B7 \") : \"no rule set stored yet\"}`;\n rulecard.append(rulehead);\n const runs = context.cleanupruns ?? [];\n if (runs.length > 0) {\n const lastrun = runs[0]!;\n const runline = document.createElement(\"p\");\n runline.textContent = `last sweep: removed ${lastrun.removed}, kept ${lastrun.kept} under ${lastrun.rules} rule${lastrun.rules === 1 ? \"\" : \"s\"}`;\n rulecard.append(runline);\n }\n if (active) {\n const ageinput = document.createElement(\"input\");\n ageinput.placeholder = \"age window in ms\";\n const kindinput = document.createElement(\"input\");\n kindinput.placeholder = \"artifact kind (any matches all)\";\n const keepinput = document.createElement(\"input\");\n keepinput.placeholder = \"keep policy: none, latest or all\";\n rulecard.append(ageinput, kindinput, keepinput, \" \", button(\"Add cleanup rule\", async () => {\n const age = Number(ageinput.value);\n const rule = { age, kind: kindinput.value.trim() || \"any\", keep: keepinput.value.trim() || \"none\" } as cleanuprule;\n const stored = await request({ kind: \"setcleanuprules\", rules: [...rules, rule] }) as { rules: number };\n status(`Stored ${stored.rules} reviewed cleanup rule${stored.rules === 1 ? \"\" : \"s\"}; ages stay your choice with no code ceiling.`);\n await refresh();\n }));\n }\n filesroot.append(rulecard);\n const inventory = context.inventory ?? [];\n if (inventory.length > 0) {\n const card = document.createElement(\"p\");\n card.textContent = `artifact inventory: ${inventory.slice(0, 5).map(entry => `${entry.name} (${entry.kind}, ${entry.size} characters, ${Math.max(0, Math.round((Date.now() - entry.at) / 60000))} minute${Math.round((Date.now() - entry.at) / 60000) === 1 ? \"\" : \"s\"} old)`).join(\" \u00B7 \")}${inventory.length > 5 ? ` and ${inventory.length - 5} more` : \"\"}`;\n filesroot.append(card);\n }\n const screens = (context.clips ?? []).filter(entry => entry.kind === \"screen\").slice(0, 2);\n for (const screen of screens) {\n const card = document.createElement(\"p\");\n card.textContent = `copyscreen result: ${screen.length} characters of png data with payload hash ${screen.hash} routed to the clipboard destination.`;\n filesroot.append(card);\n }\n const hooks = context.scanhooks ?? [];\n if (active) {\n const hookcard = document.createElement(\"div\");\n hookcard.className = \"panel\";\n const hookhead = document.createElement(\"p\");\n hookhead.textContent = hooks.length > 0 ? `scan hooks: ${hooks.map(hook => `${hook.scanner} at ${hook.origin} ${hook.granted ? \"granted\" : \"not granted\"}`).join(\" \u00B7 \")}` : \"scan hooks: none configured; scan verdicts stay pending without one.\";\n hookcard.append(hookhead);\n const scannerinput = document.createElement(\"input\");\n scannerinput.placeholder = \"scanner name\";\n const endpointinput = document.createElement(\"input\");\n endpointinput.placeholder = \"https://scanner.example/verdict\";\n hookcard.append(scannerinput, endpointinput, \" \", button(\"Configure scan hook\", async () => {\n await request({ kind: \"configurescanhook\", scanner: scannerinput.value, endpoint: endpointinput.value });\n status(`Scan hook ${scannerinput.value} configured; hook failures stay pending verdicts.`);\n await refresh();\n }));\n filesroot.append(hookcard);\n }\n}\n\n/** One capture metadata card of the gallery; bytes stay out of the context and load per capture on demand. */\ntype capturemeta = { id: string; runid: string; stepid: string; kind: string; format: string; width: number; height: number; capturedat: number; name?: string; annotated?: boolean; target?: string; bytesexpired?: boolean };\n\n/** Loads the bytes of one stored capture on demand; expired bytes resolve to undefined. */\nasync function capturebytes(id: string): Promise<string | undefined> {\n try {\n const record = await request({ kind: \"capturebytes\", id }) as { bytes: string };\n return record.bytes;\n } catch { return undefined; }\n}\n\n/** Opens any capture full size with its metadata, download and clipboard copy actions. */\nfunction opencapture(record: capturemeta): void {\n if (!capturesroot) return;\n const viewer = document.createElement(\"div\");\n viewer.className = \"panel captureviewer\";\n const head = document.createElement(\"p\");\n head.textContent = `${record.kind} \u00B7 ${record.format} \u00B7 ${record.width}\u00D7${record.height} px \u00B7 step ${record.stepid}${record.annotated ? \" \u00B7 annotated evidence\" : \"\"}${record.name !== undefined ? ` \u00B7 ${record.name}` : \"\"}`;\n viewer.append(head);\n const image = document.createElement(\"img\");\n image.alt = `Capture ${record.id} of kind ${record.kind}`;\n image.src = \"\";\n void capturebytes(record.id).then(bytes => { if (bytes) image.src = bytes; else viewer.append(Object.assign(document.createElement(\"p\"), { textContent: \"The capture bytes expired from the retention window; the metadata stays for the audit trail.\" })); });\n viewer.append(image);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Download\", () => request({ kind: \"downloadcapture\", id: record.id }).then(() => status(`Downloaded capture ${record.id} through the reviewed download flow.`))));\n actions.append(button(\"Copy to clipboard\", () => request({ kind: \"copycapture\", id: record.id }).then(() => status(`Copied capture ${record.id} to the clipboard.`))));\n actions.append(button(\"Close\", async () => viewer.remove()));\n viewer.append(actions);\n capturesroot.append(viewer);\n}\n\n\n/** One media record metadata card; bytes stay out of the context and load per record on demand. */\ntype mediameta = { id: string; runid: string; stepid: string; at: number; bytesexpired?: boolean } & Record<string, unknown>;\n\n/** Loads the bytes of one stored media record on demand; expired bytes resolve to undefined. */\nasync function mediabytes(id: string): Promise<string | undefined> {\n try {\n const record = await request({ kind: \"mediabytes\", id }) as { bytes: string };\n return record.bytes;\n } catch { return undefined; }\n}\n\n/** Plays an ordered frame sequence as a lapse: the image cycles through the frame bytes at the recorded interval. */\nfunction playframes(frameids: string[], interval: number, label: string): void {\n if (!mediaroot) return;\n const viewer = document.createElement(\"div\");\n viewer.className = \"panel captureviewer\";\n const head = document.createElement(\"p\");\n head.textContent = `${label}: ${frameids.length} frames at ${interval} millisecond intervals`;\n viewer.append(head);\n const image = document.createElement(\"img\");\n image.alt = \"Lapse frame\";\n viewer.append(image);\n let index = 0;\n let stopped = false;\n const show = async (): Promise<void> => {\n if (stopped) return;\n const bytes = await capturebytes(frameids[index] ?? \"\");\n if (bytes) image.src = bytes;\n index = (index + 1) % Math.max(1, frameids.length);\n };\n void show();\n const timer = window.setInterval(() => { void show(); }, Math.max(100, interval));\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Stop\", async () => { stopped = true; window.clearInterval(timer); viewer.remove(); }));\n viewer.append(actions);\n mediaroot.append(viewer);\n}\n\n/** Renders the media tab: the recording indicator, recording consents, pdf reports, image batches with match counts, video frames and lapse playback, recordings with play, download and delete controls, stream probe results, assets and the convertimage and makethumbs actions on stored captures. */\nfunction rendermedia(context: { session?: { stoppedat?: number; expiresat: number }; media?: mediameta[]; imagebatches?: Array<{ id: string; runid: string; stepid: string; images: Array<{ url: string; alt: string; width: number; height: number; bytes: number; mime: string }>; matched: number; downloaded: number; at: number }>; recordingconsents?: Array<{ id: string; prompt: string; origin: string; stepid: string; approved?: boolean; usedat?: number; at: number }>; recordingactive?: Array<{ id: string; kind: string; scope: string; startedat: number; stopat: number }>; recordingwindow?: number; captures?: capturemeta[] }): void {\n if (!mediaroot) return;\n mediaroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n if ((context.recordingactive ?? []).length > 0) {\n const indicator = document.createElement(\"p\");\n indicator.className = \"recordingindicator\";\n indicator.textContent = `\u25CF recording in progress: ${context.recordingactive?.map(item => `${item.kind} of ${item.scope} scope`).join(\", \")}`;\n mediaroot.append(indicator);\n }\n for (const consent of (context.recordingconsents ?? []).filter(item => item.approved === undefined)) {\n const card = document.createElement(\"div\");\n card.className = \"panel recordingcard\";\n const head = document.createElement(\"p\");\n head.textContent = `Recording consent ${consent.id} for step ${consent.stepid} on ${consent.origin}: ${consent.prompt}`;\n card.append(head);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve recording\", () => request({ kind: \"approverecordingconsent\", id: consent.id, approved: true }).then(() => status(`Recording consent ${consent.id} approved; rerun the recording step.`)).then(refresh)));\n actions.append(button(\"Decline\", () => request({ kind: \"approverecordingconsent\", id: consent.id, approved: false }).then(() => status(`Recording consent ${consent.id} declined.`)).then(refresh)));\n card.append(actions);\n mediaroot.append(card);\n }\n const records = context.media ?? [];\n const pdfs = records.filter(record => record.pages !== undefined);\n const recordings = records.filter(record => record.startedat !== undefined);\n const frames = records.filter(record => record.timestamp !== undefined);\n const canvases = records.filter(record => record.context !== undefined);\n const streams = records.filter(record => record.tracks !== undefined);\n const assets = records.filter(record => record.url !== undefined && record.kind !== undefined && (record.kind === \"favicon\" || record.kind === \"logo\"));\n if (pdfs.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `pdf reports: ${pdfs.length}`;\n card.append(head);\n for (const pdf of pdfs) {\n const row = document.createElement(\"p\");\n row.textContent = `${String(pdf.name ?? pdf.id)} \u00B7 ${String(pdf.pages)} page${String(pdf.pages) === \"1\" ? \"\" : \"s\"} \u00B7 ${String(pdf.pagewidth)}\u00D7${String(pdf.pageheight)} pt${pdf.landscape === true ? \" \u00B7 landscape\" : \"\"} \u00B7 ${String(pdf.bytes)} bytes${pdf.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n card.append(row);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Download pdf\", () => request({ kind: \"downloadmedia\", id: String(pdf.id) }).then(() => status(`Downloaded the pdf report ${String(pdf.name ?? pdf.id)} through the reviewed download flow.`)), !active || pdf.bytesexpired === true));\n card.append(actions);\n }\n mediaroot.append(card);\n }\n for (const batch of context.imagebatches ?? []) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `image batch of step ${batch.stepid}: ${batch.matched} of ${batch.images.length} observed images matched, ${batch.downloaded} downloaded`;\n card.append(head);\n const list = document.createElement(\"ol\");\n list.className = \"audit\";\n for (const image of batch.images.slice(0, 12)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${image.url}${image.alt ? ` \u00B7 ${image.alt}` : \"\"} \u00B7 ${image.width}\u00D7${image.height} \u00B7 ${image.bytes} bytes \u00B7 ${image.mime}`;\n list.append(entry);\n }\n card.append(list);\n mediaroot.append(card);\n }\n if (frames.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `video frames: ${frames.length}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const frame of frames) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${String(frame.source)} \u00B7 ${String(frame.timestamp)}s${frame.poster === true ? \" \u00B7 poster\" : \"\"}${frame.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Video frame ${String(frame.id)}`;\n if (frame.bytesexpired !== true) void mediabytes(String(frame.id)).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n grid.append(cell);\n }\n card.append(grid);\n mediaroot.append(card);\n }\n const timelapse = (context.captures ?? []).filter(record => record.kind === \"timelapse\");\n if (timelapse.length > 1) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `time lapse sequences: ${timelapse.length} frames`;\n card.append(head);\n card.append(button(\"Play lapse sequence\", async () => {\n const ordered = await request({ kind: \"capturereport\" }) as { records: Array<{ id: string; kind: string; capturedat: number }> };\n const ids = ordered.records.filter(record => record.kind === \"timelapse\").sort((left, right) => left.capturedat - right.capturedat).map(record => record.id);\n playframes(ids, 800, \"time lapse\");\n }));\n mediaroot.append(card);\n }\n if (canvases.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `canvas captures: ${canvases.length}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const canvas of canvases) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${String(canvas.element)} \u00B7 ${String(canvas.context)} \u00B7 ${String(canvas.width)}\u00D7${String(canvas.height)}${canvas.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Canvas capture ${String(canvas.id)}`;\n if (canvas.bytesexpired !== true) void mediabytes(String(canvas.id)).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n grid.append(cell);\n }\n card.append(grid);\n mediaroot.append(card);\n }\n for (const stream of streams) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `stream probe ${String(stream.label || stream.id)}: ${String(stream.tracks)} track${String(stream.tracks) === \"1\" ? \"\" : \"s\"} \u00B7 ${stream.live === true ? \"live\" : \"ended\"}`;\n card.append(head);\n const detail = stream.detail as Array<{ kind: string; label: string; width?: number; height?: number; framerate?: number; state: string }> | undefined;\n if (Array.isArray(detail)) {\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const track of detail) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${track.kind} track${track.label ? ` ${track.label}` : \"\"}${track.width !== undefined ? ` \u00B7 ${track.width}\u00D7${track.height}` : \"\"}${track.framerate !== undefined ? ` \u00B7 ${Math.round(track.framerate)} fps` : \"\"} \u00B7 ${track.state}`;\n list.append(entry);\n }\n card.append(list);\n }\n mediaroot.append(card);\n }\n if (assets.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `page assets: ${assets.filter(asset => asset.kind === \"favicon\").length} favicon and ${assets.filter(asset => asset.kind === \"logo\").length} logo entries`;\n card.append(head);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const asset of assets.slice(0, 12)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${String(asset.kind)} \u00B7 ${String(asset.url)}${asset.sizes !== undefined ? ` \u00B7 ${String(asset.sizes)}` : \"\"}`;\n list.append(entry);\n }\n card.append(list);\n mediaroot.append(card);\n }\n for (const recording of recordings) {\n const card = document.createElement(\"div\");\n card.className = \"panel recordingcard\";\n const head = document.createElement(\"p\");\n head.textContent = `${String(recording.kind)} recording ${String(recording.id)} \u00B7 ${String(recording.scope)} scope \u00B7 ${String(recording.duration ?? 0)} ms \u00B7 ${Array.isArray(recording.frames) ? String(recording.frames.length) : \"0\"} frames \u00B7 manifest ${String(recording.bytes ?? 0)} bytes${recording.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n card.append(head);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n const frames = Array.isArray(recording.frames) ? recording.frames as string[] : [];\n if (String(recording.kind) === \"screen\" && frames.length > 0) {\n actions.append(button(\"Play frames\", async () => {\n const state = await request({ kind: \"recordingframes\", id: String(recording.id) }) as { frames: string[]; interval: number };\n playframes(state.frames, state.interval, `screen recording ${String(recording.id)}`);\n }));\n }\n actions.append(button(\"Download manifest\", () => request({ kind: \"downloadrecording\", id: String(recording.id) }).then(() => status(`Downloaded the recording manifest ${String(recording.id)} through the reviewed download flow.`)), !active));\n actions.append(button(\"Delete\", () => request({ kind: \"deleterecording\", id: String(recording.id) }).then(() => status(`Deleted the recording ${String(recording.id)}.`)).then(refresh), !active));\n card.append(actions);\n mediaroot.append(card);\n }\n const stored = (context.captures ?? []).filter(record => record.bytesexpired !== true).slice(0, 12);\n if (stored.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = \"capture transforms: convertimage and makethumbs actions on stored captures\";\n card.append(head);\n for (const record of stored) {\n const row = document.createElement(\"div\");\n row.className = \"actions\";\n const label = document.createElement(\"p\");\n label.textContent = `${record.kind} ${record.id} (${record.format})`;\n row.append(label);\n for (const target of [\"png\", \"jpeg\", \"webp\"] as const) {\n if (target !== record.format) row.append(button(`\u2192 ${target}`, () => request({ kind: \"convertcapture\", id: record.id, target }).then(() => status(`Converted capture ${record.id} to ${target}.`)).then(refresh), !active));\n }\n row.append(button(\"thumbnail\", () => request({ kind: \"thumbcapture\", id: record.id, size: 240, fit: \"cover\", suffix: \"thumb\" }).then(() => status(`Thumbnailed capture ${record.id}.`)).then(refresh), !active));\n card.append(row);\n }\n mediaroot.append(card);\n }\n if (records.length === 0 && (context.imagebatches ?? []).length === 0 && (context.recordingactive ?? []).length === 0) {\n mediaroot.append(Object.assign(document.createElement(\"p\"), { textContent: \"No media stored yet; run a capturepdf, recordscreen, captureaudio, captureframe, downloadimages, shotcanvas, probestream, readmedia, readassets, timelapse, convertimage or makethumbs step.\" }));\n }\n}\n/** Renders the capture gallery: the policy toggle, stitch progress, thumbnails per run, contact sheet cells and before and after pairs with a divider. */\nfunction rendercaptures(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; outcomes?: stepoutcome[]; captures?: capturemeta[]; capturepairs?: shotpair[]; capturepolicy?: string; stitchprogress?: Array<{ stepid: string; done: number; total: number }> }): void {\n if (!capturesroot) return;\n capturesroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const policy = (context.capturepolicy ?? \"manual\") as capturepolicy;\n const policyrow = document.createElement(\"div\");\n policyrow.className = \"actions\";\n const policylabel = document.createElement(\"p\");\n policylabel.textContent = `capture policy: ${policy}${policy === \"beforeafter\" ? \" \u2014 state pairs wrap every page moving action\" : \"\"}`;\n policyrow.append(policylabel);\n for (const mode of [\"off\", \"manual\", \"annotated\", \"beforeafter\"] as const) {\n policyrow.append(button(mode, async () => { await request({ kind: \"setcapturepolicy\", mode }); status(`Capture policy set to ${mode}.`); await refresh(); }, !active || mode === policy));\n }\n capturesroot.append(policyrow);\n for (const progress of context.stitchprogress ?? []) {\n const bar = document.createElement(\"progress\");\n bar.max = Math.max(1, progress.total);\n bar.value = progress.done;\n const label = document.createElement(\"p\");\n label.textContent = `stitching full page capture of step ${progress.stepid}: tile ${progress.done} of ${progress.total}`;\n capturesroot.append(label, bar);\n }\n const captures = context.captures ?? [];\n if (captures.length === 0 && (context.capturepairs ?? []).length === 0) {\n capturesroot.append(Object.assign(document.createElement(\"p\"), { textContent: \"No captures stored yet; run a shotview, shotfullpage, shotelement, shotregion or contactsheet step.\" }));\n return;\n }\n const runs = [...new Set(captures.map(record => record.runid))];\n for (const run of runs) {\n const runcaptures = captures.filter(record => record.runid === run);\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `run ${run}: ${runcaptures.length} capture${runcaptures.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const record of runcaptures) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = record.annotated ? \"capturecard annotated\" : \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${record.kind} \u00B7 ${record.format} \u00B7 ${record.width}\u00D7${record.height}${record.annotated ? \" \u00B7 annotated\" : \"\"}${record.bytesexpired ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Capture ${record.id} of kind ${record.kind}`;\n if (!record.bytesexpired) void capturebytes(record.id).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n cell.addEventListener(\"click\", () => opencapture(record));\n grid.append(cell);\n if (record.kind === \"contactsheet\") {\n const cells = (context.outcomes ?? []).find(outcome => outcome.stepid === record.stepid && outcome.details?.cells !== undefined)?.details?.cells as Array<{ index: number; selector: string; caption: string }> | undefined;\n for (const sheetcell of cells ?? []) {\n const cellbutton = document.createElement(\"button\");\n cellbutton.type = \"button\";\n cellbutton.className = \"secondary\";\n cellbutton.textContent = sheetcell.caption || sheetcell.selector;\n cellbutton.addEventListener(\"click\", () => opencapture(record));\n grid.append(cellbutton);\n }\n }\n }\n card.append(grid);\n capturesroot.append(card);\n }\n for (const pair of context.capturepairs ?? []) {\n const card = document.createElement(\"div\");\n card.className = \"panel pairview\";\n const head = document.createElement(\"p\");\n head.textContent = `state pair around the ${pair.actionkind} action${pair.target !== undefined ? ` on ${pair.target}` : \"\"}${pair.domsnapshotid !== undefined ? ` \u00B7 dom snapshot ${pair.domsnapshotid}` : \"\"}`;\n card.append(head);\n const row = document.createElement(\"div\");\n row.className = \"pairrow\";\n const before = document.createElement(\"img\");\n before.alt = `Before shot ${pair.beforeid}`;\n const after = document.createElement(\"img\");\n after.alt = `After shot ${pair.afterid}`;\n void capturebytes(pair.beforeid).then(bytes => { if (bytes) before.src = bytes; });\n void capturebytes(pair.afterid).then(bytes => { if (bytes) after.src = bytes; });\n row.append(before, after);\n const divider = document.createElement(\"input\");\n divider.type = \"range\";\n divider.min = \"0\";\n divider.max = \"100\";\n divider.value = \"50\";\n divider.setAttribute(\"aria-label\", \"Before and after divider\");\n divider.addEventListener(\"input\", () => { before.style.width = `${100 - Number(divider.value)}%`; after.style.width = `${Number(divider.value)}%`; });\n card.append(row, divider);\n capturesroot.append(card);\n }\n}\n\n\n/** Renders the traffic control view: the active block, mock and rewrite rule lists with live hit counts, the cookie operations with values redacted, the oauth flow state with provider and scopes, the stored token metadata per provider, the proxy state with a manual revert button, the rate limit waits with reset times, the api key consent scope and the multipart upload progress of postfiles steps. */\nfunction rendertraffic(context: { session?: { stoppedat?: number; expiresat: number }; traffic?: { blocks: Array<{ id: string; urlpattern: string; hits: number; revertedat?: number; stepid: string }>; mocks: Array<{ id: string; urlpattern: string; status: number; hits: number; revertedat?: number }>; rewrites: Array<{ id: string; urlpattern: string; name: string; operation: string; value?: string; hits: number; revertedat?: number }>; cookies: Array<{ id: string; kind: string; domain: string; names: string[]; at: number }>; proxies: Array<{ id: string; scheme: string; host: string; port: number; bypass: string[]; appliedat: number; revertedat?: number }>; ratelimits: Array<{ origin: string; remaining?: number; limit?: number; resetat: number }> }; tokens?: { tokens: Array<{ id: string; provider: string; origin: string; scopes: string[]; expiresat: number; refreshedat?: number; revokedat?: number }> }; authflows?: Array<{ provider: string; redirectorigin: string; scopes: string[]; stepid: string; tabid: number; stage: string }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; activerules?: number; progress?: planprogress }): void {\n if (!trafficroot) return;\n trafficroot.replaceChildren();\n const head = document.createElement(\"p\");\n head.textContent = `active traffic rules: ${context.activerules ?? 0} (every rule reverts at run end)`;\n trafficroot.append(head);\n const traffic = context.traffic;\n if (traffic === undefined) return;\n if ( (traffic.blocks.length === 0 && traffic.mocks.length === 0 && traffic.rewrites.length === 0 && traffic.cookies.length === 0 && traffic.proxies.length === 0 && traffic.ratelimits.length === 0)) {\n trafficroot.append(Object.assign(document.createElement(\"p\"), { className: \"muted\", textContent: \"No traffic rule has been applied yet; blockrequest, mockresponse, rewriteheaders, setcookies, clearcookies, routeproxy, postform and postfiles steps land here.\" }));\n }\n for (const rule of traffic.blocks) {\n const row = document.createElement(\"p\");\n row.textContent = `block ${rule.urlpattern} \u00B7 ${rule.hits} blocked \u00B7 ${rule.revertedat !== undefined ? \"reverted\" : \"active\"} \u00B7 step ${rule.stepid}`;\n trafficroot.append(row);\n }\n for (const spec of traffic.mocks) {\n const row = document.createElement(\"p\");\n row.textContent = `mock ${spec.urlpattern} \u2192 ${spec.status} \u00B7 ${spec.hits} served \u00B7 ${spec.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n }\n for (const rule of traffic.rewrites) {\n const row = document.createElement(\"p\");\n row.textContent = `rewrite ${rule.operation} ${rule.name} on ${rule.urlpattern} \u00B7 ${rule.hits} applied \u00B7 ${rule.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n }\n for (const route of traffic.proxies) {\n const row = document.createElement(\"p\");\n row.textContent = `proxy ${route.scheme}://${route.host}:${route.port} \u00B7 bypass ${route.bypass.join(\", \")} \u00B7 ${route.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n if (route.revertedat === undefined) {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Revert proxy route\", () => request({ kind: \"revertproxyroute\", id: route.id }).then(() => status(`Proxy route ${route.id} reverted; the previous routing state is restored.`)).then(refresh)));\n trafficroot.append(actions);\n }\n }\n for (const read of traffic.ratelimits) {\n const row = document.createElement(\"p\");\n row.textContent = `rate limit ${read.origin} \u00B7 ${read.remaining ?? \"?\"} of ${read.limit ?? \"?\"} remaining \u00B7 resets ${new Date(read.resetat).toLocaleTimeString()}`;\n trafficroot.append(row);\n }\n for (const flow of context.authflows ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `oauth ${flow.provider} \u00B7 scopes ${flow.scopes.join(\", \")} \u00B7 redirect ${flow.redirectorigin} \u00B7 ${flow.stage} in tab ${flow.tabid}`;\n trafficroot.append(row);\n }\n for (const token of context.tokens?.tokens ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `token ${token.provider} \u00B7 scopes ${token.scopes.join(\", \")} \u00B7 ${token.revokedat !== undefined ? \"revoked\" : `expires ${new Date(token.expiresat).toLocaleTimeString()}`}${token.refreshedat !== undefined ? \" \u00B7 refreshed\" : \"\"}`;\n trafficroot.append(row);\n if (token.revokedat === undefined) {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Revoke token\", () => request({ kind: \"revoketokens\", tokenids: [token.id], reason: \"review panel demand\" }).then(() => status(`Token ${token.id} of ${token.provider} revoked.`)).then(refresh)));\n trafficroot.append(actions);\n }\n }\n for (const op of traffic.cookies.slice(0, 8)) {\n const row = document.createElement(\"p\");\n row.textContent = `cookie ${op.kind} \u00B7 ${op.domain} \u00B7 ${op.names.length === 0 ? \"all cookies\" : op.names.join(\", \")} \u00B7 ${new Date(op.at).toLocaleTimeString()} (values never stored)`;\n trafficroot.append(row);\n }\n for (const ref of context.apikeys ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `api key ${ref.name} \u00B7 header ${ref.header} \u00B7 scoped to ${ref.origins.join(\", \")}${ref.lastuse !== undefined ? ` \u00B7 last use ${new Date(ref.lastuse).toLocaleTimeString()}` : \" \u00B7 unused\"}`;\n trafficroot.append(row);\n }\n const uploads = (context.progress?.outcomes ?? []).filter(outcome => outcome.details?.upload !== undefined).slice(-4);\n for (const outcome of uploads) {\n const entry = outcome.details?.upload as { chunk: number; chunks: number; uploaded: number; bytes: number };\n const row = document.createElement(\"p\");\n row.textContent = `upload chunk ${entry.chunk} of ${entry.chunks} \u00B7 ${entry.uploaded} of ${entry.bytes} bytes`;\n trafficroot.append(row);\n }\n}\n\n/** Renders the network calls view: every outbound call of the run with status, duration, retries and byte counts, expandable header names, parsed fields and errors, fetch consent prompts with name and value, stream progress bars, origin, method and status class filters, endpoint and api key configuration and the reviewed call list export. */\nfunction rendercalls(context: { session?: { stoppedat?: number; expiresat: number }; calls?: Array<{ id: string; runid: string; stepid: string; kind: string; url: string; origin: string; method: string; status: number; statusclass: string; duration: number; retries: number; bytes: number; headernames: string[]; endpoint?: string; bodyexpired?: boolean; fields?: Array<{ name: string; path: string; kind: string; value?: unknown; missing?: boolean }>; errors?: string[]; streambytes?: number }>; fetchconsents?: Array<{ id: string; origin: string; headers: Array<{ name: string; value: string }>; approved?: boolean; expiresat: number; at: number }>; endpoints?: Array<{ name: string; method: string; url: string; version: number; headers?: Record<string, string>; schema?: { fields: Array<{ name: string; kind: string; required?: boolean; default?: string | number | boolean }> } }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; callretention?: number; fetchesactive?: number }): void {\n if (!callsroot) return;\n callsroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n for (const consent of (context.fetchconsents ?? []).filter(item => item.approved === undefined)) {\n const card = document.createElement(\"div\");\n card.className = \"panel consentcard\";\n const head = document.createElement(\"p\");\n head.textContent = `Fetch consent ${consent.id} for ${consent.origin}: review every custom header before it is sent.`;\n card.append(head);\n for (const header of consent.headers) {\n const row = document.createElement(\"p\");\n row.textContent = `${header.name}: ${header.value}`;\n card.append(row);\n }\n const note = document.createElement(\"p\");\n note.className = \"muted\";\n note.textContent = `The prompt appears once per origin and expires ${new Date(consent.expiresat).toLocaleTimeString()}; header values never enter the audit trail.`;\n card.append(note);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve headers\", () => request({ kind: \"approvefetchconsent\", id: consent.id, approved: true }).then(() => status(`Fetch consent ${consent.id} approved; rerun the fetch step.`)).then(refresh)));\n actions.append(button(\"Decline\", () => request({ kind: \"approvefetchconsent\", id: consent.id, approved: false }).then(() => status(`Fetch consent ${consent.id} declined.`)).then(refresh)));\n card.append(actions);\n callsroot.append(card);\n }\n const endpoints = context.endpoints ?? [];\n if (endpoints.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `typed endpoints: ${endpoints.length}`;\n card.append(head);\n for (const endpoint of endpoints) {\n const row = document.createElement(\"p\");\n row.textContent = `${endpoint.name} \u00B7 ${endpoint.method} ${endpoint.url} \u00B7 v${endpoint.version} \u00B7 ${endpoint.schema?.fields.length ?? 0} payload field${endpoint.schema?.fields.length === 1 ? \"\" : \"s\"}${endpoint.headers !== undefined ? ` \u00B7 ${Object.keys(endpoint.headers).length} reviewed header${Object.keys(endpoint.headers).length === 1 ? \"\" : \"s\"}` : \"\"}`;\n card.append(row);\n }\n callsroot.append(card);\n }\n const apikeys = context.apikeys ?? [];\n if (apikeys.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `api key references: ${apikeys.length} (secrets never listed)`;\n card.append(head);\n for (const ref of apikeys) {\n const row = document.createElement(\"p\");\n row.textContent = `${ref.name} \u00B7 header ${ref.header} \u00B7 scoped to ${ref.origins.join(\", \")}`;\n card.append(row);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Remove ${ref.name}`, () => request({ kind: \"deleteapikey\", name: ref.name }).then(() => status(`Api key reference ${ref.name} removed.`)).then(refresh)));\n card.append(actions);\n }\n callsroot.append(card);\n }\n const callsmeta = context.calls ?? [];\n const filters = document.createElement(\"div\");\n filters.className = \"actions\";\n const originfilter = document.createElement(\"input\");\n originfilter.placeholder = \"filter by origin\";\n const methodfilter = document.createElement(\"input\");\n methodfilter.placeholder = \"filter by method\";\n const classfilter = document.createElement(\"input\");\n classfilter.placeholder = \"filter by status class\";\n filters.append(originfilter, methodfilter, classfilter);\n callsroot.append(filters);\n const list = document.createElement(\"div\");\n const applyfilters = (): void => {\n list.replaceChildren();\n const origin = originfilter.value.trim().toLowerCase();\n const method = methodfilter.value.trim().toUpperCase();\n const statusclass = classfilter.value.trim().toLowerCase();\n const matched = callsmeta.filter(call => (!origin || call.origin.toLowerCase().includes(origin)) && (!method || call.method.toUpperCase().includes(method)) && (!statusclass || call.statusclass.includes(statusclass)));\n if (matched.length === 0) { list.textContent = \"No outbound call matches the filters yet.\"; return; }\n for (const call of matched) {\n const card = document.createElement(\"details\");\n card.className = \"panel callcard\";\n const summary = document.createElement(\"summary\");\n const credential = call.headernames.some(name => name.toLowerCase().startsWith(\"apikey:\") || [\"authorization\", \"cookie\", \"proxy-authorization\", \"api-key\", \"x-api-key\", \"x-auth-token\"].includes(name.toLowerCase()));\n summary.textContent = `${call.method} ${call.kind} ${call.status} ${call.statusclass} \u00B7 ${new URL(call.url).host} \u00B7 ${call.duration} ms \u00B7 ${call.retries} retr${call.retries === 1 ? \"y\" : \"ies\"} \u00B7 ${call.bytes} bytes \u00B7 step ${call.stepid}`;\n if (credential) {\n const badge = document.createElement(\"span\");\n badge.className = \"credentialbadge\";\n badge.textContent = \" credential call \";\n summary.append(badge);\n }\n card.append(summary);\n const urlrow = document.createElement(\"p\");\n urlrow.textContent = `url: ${call.url}${call.endpoint !== undefined ? ` \u00B7 endpoint ${call.endpoint}` : \"\"}${call.bodyexpired === true ? \" \u00B7 body expired from retention\" : \"\"}`;\n card.append(urlrow);\n const headersrow = document.createElement(\"p\");\n headersrow.textContent = `request header names: ${call.headernames.length > 0 ? call.headernames.join(\", \") : \"none\"} (values never persist)`;\n card.append(headersrow);\n if ((call.fields ?? []).length > 0) {\n const fieldstitle = document.createElement(\"p\");\n fieldstitle.textContent = `parsed fields: ${(call.fields ?? []).length}`;\n card.append(fieldstitle);\n for (const field of call.fields ?? []) {\n const fieldrow = document.createElement(\"p\");\n fieldrow.textContent = `${field.name} (${field.kind}) from ${field.path}: ${field.missing === true ? \"miss filled by the reviewed default\" : JSON.stringify(field.value)}`;\n card.append(fieldrow);\n }\n }\n if (call.streambytes !== undefined) {\n const streamrow = document.createElement(\"p\");\n streamrow.textContent = `streamed ${call.streambytes} bytes of the response body`;\n card.append(streamrow);\n const gauge = document.createElement(\"progress\");\n gauge.max = Math.max(call.streambytes, call.bytes);\n gauge.value = call.streambytes;\n card.append(gauge);\n }\n for (const error of call.errors ?? []) {\n const errorrow = document.createElement(\"p\");\n errorrow.className = \"diffrow.removed\";\n errorrow.textContent = `error of step ${call.stepid}: ${error}`;\n card.append(errorrow);\n }\n list.append(card);\n }\n };\n originfilter.addEventListener(\"input\", applyfilters);\n methodfilter.addEventListener(\"input\", applyfilters);\n classfilter.addEventListener(\"input\", applyfilters);\n applyfilters();\n callsroot.append(list);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Export ${callsmeta.length} call${callsmeta.length === 1 ? \"\" : \"s\"}`, () => request({ kind: \"exportcalls\" }).then(() => status(`Exported ${callsmeta.length} call record${callsmeta.length === 1 ? \"\" : \"s\"} through the reviewed download flow.`)).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n if (active) {\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"call body retention (records)\";\n retentioninput.value = context.callretention !== undefined ? String(context.callretention) : \"\";\n retentioninput.setAttribute(\"aria-label\", \"call body retention window\");\n const retentionbutton = button(\"Save call retention\", () => request({ kind: \"setcallretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Call body retention saved as ${retentioninput.value === \"\" ? \"keep every body\" : retentioninput.value} records; metadata always survives.`)).then(refresh));\n actions.append(retentioninput, retentionbutton);\n }\n callsroot.append(actions);\n}\n\n\n/** Renders the network view: every observed exchange of the run with method, url, status, size and duration, expandable redacted headers and a body preview, failed requests with an error class badge, grouping by correlation id, the live channel state with message counters, the event stream subscriptions with event names, the poll loops with cursor values and stop conditions, the webrequest grant toggle and the netlog export. */\nfunction rendernetview(context: { session?: { stoppedat?: number; expiresat: number }; exchanges?: Array<{ id: string; runid: string; stepid: string; correlationid: string; url: string; origin: string; method: string; status: number; statusclass: string; errorclass?: string; source: string; timing: number; bytes: number; mime?: string; bodyref?: string; bodyexpired?: boolean; requestheaders?: Record<string, string>; responseheaders?: Record<string, string> }>; channels?: Array<{ id: string; kind: string; url: string; origin: string; state: string; sent: number; received: number; reconnects: number; lasteventid?: string }>; subscriptions?: Array<{ id: string; url: string; origin: string; state: string; events: number; names: string[]; lasteventid?: string; cancel: { kind: string; value: string | number } }>; apimap?: Array<{ endpoint: string; method: string; mime: string; frequency: number; jsonshare: number; stability: number; origin: string; payloadshape: string[] }>; progress?: planprogress; webrequestgrant?: boolean; bodyretention?: number; socketsactive?: number; activerules?: number; traffic?: { blocks: Array<{ id: string; urlpattern: string; hits: number; revertedat?: number; stepid: string }>; mocks: Array<{ id: string; urlpattern: string; status: number; hits: number; revertedat?: number }>; rewrites: Array<{ id: string; urlpattern: string; name: string; operation: string; value?: string; hits: number; revertedat?: number }>; cookies: Array<{ id: string; kind: string; domain: string; names: string[]; at: number }>; proxies: Array<{ id: string; scheme: string; host: string; port: number; bypass: string[]; appliedat: number; revertedat?: number }>; ratelimits: Array<{ origin: string; remaining?: number; limit?: number; resetat: number }> }; tokens?: { tokens: Array<{ id: string; provider: string; origin: string; scopes: string[]; expiresat: number; refreshedat?: number; revokedat?: number }> }; authflows?: Array<{ provider: string; redirectorigin: string; scopes: string[]; stepid: string; tabid: number; stage: string }> }): void {\n if (!netviewroot) return;\n netviewroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const grantcard = document.createElement(\"div\");\n grantcard.className = \"panel\";\n const grantrow = document.createElement(\"p\");\n grantrow.textContent = `request watching: ${context.webrequestgrant === true ? \"granted\" : \"not granted\"} \u2014 the observation derives from the page timing buffers and adds no manifest permission.`;\n grantcard.append(grantrow);\n if (active) {\n const grantactions = document.createElement(\"div\");\n grantactions.className = \"actions\";\n grantactions.append(button(context.webrequestgrant === true ? \"Revoke request watching\" : \"Grant request watching\", () => request({ kind: \"setwebrequestgrant\", granted: context.webrequestgrant !== true }).then(() => status(context.webrequestgrant === true ? \"Request watching revoked.\" : \"Request watching granted; watchrequests steps can run now.\")).then(refresh)));\n grantcard.append(grantactions);\n }\n netviewroot.append(grantcard);\n const channels = context.channels ?? [];\n const subscriptions = context.subscriptions ?? [];\n if (channels.length > 0 || subscriptions.length > 0 || (context.socketsactive ?? 0) > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `live channels: ${channels.length} websocket channel${channels.length === 1 ? \"\" : \"s\"} \u00B7 ${subscriptions.length} event stream${subscriptions.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const channel of channels) {\n const row = document.createElement(\"p\");\n row.textContent = `${channel.kind} ${channel.state} \u00B7 ${channel.origin} \u00B7 ${channel.sent} sent \u00B7 ${channel.received} received \u00B7 ${channel.reconnects} reconnect${channel.reconnects === 1 ? \"\" : \"s\"}${channel.lasteventid !== undefined ? ` \u00B7 last event ${channel.lasteventid}` : \"\"}`;\n card.append(row);\n if (channel.state === \"open\" || channel.state === \"connecting\") {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Close ${channel.id}`, () => request({ kind: \"closesocket\", id: channel.id }).then(() => status(`Channel ${channel.id} closed cleanly.`)).then(refresh)));\n card.append(actions);\n }\n }\n for (const subscription of subscriptions) {\n const row = document.createElement(\"p\");\n row.textContent = `sse ${subscription.state} \u00B7 ${subscription.origin} \u00B7 ${subscription.events} event${subscription.events === 1 ? \"\" : \"s\"}${subscription.names.length > 0 ? ` (${subscription.names.slice(0, 4).join(\", \")}${subscription.names.length > 4 ? \"\u2026\" : \"\"})` : \"\"}${subscription.lasteventid !== undefined ? ` \u00B7 resume at ${subscription.lasteventid}` : \"\"} \u00B7 cancel on ${subscription.cancel.kind}`;\n card.append(row);\n }\n netviewroot.append(card);\n }\n const pollevidence = (context.progress?.outcomes ?? []).filter(outcome => outcome.details?.poll !== undefined).map(outcome => outcome.details?.poll as { poll: number; cursor?: string; status: number; stopped: boolean; reason: string });\n if (pollevidence.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `poll loops: ${pollevidence.length} iteration${pollevidence.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const poll of pollevidence.slice(0, 8)) {\n const row = document.createElement(\"p\");\n row.textContent = `poll ${poll.poll} \u00B7 status ${poll.status}${poll.cursor !== undefined ? ` \u00B7 cursor ${poll.cursor}` : \"\"} \u00B7 ${poll.stopped ? `stopped: ${poll.reason}` : \"continuing\"}`;\n card.append(row);\n }\n card.append(document.createRange().createContextualFragment(\"\"));\n netviewroot.append(card);\n }\n const exchanges = context.exchanges ?? [];\n const list = document.createElement(\"div\");\n if (exchanges.length === 0) { list.textContent = \"No request of the run has been observed yet; grant request watching and run a watchrequests step.\"; }\n for (const exchange of exchanges) {\n const card = document.createElement(\"details\");\n card.className = \"panel callcard\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `${exchange.method} ${exchange.status} ${exchange.statusclass} \u00B7 ${new URL(exchange.url).host} \u00B7 ${exchange.bytes} bytes \u00B7 ${exchange.timing} ms \u00B7 correlation ${exchange.correlationid} \u00B7 ${exchange.source === \"page\" ? \"derived\" : \"captured\"}`;\n if (exchange.errorclass !== undefined) {\n const badge = document.createElement(\"span\");\n badge.className = \"credentialbadge\";\n badge.textContent = ` ${exchange.errorclass} `;\n summary.append(badge);\n }\n card.append(summary);\n const urlrow = document.createElement(\"p\");\n urlrow.textContent = `url: ${exchange.url}${exchange.mime !== undefined ? ` \u00B7 ${exchange.mime}` : \"\"}${exchange.bodyref !== undefined ? ` \u00B7 body ${exchange.bodyref}` : \"\"}${exchange.bodyexpired === true ? \" \u00B7 body expired from retention\" : \"\"}`;\n card.append(urlrow);\n const requestheadernames = Object.keys(exchange.requestheaders ?? {});\n if (requestheadernames.length > 0 || Object.keys(exchange.responseheaders ?? {}).length > 0) {\n const headersrow = document.createElement(\"p\");\n headersrow.textContent = `stored headers (redacted on the redaction list): request ${requestheadernames.length > 0 ? requestheadernames.join(\", \") : \"none\"} \u00B7 response ${Object.keys(exchange.responseheaders ?? {}).join(\", \") || \"none\"}`;\n card.append(headersrow);\n } else {\n const headersrow = document.createElement(\"p\");\n headersrow.className = \"muted\";\n headersrow.textContent = \"no captured headers: derived page exchanges expose no header names through the timing buffers.\";\n card.append(headersrow);\n }\n if (exchange.bodyref !== undefined && exchange.bodyexpired !== true) {\n const bodyrow = document.createElement(\"p\");\n bodyrow.textContent = `captured body ${exchange.bodyref}`;\n card.append(bodyrow);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Preview body ${exchange.bodyref}`, () => request({ kind: \"exchangebody\", ref: exchange.bodyref }).then(value => {\n const record = value as { body: string; mime: string; bytes: number };\n bodyrow.textContent = `captured body ${exchange.bodyref} of ${record.mime} and ${record.bytes} bytes: ${record.body.slice(0, 400)}${record.body.length > 400 ? \"\u2026 (display preview truncates; the stored body keeps every byte)\" : \"\"}`;\n }).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n card.append(actions);\n }\n list.append(card);\n }\n netviewroot.append(list);\n const apimap = context.apimap ?? [];\n if (apimap.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `page api map: ${apimap.length} ranked endpoint${apimap.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const entry of apimap.slice(0, 10)) {\n const row = document.createElement(\"p\");\n row.textContent = `${entry.method} ${entry.endpoint} \u00B7 ${entry.frequency} call${entry.frequency === 1 ? \"\" : \"s\"} \u00B7 json ${Math.round(entry.jsonshare * 100)}% \u00B7 stable ${Math.round(entry.stability * 100)}%${entry.payloadshape.length > 0 ? ` \u00B7 ${entry.payloadshape.slice(0, 5).join(\", \")}` : \"\"}`;\n card.append(row);\n }\n netviewroot.append(card);\n }\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Export netlog (${exchanges.length} exchange${exchanges.length === 1 ? \"\" : \"s\"})`, () => request({ kind: \"exportnetlog\" }).then(() => status(\"Exported the captured run log through the reviewed download flow.\")).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n if (active) {\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"captured body retention (records)\";\n retentioninput.value = context.bodyretention !== undefined ? String(context.bodyretention) : \"\";\n retentioninput.setAttribute(\"aria-label\", \"captured body retention window\");\n actions.append(retentioninput, button(\"Save body retention\", () => request({ kind: \"setbodyretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Captured body retention saved as ${retentioninput.value === \"\" ? \"keep every body\" : retentioninput.value} records; exchange metadata always survives.`)).then(refresh)));\n }\n netviewroot.append(actions);\n}\n\nfunction rendercapabilities(report?: capabilityreport): void {\n if (!capabilitiestext) return;\n if (!report) { capabilitiestext.textContent = \"Optional capabilities unknown.\"; return; }\n capabilitiestext.textContent = `tabs ${report.tabs ? \"granted\" : \"absent\"} \u00B7 downloads ${report.downloads ? \"granted\" : \"absent\"} \u00B7 clipboard read ${report.clipboardread ? \"granted\" : \"absent\"} \u00B7 clipboard write ${report.clipboardwrite ? \"granted\" : \"absent\"}`;\n}\n\nfunction renderaudit(events: auditevent[]): void { if (!auditroot) return; auditroot.replaceChildren(); for (const event of events.slice(0, 12)) { const item = document.createElement(\"li\"); item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 ${event.kind} \u00B7 ${event.summary}`; auditroot.append(item); } }\nfunction renderdiagnostic(report?: diagnosticreport): void { if (!diagnosticroot) return; diagnosticroot.replaceChildren(); if (!report) { diagnosticroot.textContent = \"Run a local diagnostic after starting a session to record bridge and page-shape health.\"; return; } const values = [`origin: ${report.origin}`, `title: ${report.title || \"untitled\"}`, `interactive elements: ${report.interactivecount}`, `forms: ${report.formcount}`, `page text length: ${report.textlength}`, `bridge available: ${report.bridgeavailable ? \"yes\" : \"no\"}`]; for (const value of values) { const item = document.createElement(\"li\"); item.textContent = value; diagnosticroot.append(item); } }\n/** Renders the run timeline view: console capture consent prompts, level, source and step filters, entries with spam collapse counts and step markers, errors expanded into their stack frames, long task bars beside their steps and the level count summary with the retention setting. */\nfunction rendertimeline(context: { plan?: agentplan; timeline?: { entries: timelineentry[]; errors: errorrecord[]; rejections: rejectionrecord[]; longtasks: longtaskentry[]; levelcounts: Record<string, number> }; consoleconsents?: consoleconsentrecord[]; timelineretention?: number; levelsummaries?: Array<{ runid: string; counts: Record<string, number>; at: number }>; rotationtargets?: Array<{ target: string; runid: string; entries: number; at: number }> }): void {\n if (!timelineroot) return;\n timelineroot.replaceChildren();\n const waiting = (context.consoleconsents ?? []).filter(consent => consent.approved === undefined);\n for (const consent of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Console capture consent: ${consent.prompt}`;\n card.append(prompt, button(\"Approve console capture\", () => request({ kind: \"approveconsoleconsent\", id: consent.id }).then(() => status(`Console capture on ${consent.origin} approved; run the watchconsole step again.`)).then(refresh)));\n timelineroot.append(card);\n }\n const entries = context.timeline?.entries ?? [];\n const errors = context.timeline?.errors ?? [];\n const rejections = context.timeline?.rejections ?? [];\n const longtasks = context.timeline?.longtasks ?? [];\n if (entries.length === 0 && errors.length === 0 && rejections.length === 0 && longtasks.length === 0) { timelineroot.textContent = \"Run watchconsole, watcherrors or watchtasks steps to fill the run timeline.\"; return; }\n const levels = [\"error\", \"warn\", \"info\", \"log\", \"debug\", \"trace\"] as const;\n const sources = [\"console\", \"error\", \"rejection\", \"resource\", \"longtask\", \"network\"] as const;\n const filters = document.createElement(\"div\");\n filters.className = \"actions\";\n for (const level of levels) filters.append(button(timelinefilter.level === level ? `level ${level} \u2713` : `level ${level}`, async () => { timelinefilter.level = timelinefilter.level === level ? \"\" : level; await refresh(); }));\n for (const source of sources) filters.append(button(timelinefilter.source === source ? `source ${source} \u2713` : `source ${source}`, async () => { timelinefilter.source = timelinefilter.source === source ? \"\" : source; await refresh(); }));\n timelineroot.append(filters);\n const stepids = [...new Set(entries.map(entry => entry.stepid))];\n if (stepids.length > 1) {\n const select = document.createElement(\"select\");\n select.style.width = \"100%\";\n const any = document.createElement(\"option\");\n any.value = \"\";\n any.textContent = \"every step\";\n select.append(any);\n for (const stepid of stepids) {\n const option = document.createElement(\"option\");\n option.value = stepid;\n option.textContent = `step ${stepid}`;\n if (timelinefilter.stepid === stepid) option.selected = true;\n select.append(option);\n }\n select.addEventListener(\"change\", () => { timelinefilter.stepid = select.value; void refresh(); });\n timelineroot.append(select);\n }\n const shown = entries.filter(entry => (timelinefilter.level === \"\" || entry.level === timelinefilter.level) && (timelinefilter.source === \"\" || entry.source === timelinefilter.source) && (timelinefilter.stepid === \"\" || entry.stepid === timelinefilter.stepid)).slice().reverse().slice(0, 60);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const entry of shown) {\n const item = document.createElement(\"li\");\n item.className = \"timelinerow\";\n item.dataset.level = entry.level;\n const head = document.createElement(\"p\");\n head.className = \"timeline\";\n head.textContent = `${new Date(entry.time).toLocaleTimeString()} \u00B7 ${entry.level} \u00B7 ${entry.source} \u00B7 step ${entry.stepid}${entry.repeat !== undefined && entry.repeat > 1 ? ` \u00B7 collapsed \u00D7${entry.repeat}` : \"\"}`;\n const message = document.createElement(\"p\");\n message.textContent = entry.message;\n item.append(head, message);\n if (entry.level === \"error\" && (entry.source === \"error\" || entry.source === \"rejection\")) {\n const record = entry.source === \"error\" ? errors.find(candidate => candidate.stepid === entry.stepid && candidate.message === entry.message) : rejections.find(candidate => candidate.stepid === entry.stepid && candidate.reason === entry.message);\n const frames = record && \"frames\" in record ? record.frames : [];\n if (frames.length > 0) {\n const expand = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = `${frames.length} stack frame${frames.length === 1 ? \"\" : \"s\"}`;\n const pre = document.createElement(\"pre\");\n pre.textContent = frames.map(frame => `at ${frame.functionname ?? \"<anonymous>\"} (${frame.url}:${frame.line}${frame.column !== undefined ? `:${frame.column}` : \"\"})`).join(\"\\n\");\n expand.append(summary, pre);\n item.append(expand);\n }\n }\n list.append(item);\n }\n timelineroot.append(list);\n const maxtask = longtasks.reduce((max, task) => Math.max(max, task.duration), 0);\n for (const task of longtasks.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `long task \u00B7 ${task.duration} ms${task.attributions.length > 0 ? ` \u00B7 ${task.attributions.join(\", \")}` : \"\"} \u00B7 step ${task.stepid}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = maxtask > 0 ? `${Math.round((task.duration / maxtask) * 100)}%` : \"0%\";\n gauge.append(fill);\n bar.append(label, gauge);\n timelineroot.append(bar);\n }\n const counts = context.timeline?.levelcounts ?? {};\n const summaryline = document.createElement(\"p\");\n summaryline.className = \"muted\";\n const expired = (context.levelsummaries ?? []).reduce((total, item) => total + Object.values(item.counts).reduce((sum, count) => sum + count, 0), 0);\n summaryline.textContent = `${entries.length} live entr${entries.length === 1 ? \"y\" : \"ies\"} (${levels.map(level => `${counts[level] ?? 0} ${level}`).join(\" \u00B7 \")})${expired > 0 ? ` \u00B7 ${expired} expired into level summaries` : \"\"}${(context.rotationtargets ?? []).length > 0 ? ` \u00B7 ${(context.rotationtargets ?? []).reduce((total, target) => total + target.entries, 0)} rotated to overflow stores` : \"\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.type = \"number\";\n retentioninput.min = \"0\";\n retentioninput.placeholder = \"timeline retention\";\n retentioninput.value = context.timelineretention !== undefined ? String(context.timelineretention) : \"\";\n timelineroot.append(summaryline, retentioninput, button(\"Save timeline retention\", () => request({ kind: \"settimelineretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Timeline retention saved as ${retentioninput.value === \"\" ? \"keep every entry\" : retentioninput.value} entries; level count summaries always survive.`)).then(refresh)));\n}\n\n/** Renders the console diff view: two run id fields, the compare action and the added, removed and repeated lines of the compared console outputs. */\nfunction renderconsolediff(): void {\n if (!consolediffroot) return;\n consolediffroot.replaceChildren();\n const baseinput = document.createElement(\"input\");\n baseinput.placeholder = \"base run id\";\n const targetinput = document.createElement(\"input\");\n targetinput.placeholder = \"target run id\";\n consolediffroot.append(baseinput, targetinput, button(\"Compare console output\", () => request({ kind: \"consolediff\", base: baseinput.value, target: targetinput.value }).then(value => {\n const parsed = value as { diff: consolediff };\n if (!parsed) throw new Error(\"The console diff returned no result.\");\n lastdiff = parsed.diff;\n status(`Diffed runs ${parsed.diff.base} and ${parsed.diff.target}: ${parsed.diff.added} added, ${parsed.diff.removed} removed and ${parsed.diff.repeated} repeated line${parsed.diff.added + parsed.diff.removed + parsed.diff.repeated === 1 ? \"\" : \"s\"}.`);\n renderconsolediff();\n })));\n if (!lastdiff) { const hint = document.createElement(\"p\"); hint.className = \"muted\"; hint.textContent = \"Compare the console output of two runs to see added, removed and repeated lines.\"; consolediffroot.append(hint); return; }\n const headline = document.createElement(\"p\");\n headline.className = \"muted\";\n headline.textContent = `Run ${lastdiff.base} became run ${lastdiff.target}: ${lastdiff.added} added, ${lastdiff.removed} removed and ${lastdiff.repeated} repeated.`;\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const line of lastdiff.lines.slice(0, 80)) {\n const item = document.createElement(\"li\");\n item.className = `diffrow ${line.kind}`;\n item.textContent = `${line.kind}${line.count !== undefined ? ` \u00D7${line.count}` : \"\"}: ${line.text}`;\n list.append(item);\n }\n consolediffroot.append(headline, list);\n}\n\n/** Renders the debugger view: the debugger consent prompts with the domain allowlist shown, the session state with its domains and honest derivation, the sent commands with durations and results, the breakpoints with hit counts and conditions, the pause banner with call frames, the watch expression values per pause, the script override list with revert controls and the domain event counts streamed beside the run timeline. */\nfunction renderdebugger(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number; origin?: string }; cdpsessions?: Array<{ id: string; runid: string; tabid: number; origin: string; attachedat: number; domains: string[]; debuggerversion: string; detachedat?: number; userdetached?: boolean }>; cdpcommands?: Array<{ id: string; sessionid: string; method: string; domain: string; duration: number; errorclass?: string; at: number }>; cdpeventrules?: Array<{ id: string; domain: string; event: string; events: number; closedat?: number; match?: string }>; breakpoints?: Array<{ id: string; runid: string; url: string; line: number; column?: number; condition?: string; hits: number; revertedat?: number }>; pauses?: Array<{ id: string; runid: string; stepid: string; reason: string; callframes: Array<{ functionname?: string; url: string; line: number; column?: number }>; hitbreakpoint?: string; domsnapshotid?: string; at: number; framesexpired?: boolean }>; watchexpressions?: Array<{ id: string; expression: string; scope: string; values: Array<{ pauseid: string; value: string; at: number }>; reviewed: boolean }>; scriptoverrides?: Array<{ id: string; urlpattern: string; hits: number; appliedat: number; revertedat?: number; reviewed: boolean }>; debuggergrants?: Array<{ id: string; origin: string; domains: string[]; approved?: boolean; consentedat: number; revokedat?: number }>; pauseretention?: number; breakpointceiling?: number; cdpattached?: number }): void {\n if (!debuggerroot) return;\n debuggerroot.replaceChildren();\n const waiting = (context.debuggergrants ?? []).filter(grant => grant.approved === undefined && grant.revokedat === undefined);\n for (const grant of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Debugger attach on ${grant.origin} waits for your consent with the domain allowlist ${grant.domains.join(\", \")} shown.`;\n card.append(prompt, button(\"Approve debugger consent\", () => request({ kind: \"approvedebuggerconsent\", id: grant.id }).then(() => status(`Debugger consent on ${grant.origin} approved for ${grant.domains.join(\", \")}; run the attachcdp step again.`)).then(refresh)));\n debuggerroot.append(card);\n }\n const granted = (context.debuggergrants ?? []).filter(grant => grant.approved === true && grant.revokedat === undefined);\n if (granted.length > 0) debuggerroot.append(button(\"Detach debugger now\", () => request({ kind: \"revokedebuggerconsent\" }).then(value => { const parsed = value as { revoked: number; paused: boolean }; status(`Detached the debugger: ${parsed.revoked} consent record${parsed.revoked === 1 ? \"\" : \"s\"} revoked, every breakpoint and override reverted and the run paused for review.`); return refresh(); })));\n const sessions = context.cdpsessions ?? [];\n const attached = sessions.filter(session => session.detachedat === undefined);\n const sessionline = document.createElement(\"p\");\n sessionline.className = \"muted\";\n sessionline.textContent = attached.length === 0\n ? \"No devtools session is attached; run the attachcdp step behind the reviewed debugger consent.\"\n : `${attached.length} attached devtools session${attached.length === 1 ? \"\" : \"s\"}${attached[0] !== undefined ? ` of ${attached[0].origin} with the domains ${attached[0].domains.join(\", \")} enabled through ${attached[0].debuggerversion}` : \"\"}.`;\n debuggerroot.append(sessionline);\n const lastpause = (context.pauses ?? [])[0];\n if (lastpause !== undefined && context.cdpattached !== 0) {\n const banner = document.createElement(\"div\");\n banner.className = \"bannercard\";\n const head = document.createElement(\"p\");\n head.textContent = `Paused on ${lastpause.reason}${lastpause.hitbreakpoint !== undefined ? ` at breakpoint ${lastpause.hitbreakpoint}` : \"\"}${lastpause.domsnapshotid !== undefined ? ` with dom snapshot ${lastpause.domsnapshotid}` : \"\"}.`;\n banner.append(head);\n if (lastpause.framesexpired === true) {\n const expired = document.createElement(\"p\");\n expired.textContent = \"The call frames expired from the pause retention window; the pause reason and hit breakpoint survive.\";\n banner.append(expired);\n } else {\n for (const frame of lastpause.callframes.slice(0, 6)) {\n const row = document.createElement(\"p\");\n row.textContent = `${frame.functionname ?? \"anonymous\"} ${frame.url}:${frame.line}${frame.column !== undefined ? `:${frame.column}` : \"\"}`;\n banner.append(row);\n }\n }\n debuggerroot.append(banner);\n }\n const commands = context.cdpcommands ?? [];\n if (commands.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Raw protocol commands\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const command of commands.slice(0, 12)) {\n const item = document.createElement(\"li\");\n const badge = document.createElement(\"span\");\n badge.className = \"protocolbadge\";\n badge.textContent = \"raw protocol\";\n item.append(`${command.method} \u00B7 ${command.duration} ms${command.errorclass !== undefined ? ` \u00B7 ${command.errorclass}` : \"\"} \u00B7 session ${command.sessionid.slice(0, 8)}`, badge);\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const breakpoints = (context.breakpoints ?? []).filter(spec => spec.revertedat === undefined);\n if (breakpoints.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Breakpoints\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const spec of breakpoints) {\n const item = document.createElement(\"li\");\n item.textContent = `${spec.url}:${spec.line}${spec.column !== undefined ? `:${spec.column}` : \"\"} \u00B7 ${spec.hits} hit${spec.hits === 1 ? \"\" : \"s\"}${spec.condition !== undefined ? ` \u00B7 condition ${spec.condition}` : \"\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const watches = context.watchexpressions ?? [];\n if (watches.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Watch expressions\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const watch of watches) {\n const item = document.createElement(\"li\");\n const values = watch.values.slice(-4).map(value => `${value.value} @${value.pauseid.slice(0, 6)}`).join(\" \u00B7 \");\n item.textContent = `${watch.expression} (${watch.scope} scope${watch.reviewed ? \", reviewed\" : \"\"})${values ? `: ${values}` : \": no value captured yet\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const overrides = context.scriptoverrides ?? [];\n if (overrides.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Script overrides\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const spec of overrides) {\n const item = document.createElement(\"li\");\n item.textContent = `${spec.urlpattern} \u00B7 ${spec.hits} applied evaluation${spec.hits === 1 ? \"\" : \"s\"}${spec.reviewed ? \" \u00B7 reviewed fixture\" : \"\"}${spec.revertedat !== undefined ? \" \u00B7 reverted\" : \" \u00B7 active\"}`;\n if (spec.revertedat === undefined) item.append(button(\"Revert fixture\", () => request({ kind: \"revertcdpoverride\", id: spec.id }).then(() => status(`Reverted the script override of ${spec.urlpattern}; later evaluations run the original source again.`)).then(refresh)));\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const rules = context.cdpeventrules ?? [];\n if (rules.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Domain events beside the timeline\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const rule of rules.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${rule.domain}.${rule.event}${rule.match !== undefined ? ` matching ${rule.match}` : \"\"} \u00B7 ${rule.events} matched event${rule.events === 1 ? \"\" : \"s\"}${rule.closedat !== undefined ? \" \u00B7 closed\" : \"\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const settingsline = document.createElement(\"p\");\n settingsline.className = \"muted\";\n settingsline.textContent = `Pause retention ${context.pauseretention ?? \"keeps every capture\"} \u00B7 breakpoint ceiling ${context.breakpointceiling ?? \"none\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"pause retention\";\n retentioninput.value = context.pauseretention !== undefined ? String(context.pauseretention) : \"\";\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.placeholder = \"breakpoint ceiling\";\n ceilinginput.value = context.breakpointceiling !== undefined ? String(context.breakpointceiling) : \"\";\n debuggerroot.append(settingsline, retentioninput, ceilinginput, button(\"Save debugger settings\", () => Promise.all([request({ kind: \"setpauseretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }), request({ kind: \"setbreakpointceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) })]).then(() => status(`Debugger settings saved: pause retention ${retentioninput.value === \"\" ? \"keeps every capture\" : retentioninput.value} and breakpoint ceiling ${ceilinginput.value === \"\" ? \"none\" : ceilinginput.value}.`)).then(refresh)));\n}\n\n/** Renders the emulation view: the pending location consent prompts with their coordinates, the active layers per run with their revert plans and the manual revert button, the stacking warning when layers pile on one tab, the offline note when a network layer cuts the traffic, the user curated preset libraries with the preset editor, the blackbox patterns of the current run, the permission override history with restore states, the import and export of preset files through review and the restore of the stored state after a crash. */\nfunction renderemulation(context: { plan?: agentplan; session?: { stoppedat?: number; expiresat: number; origin?: string }; emulation?: { layers: Array<{ id: string; runid: string; stepid: string; family: string; name: string; originscope: string; appliedat: number; revertedat?: number; revertplan: string[] }>; devices: Array<{ name: string; width: number; height: number; pixelratio: number; mobile: boolean }>; networks: Array<{ name: string; latency: number; download: number; upload: number; offline: boolean }>; locations: Array<{ name: string; latitude: number; longitude: number; accuracy: number }>; agents: Array<{ name: string; useragent: string; platform: string; brands: string[] }>; blackbox: Array<{ origin: string; rules: Array<{ urlpatterns: string[]; tracescope: string }> }>; permissions: Array<{ id: string; runid: string; origin: string; name: string; state: string; priorstate: string; appliedat: number; restoredat?: number }>; consents: Array<{ id: string; origin: string; latitude: number; longitude: number; approved?: boolean; consentedat: number; revokedat?: number }> }; emulatedlayers?: string[]; emulationretention?: number }): void {\n if (!emulationroot) return;\n emulationroot.replaceChildren();\n const emulation = context.emulation;\n if (!emulation) { emulationroot.textContent = \"No emulation state is available yet; start a session and review a plan with emulation steps.\"; return; }\n const pending = emulation.consents.filter(consent => consent.approved === undefined && consent.revokedat === undefined);\n for (const consent of pending) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `Location consent needed on ${consent.origin}`;\n const coordinates = document.createElement(\"p\");\n coordinates.textContent = `Reviewed coordinates: ${consent.latitude}, ${consent.longitude}; the override applies through a page-injected geolocation mask and the true browser location stays untouched.`;\n card.append(title, coordinates, button(\"Approve location consent\", () => request({ kind: \"approvelocationconsent\", id: consent.id }).then(() => { status(`Approved the location consent for ${consent.latitude}, ${consent.longitude} on ${consent.origin}.`); return refresh(); })));\n emulationroot.append(card);\n }\n const active = emulation.layers.filter(layer => layer.revertedat === undefined);\n const state = document.createElement(\"p\");\n state.textContent = `${active.length} active emulation layer${active.length === 1 ? \"\" : \"s\"} of run ${active[0]?.runid ?? \"none\"}${active.length > 1 ? \"; the last applied layer wins conflicts\" : \"\"}.`;\n emulationroot.append(state);\n if (active.length > 1) {\n const warn = document.createElement(\"p\");\n warn.textContent = `Warning: ${active.length} layers stack on one tab (${active.map(layer => layer.name).join(\", \")}); every mask reverts at run end in reverse order.`;\n warn.className = \"muted\";\n emulationroot.append(warn);\n }\n const offlinelayer = active.find(layer => layer.family === \"network\" && emulation.networks.some(preset => preset.name === layer.name && preset.offline));\n if (offlinelayer !== undefined) {\n const offline = document.createElement(\"p\");\n offline.textContent = `Offline: the network layer ${offlinelayer.name} cuts the traffic the extension initiates; page traffic stays observed only.`;\n offline.className = \"muted\";\n emulationroot.append(offline);\n }\n for (const layer of active) {\n const row = document.createElement(\"div\");\n row.className = \"emulationrow\";\n row.dataset.stacked = active.length > 1 ? \"true\" : \"false\";\n const line = document.createElement(\"p\");\n line.textContent = `${layer.family} layer ${layer.name} on ${layer.originscope} applied ${new Date(layer.appliedat).toLocaleTimeString()} with the revert plan ${layer.revertplan.join(\", \")}.`;\n row.append(line, button(\"Revert now\", () => request({ kind: \"revertemulation\" }).then(() => { status(\"Reverted every active emulation layer of the run on review panel demand.\"); return refresh(); })));\n emulationroot.append(row);\n }\n if (active.length > 0) {\n emulationroot.append(button(\"Restore stored layers after a crash\", () => request({ kind: \"restoreemulation\" }).then(() => { status(\"Restored the stored emulation layers of the run record.\"); return refresh(); })));\n }\n const families: Array<{ label: string; presets: Array<{ label: string; kind: string }> }> = [\n { label: \"device presets\", presets: emulation.devices.map(preset => ({ label: `${preset.name}: ${preset.width}x${preset.height} @${preset.pixelratio}${preset.mobile ? \" mobile\" : \"\"}`, kind: \"device\" })) },\n { label: \"network presets\", presets: emulation.networks.map(preset => ({ label: `${preset.name}: ${preset.latency}ms, ${preset.download}/${preset.upload} kbps${preset.offline ? \", offline\" : \"\"}`, kind: \"network\" })) },\n { label: \"location presets\", presets: emulation.locations.map(preset => ({ label: `${preset.name}: ${preset.latitude}, ${preset.longitude} \u00B1${preset.accuracy}m`, kind: \"location\" })) },\n { label: \"agent presets\", presets: emulation.agents.map(preset => ({ label: `${preset.name}: ${preset.platform} with ${preset.brands.length} brands`, kind: \"agent\" })) },\n ];\n for (const family of families) {\n const head = document.createElement(\"h4\");\n head.textContent = family.label;\n emulationroot.append(head);\n if (family.presets.length === 0) {\n const empty = document.createElement(\"p\");\n empty.className = \"muted\";\n empty.textContent = \"No user curated preset yet; the library stays user data instead of a hardcoded list.\";\n emulationroot.append(empty);\n continue;\n }\n for (const preset of family.presets) {\n const line = document.createElement(\"p\");\n line.textContent = preset.label;\n emulationroot.append(line);\n }\n }\n const editor = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = \"Preset editor\";\n editor.append(summary);\n const nameinput = document.createElement(\"input\");\n nameinput.placeholder = \"preset name\";\n const valueinput = document.createElement(\"input\");\n valueinput.placeholder = 'preset json, for example {\"name\":\"phone\",\"width\":390,\"height\":844,\"pixelratio\":3,\"mobile\":true}';\n const familyselect = document.createElement(\"select\");\n for (const family of [\"device\", \"network\", \"location\", \"agent\"]) {\n const option = document.createElement(\"option\");\n option.value = family;\n option.textContent = family;\n familyselect.append(option);\n }\n editor.append(nameinput, valueinput, familyselect, button(\"Save preset\", async () => {\n let payload: unknown;\n try { payload = JSON.parse(valueinput.value); } catch { throw new Error(\"The preset payload must be reviewed JSON.\"); }\n if (payload && typeof payload === \"object\" && !Array.isArray(payload) && nameinput.value.trim()) payload = { ...(payload as Record<string, unknown>), name: nameinput.value.trim() };\n const kind = familyselect.value === \"device\" ? \"setdevicepreset\" : familyselect.value === \"network\" ? \"setnetworkpreset\" : familyselect.value === \"location\" ? \"setlocationpreset\" : \"setagentpreset\";\n const field = familyselect.value;\n await request({ kind, [field]: payload });\n status(`Stored the ${familyselect.value} preset in the user curated library.`);\n await refresh();\n }));\n const exportrow = document.createElement(\"div\");\n exportrow.className = \"actions\";\n exportrow.append(button(\"Export preset file\", () => request({ kind: \"exportpresets\" }).then(value => { const parsed = value as { exported: number }; status(`Exported ${parsed.exported} preset${parsed.exported === 1 ? \"\" : \"s\"} through the reviewed download flow.`); return refresh(); })));\n const importinput = document.createElement(\"input\");\n importinput.type = \"file\";\n importinput.accept = \"application/json\";\n importinput.addEventListener(\"change\", () => {\n const file = importinput.files?.[0];\n if (!file) return;\n void file.text().then(content => JSON.parse(content)).then(filevalue => request({ kind: \"importpresets\", file: filevalue })).then(value => { const parsed = value as { imported: number }; status(`Imported ${parsed.imported} reviewed preset${parsed.imported === 1 ? \"\" : \"s\"} into the library.`); return refresh(); }).catch(error => status(error instanceof Error ? error.message : String(error), true));\n });\n exportrow.append(importinput);\n editor.append(exportrow);\n emulationroot.append(editor);\n const blackbox = emulation.blackbox.filter(entry => entry.rules.length > 0);\n if (blackbox.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"blackboxed patterns of the run\";\n emulationroot.append(head);\n for (const entry of blackbox) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.origin}: ${entry.rules.flatMap(rule => rule.urlpatterns).join(\", \")} (${entry.rules.map(rule => rule.tracescope).join(\", \")} scope)`;\n emulationroot.append(line);\n }\n }\n const restored = emulation.permissions.filter(record => record.restoredat === undefined);\n if (restored.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"permission overrides pending restore\";\n emulationroot.append(head);\n for (const record of restored) {\n const line = document.createElement(\"p\");\n line.textContent = `${record.name} of ${record.origin} answered ${record.state} for run ${record.runid}; the prior ${record.priorstate} state restores at run end.`;\n emulationroot.append(line);\n }\n }\n const retentionrow = document.createElement(\"p\");\n retentionrow.className = \"muted\";\n retentionrow.textContent = `Reverted layer state retention: ${context.emulationretention === undefined ? \"keep every prior state\" : `${context.emulationretention} layer${context.emulationretention === 1 ? \"\" : \"s\"}`}; the layer history itself always survives.`;\n emulationroot.append(retentionrow);\n}\n\nasync function refresh(): Promise<void> { const context = await request({ kind: \"context\" }) as { plan?: agentplan; progress?: planprogress; diagnostic?: diagnosticreport; audit: auditevent[]; outcomes?: stepoutcome[]; capabilities?: capabilityreport; session?: { id: string; pausedat?: number; stoppedat?: number; expiresat: number; origin?: string }; map?: clickablemap; retries?: retryoutcome[]; a11y?: a11ycapture; reader?: readercapture; banners?: bannerreport[]; mutationevents?: mutationevent[]; focusevents?: focusevent[]; diffs?: snapshotdiff[]; selectors?: derivedselector[]; trail?: { trail: trailentry[] }; navrecords?: navrecord[]; ratestates?: ratelimitstate[]; safeties?: safetyverdict[]; curated?: curatedlist[]; waitprofiles?: waitprofilerecord[]; auths?: Array<{ origin: string; username: string; reviewedat: number }>; navcontrol?: navcontrol; navqueues?: navqueues; artifacts?: artifactrecord[]; tabs?: tabshape[]; windows?: windowshape[]; tabgroups?: tabgrouprecord[]; badges?: tabbadge[]; tabmetas?: tabmeta[]; clones?: Array<{ url: string; tabids: number[] }>; layouts?: tablayout[]; snapshots?: sessionsnapshot[]; closedtabs?: closedtab[]; tasktabgauge?: { used: number; ceiling?: number; over: boolean }; controltab?: controltabstate; profiles?: formprofile[]; tickets?: submitticket[]; wizards?: { wizards: wizardstate[]; picks: typeaheadpick[] }; picks?: typeaheadpick[]; errorreports?: errorreport[]; captchas?: captchahandoff[]; detections?: detectionrecord[]; codeentry?: boolean; datasets?: dataset[]; imports?: dataset[]; extractsessions?: extractsession[]; streams?: streamstate[]; exports?: Array<{ id: string; kind: string; name: string; rowcount: number; checksum: string; at: number }>; provenances?: provenancerecord[]; taskrules?: taskrules[]; sheetendpoints?: Array<{ endpoint: string; origin: string; configuredat: number; granted: boolean }>; downloads?: downloadrecord[]; mimefilters?: mimefilter[]; clipconsents?: clipboardconsentrecord[]; clips?: clipentry[]; netlogs?: netlogrecord[]; quarantines?: quarantineentry[]; capturecounters?: Array<{ taskid: string; counters: Record<string, number>; at: number }>; cleanuprules?: cleanuprule[]; cleanupruns?: cleanuprun[]; inventory?: artifactinventoryentry[]; scanhooks?: Array<{ scanner: string; endpoint: string; origin: string; configuredat: number; granted: boolean }>; captures?: Array<{ id: string; runid: string; stepid: string; kind: string; format: string; width: number; height: number; capturedat: number; name?: string; annotated?: boolean; target?: string; bytesexpired?: boolean }>; capturepairs?: shotpair[]; capturepolicy?: string; stitchprogress?: Array<{ stepid: string; done: number; total: number }>; media?: Array<{ id: string; runid: string; stepid: string; at: number; bytesexpired?: boolean } & Record<string, unknown>>; imagebatches?: Array<{ id: string; runid: string; stepid: string; images: Array<{ url: string; alt: string; width: number; height: number; bytes: number; mime: string }>; matched: number; downloaded: number; at: number }>; recordingconsents?: Array<{ id: string; prompt: string; origin: string; stepid: string; approved?: boolean; usedat?: number; at: number }>; recordingactive?: Array<{ id: string; kind: string; scope: string; startedat: number; stopat: number }>; recordingwindow?: number; calls?: Array<{ id: string; runid: string; stepid: string; kind: string; url: string; origin: string; method: string; status: number; statusclass: string; duration: number; retries: number; bytes: number; headernames: string[]; endpoint?: string; bodyexpired?: boolean; fields?: Array<{ name: string; path: string; kind: string; value?: unknown; missing?: boolean }>; errors?: string[]; streambytes?: number }>; fetchconsents?: Array<{ id: string; origin: string; headers: Array<{ name: string; value: string }>; approved?: boolean; expiresat: number; at: number }>; endpoints?: Array<{ name: string; method: string; url: string; version: number; headers?: Record<string, string>; schema?: { fields: Array<{ name: string; kind: string; required?: boolean; default?: string | number | boolean }> } }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; callretention?: number; fetchesactive?: number; exchanges?: Array<{ id: string; runid: string; stepid: string; correlationid: string; url: string; origin: string; method: string; status: number; statusclass: string; errorclass?: string; source: string; timing: number; bytes: number; mime?: string; bodyref?: string; bodyexpired?: boolean; requestheaders?: Record<string, string>; responseheaders?: Record<string, string> }>; channels?: Array<{ id: string; kind: string; url: string; origin: string; state: string; sent: number; received: number; reconnects: number; lasteventid?: string }>; subscriptions?: Array<{ id: string; url: string; origin: string; state: string; events: number; names: string[]; lasteventid?: string; cancel: { kind: string; value: string | number } }>; apimap?: Array<{ endpoint: string; method: string; mime: string; frequency: number; jsonshare: number; stability: number; origin: string; payloadshape: string[] }>; webrequestgrant?: boolean; bodyretention?: number; timelineretention?: number; timeline?: { entries: timelineentry[]; errors: errorrecord[]; rejections: rejectionrecord[]; longtasks: longtaskentry[]; levelcounts: Record<string, number> }; consoleconsents?: consoleconsentrecord[]; rotationtargets?: Array<{ target: string; runid: string; entries: number; at: number }>; levelsummaries?: Array<{ runid: string; counts: Record<string, number>; at: number }>; cdpsessions?: Array<{ id: string; runid: string; tabid: number; origin: string; attachedat: number; domains: string[]; debuggerversion: string; detachedat?: number; userdetached?: boolean }>; cdpcommands?: Array<{ id: string; sessionid: string; method: string; domain: string; duration: number; errorclass?: string; at: number }>; cdpeventrules?: Array<{ id: string; domain: string; event: string; events: number; closedat?: number; match?: string }>; breakpoints?: Array<{ id: string; runid: string; url: string; line: number; column?: number; condition?: string; hits: number; revertedat?: number }>; pauses?: Array<{ id: string; runid: string; stepid: string; reason: string; callframes: Array<{ functionname?: string; url: string; line: number; column?: number }>; hitbreakpoint?: string; domsnapshotid?: string; at: number; framesexpired?: boolean }>; watchexpressions?: Array<{ id: string; expression: string; scope: string; values: Array<{ pauseid: string; value: string; at: number }>; reviewed: boolean }>; scriptoverrides?: Array<{ id: string; urlpattern: string; hits: number; appliedat: number; revertedat?: number; reviewed: boolean }>; debuggergrants?: Array<{ id: string; origin: string; domains: string[]; approved?: boolean; consentedat: number; revokedat?: number }>; pauseretention?: number; breakpointceiling?: number; cdpattached?: number; socketsactive?: number; profileretention?: number; traceceiling?: number; profileactive?: number; profiletargets?: Array<{ kind: string; url: string; sessionid: string; attachedat: number }>; profile?: { flows: Array<{ id: string; runid: string; stepid: string; name: string; duration: number; steps: string[] }>; heaps: Array<{ id: string; runid: string; origin: string; bytesize: number; nodecount: number; capturedat: number; bytesexpired?: boolean }>; samples: Array<{ id: string; runid: string; stepid: string; usedbytes: number; limitbytes: number; at: number }>; trends: Array<{ runid: string; slope: number; samples: number; flaggedsteps: string[]; at: number }>; profiles: Array<{ id: string; runid: string; duration: number; samplecount: number; hotfunctions: string[]; at: number; samplesexpired?: boolean }>; shifts: Array<{ id: string; runid: string; stepid: string; score: number; starttime: number; selectors: string[]; at: number }>; traces: Array<{ id: string; runid: string; origin: string; categories: string[]; bytesize: number; events: number; annotations: Array<{ stepid: string; label: string; offset: number }>; startedat: number; endedat: number; bytesexpired?: boolean; exportedat?: number }>; sourcemaps: Array<{ id: string; runid: string; origin: string; scripturl: string; mapurl: string; parsed: boolean; at: number }>; consents: Array<{ id: string; origin: string; approved?: boolean; consentedat: number; revokedat?: number }> }; emulation?: { layers: Array<{ id: string; runid: string; stepid: string; family: string; name: string; originscope: string; appliedat: number; revertedat?: number; revertplan: string[] }>; devices: Array<{ name: string; width: number; height: number; pixelratio: number; mobile: boolean }>; networks: Array<{ name: string; latency: number; download: number; upload: number; offline: boolean }>; locations: Array<{ name: string; latitude: number; longitude: number; accuracy: number }>; agents: Array<{ name: string; useragent: string; platform: string; brands: string[] }>; blackbox: Array<{ origin: string; rules: Array<{ urlpatterns: string[]; tracescope: string }> }>; permissions: Array<{ id: string; runid: string; origin: string; name: string; state: string; priorstate: string; appliedat: number; restoredat?: number }>; consents: Array<{ id: string; origin: string; latitude: number; longitude: number; approved?: boolean; consentedat: number; revokedat?: number }> }; emulatedlayers?: string[]; emulationretention?: number; sessionmemory?: { records: sessionrecord[]; events: sessionevent[]; folders: sessionfolder[]; diffs: sessiondiff[]; auto?: { period: number; maxsnapshots: number; expiry: number }; crashed?: boolean }; autosnapshotstate?: autosnapshotstate; sessionretention?: number; taskstate?: taskstate; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[]; provenance: workflowprovenance[] }; runlogretention?: number; trigger?: { rules: Array<{ id: string; kind: string; workflowid: string; workflowname?: string; label: string; enabled: boolean; paused?: boolean; cooldown: number; lastfireat?: number; nextfireat?: number; fires: number; launches: number; suppressions: number; summary: Record<string, unknown> }>; queued: number }; triggerretention?: number; mcp?: { state: string; config: { bind?: string; port: number; transports: string[]; framesize?: number; queuedepth?: number; callretention?: number; enabled: boolean; remote?: boolean }; bind: string; port: number; localhost: boolean; clients: Array<{ id: string; transport: string; paired: boolean; connectedat: number; capabilities?: { protocolversion: string; toolversion: number; tools: number; transports: string[] }; pairedat?: number }>; bridge?: { id: string; host: string; connected: boolean; restarts: number; received: number; sent: number; startedat: number }; calls: Array<{ id: string; clientid: string; tool: string; origin: string; ok: boolean; code?: string; at: number }>; catalog: { tools: Array<{ name: string; version: number; description: string; risk: string; consentmeta?: string; inputschema: { type: string; properties: Record<string, { type: string; description: string; required?: boolean }>; required: string[] } }> }; launches: Array<{ id: string; host: string; pid: number; restart: boolean; at: number }> }; }; renderplan(context.plan, context.progress, context.outcomes ?? [], context.retries ?? []); renderdiagnostic(context.diagnostic); rendermap(context.map); rendera11y(context.a11y); renderreader(context.reader); renderdetections(context.plan, context.outcomes ?? []); renderstream(context.mutationevents ?? [], context.focusevents ?? []); renderdiffs(context.diffs ?? []); renderbanners(context.banners ?? []); renderselectors(context.selectors ?? []); rendertrail(context.trail?.trail ?? []); rendernavigation(context); rendertabswindows(context); renderforms(context); renderdatasets(context); renderfiles(context); rendercaptures(context); rendermedia(context); rendercalls(context); rendernetview(context); rendertraffic(context); rendertimeline(context); renderdebugger(context); renderprofiling(context); renderemulation(context); rendersessions(context); renderworkflows(context); renderworkfloweditor(context); rendertriggers(context); renderagentprotocol(context); renderconsolediff(); renderaudit(context.audit); rendercapabilities(context.capabilities); if (context.session?.pausedat) status(\"Session paused. Reviewed actions are blocked until resume.\"); else status(context.session ? \"Active session is visible. The extension is waiting for review.\" : \"No active browser session.\"); }\nasync function create(kind: \"proposelocal\" | \"proposeremote\"): Promise<void> { await request({ kind, objective: objective?.value ?? \"\" }); await refresh(); }\nlocalbutton?.addEventListener(\"click\", () => create(\"proposelocal\").catch(error => status(error instanceof Error ? error.message : String(error), true)));\nremotebutton?.addEventListener(\"click\", () => create(\"proposeremote\").catch(error => status(error instanceof Error ? error.message : String(error), true)));\ndiagnosticbutton?.addEventListener(\"click\", () => request({ kind: \"diagnostic\" }).then(() => refresh()).catch(error => status(error instanceof Error ? error.message : String(error), true)));\nrefresh().catch(error => status(error instanceof Error ? error.message : String(error), true));\n\n/** Renders the profiling view: the source map consent prompts, the flow duration bars per step, the heap samples with the growth trend line, the hot functions of the cpu profiles, the layout shifts with scores and impacted selectors, the trace records with export and replay controls grouped by category and step, the attach target state of iframes and workers, and the profile retention and trace byte ceiling settings. */\nfunction renderprofiling(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; profile?: { flows: Array<{ id: string; runid: string; stepid: string; name: string; duration: number; steps: string[] }>; heaps: Array<{ id: string; runid: string; origin: string; bytesize: number; nodecount: number; capturedat: number; bytesexpired?: boolean }>; samples: Array<{ id: string; runid: string; stepid: string; usedbytes: number; limitbytes: number; at: number }>; trends: Array<{ runid: string; slope: number; samples: number; flaggedsteps: string[]; at: number }>; profiles: Array<{ id: string; runid: string; duration: number; samplecount: number; hotfunctions: string[]; at: number; samplesexpired?: boolean }>; shifts: Array<{ id: string; runid: string; stepid: string; score: number; starttime: number; selectors: string[]; at: number }>; traces: Array<{ id: string; runid: string; origin: string; categories: string[]; bytesize: number; events: number; annotations: Array<{ stepid: string; label: string; offset: number }>; startedat: number; endedat: number; bytesexpired?: boolean; exportedat?: number }>; sourcemaps: Array<{ id: string; runid: string; origin: string; scripturl: string; mapurl: string; parsed: boolean; at: number }>; consents: Array<{ id: string; origin: string; approved?: boolean; consentedat: number; revokedat?: number }> }; profileretention?: number; traceceiling?: number; profileactive?: number; profiletargets?: Array<{ kind: string; url: string; sessionid: string; attachedat: number }> }): void {\n if (!profilingroot) return;\n profilingroot.replaceChildren();\n const report = context.profile;\n const waiting = (report?.consents ?? []).filter(consent => consent.approved === undefined && consent.revokedat === undefined);\n for (const consent of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Source map capture on ${consent.origin} waits for your consent; the map files of the loaded same origin scripts are fetched and parsed locally.`;\n card.append(prompt, button(\"Approve source map capture\", () => request({ kind: \"approvesourcemapconsent\", id: consent.id }).then(() => status(`Source map capture on ${consent.origin} approved; run the capturesourcemaps step again.`)).then(refresh)));\n profilingroot.append(card);\n }\n const granted = (report?.consents ?? []).filter(consent => consent.approved === true && consent.revokedat === undefined);\n if (granted.length > 0) profilingroot.append(button(\"Revoke source map consent\", () => request({ kind: \"revokesourcemapconsent\" }).then(value => { const parsed = value as { revoked: number }; status(`Revoked ${parsed.revoked} source map consent record${parsed.revoked === 1 ? \"\" : \"s\"}; the next capture needs a new reviewed prompt.`); return refresh(); })));\n const stateline = document.createElement(\"p\");\n stateline.className = \"muted\";\n stateline.textContent = `${context.profileactive ?? 0} profiling instrument${(context.profileactive ?? 0) === 1 ? \"\" : \"s\"} active${(context.profiletargets ?? []).length > 0 ? ` with the targets ${(context.profiletargets ?? []).map(target => `${target.kind} ${target.url} (${target.sessionid.slice(0, 10)})`).join(\", \")} attached through flattened sub sessions` : \"\"}.`;\n profilingroot.append(stateline);\n const flows = report?.flows ?? [];\n if (flows.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Flow durations per step\";\n profilingroot.append(head);\n const maxflow = flows.reduce((max, metric) => Math.max(max, metric.duration), 0);\n for (const metric of flows.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `${metric.name} \u00B7 ${metric.duration} ms \u00B7 steps ${metric.steps.join(\", \")}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = maxflow > 0 ? `${Math.round((metric.duration / maxflow) * 100)}%` : \"0%\";\n gauge.append(fill);\n bar.append(label, gauge);\n profilingroot.append(bar);\n }\n }\n const heaps = report?.heaps ?? [];\n const samples = report?.samples ?? [];\n const trend = (report?.trends ?? [])[0];\n if (samples.length > 0 || heaps.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Heap samples with the growth trend\";\n profilingroot.append(head);\n const maxused = samples.reduce((max, sample) => Math.max(max, sample.usedbytes), 1);\n for (const sample of samples.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `${sample.usedbytes} of ${sample.limitbytes} bytes \u00B7 step ${sample.stepid}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = `${Math.round((sample.usedbytes / maxused) * 100)}%`;\n gauge.append(fill);\n bar.append(label, gauge);\n profilingroot.append(bar);\n }\n const trendline = document.createElement(\"p\");\n trendline.className = \"muted\";\n trendline.textContent = trend !== undefined ? `Trend slope ${trend.slope.toFixed(2)} bytes per millisecond over ${trend.samples} sample${trend.samples === 1 ? \"\" : \"s\"}${trend.flaggedsteps.length > 0 ? `; flagged steps ${trend.flaggedsteps.join(\", \")}` : \"\"}.` : \"No growth trend computed yet; trackmemory computes it from the samples beside every step.\";\n profilingroot.append(trendline);\n if (heaps.length > 0) {\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const heap of heaps.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `snapshot ${heap.id.slice(0, 8)} \u00B7 ${heap.bytesize} bytes \u00B7 ${heap.nodecount} dom nodes${heap.bytesexpired === true ? \" \u00B7 heavy bytes expired\" : \"\"}`;\n list.append(item);\n }\n profilingroot.append(list);\n }\n }\n const cpuprofiles = report?.profiles ?? [];\n if (cpuprofiles.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Cpu profiles with hot functions\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const profile of cpuprofiles.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `profile ${profile.id.slice(0, 8)} \u00B7 ${profile.duration} ms \u00B7 ${profile.samplecount} sample${profile.samplecount === 1 ? \"\" : \"s\"} \u00B7 hot ${profile.hotfunctions.slice(0, 4).join(\", \") || \"none\"}${profile.samplesexpired === true ? \" \u00B7 heavy samples expired\" : \"\"}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const shifts = report?.shifts ?? [];\n if (shifts.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Layout shifts with scores and selectors\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const shift of shifts.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `score ${shift.score.toFixed(4)} at ${Math.round(shift.starttime)} ms${shift.selectors.length > 0 ? ` \u00B7 impacted ${shift.selectors.join(\", \")}` : \"\"} \u00B7 step ${shift.stepid}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const traces = report?.traces ?? [];\n if (traces.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Traces with step annotations\";\n profilingroot.append(head);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const trace of traces.slice(0, 8)) {\n const item = document.createElement(\"li\");\n item.textContent = `trace ${trace.id.slice(0, 8)} \u00B7 ${trace.categories.join(\", \")} \u00B7 ${trace.events} event${trace.events === 1 ? \"\" : \"s\"} \u00B7 ${trace.bytesize} bytes \u00B7 ${trace.annotations.length} annotation${trace.annotations.length === 1 ? \"\" : \"s\"}${trace.bytesexpired === true ? \" \u00B7 heavy bytes expired\" : \"\"}${trace.exportedat !== undefined ? \" \u00B7 exported\" : \"\"}`;\n item.append(button(\"Replay trace\", () => request({ kind: \"tracereplay\", traceid: trace.id }).then(value => { const replay = value as { events: Array<{ name: string; category: string; offset: number; stepid?: string }>; categories: Record<string, number>; annotations: Array<{ stepid: string; label: string }> }; const grouped = Object.entries(replay.categories).map(([category, count]) => `${category} ${count}`).join(\", \"); const steps = [...new Set(replay.events.map(event => event.stepid).filter((stepid): stepid is string => stepid !== undefined))].join(\", \"); status(`Trace replay of ${trace.id.slice(0, 8)}: ${replay.events.length} event${replay.events.length === 1 ? \"\" : \"s\"} grouped by category (${grouped}) and by step (${steps || \"none\"}) with ${replay.annotations.length} annotation${replay.annotations.length === 1 ? \"\" : \"s\"}.`); return refresh(); })));\n if (trace.bytesexpired !== true) item.append(button(\"Export trace\", () => request({ kind: \"exporttrace\", traceid: trace.id }).then(() => status(`Exported the trace ${trace.id.slice(0, 8)} through the reviewed download flow with its ${trace.annotations.length} step annotation${trace.annotations.length === 1 ? \"\" : \"s\"}.`)).then(refresh)));\n list.append(item);\n }\n profilingroot.append(list);\n }\n const sourcemaps = report?.sourcemaps ?? [];\n if (sourcemaps.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Source maps\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const ref of sourcemaps.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${ref.scripturl} \u2192 ${ref.mapurl} \u00B7 ${ref.parsed ? \"parsed\" : \"unparsed\"}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const settingsline = document.createElement(\"p\");\n settingsline.className = \"muted\";\n settingsline.textContent = `Profile retention ${context.profileretention ?? \"keeps every heavy artifact\"} \u00B7 trace byte ceiling ${context.traceceiling ?? \"none\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"profile retention ms\";\n retentioninput.value = context.profileretention !== undefined ? String(context.profileretention) : \"\";\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.placeholder = \"trace byte ceiling\";\n ceilinginput.value = context.traceceiling !== undefined ? String(context.traceceiling) : \"\";\n profilingroot.append(settingsline, retentioninput, ceilinginput, button(\"Save profiling settings\", () => Promise.all([request({ kind: \"setprofileretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }), request({ kind: \"settraceceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) })]).then(() => status(`Profiling settings saved: profile retention ${retentioninput.value === \"\" ? \"keeps every heavy artifact\" : `${retentioninput.value} milliseconds`} and trace byte ceiling ${ceilinginput.value === \"\" ? \"none\" : `${ceilinginput.value} bytes`}.`)).then(refresh)));\n}\n\n/** Renders the sessions view of the 1.1.49 memory release: the crash restore banner after a browser restart, the auto snapshot state, the search box with its time window, the saved sessions grouped by folder with tags and timestamps, the restore review listing tabs, form state and captures before approval, the diff selection and its change view, the export review and the import review. */\nfunction rendersessions(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; sessionmemory?: { records: sessionrecord[]; events: sessionevent[]; folders: sessionfolder[]; diffs: sessiondiff[]; auto?: { period: number; maxsnapshots: number; expiry: number }; crashed?: boolean }; autosnapshotstate?: autosnapshotstate; sessionretention?: number; taskstate?: taskstate }): void {\n if (!sessionsroot) return;\n sessionsroot.replaceChildren();\n const memory = context.sessionmemory;\n const auto = context.autosnapshotstate;\n const crashed = memory?.crashed === true;\n if (crashed) {\n const banner = document.createElement(\"div\");\n banner.className = \"crashbanner\";\n const title = document.createElement(\"p\");\n title.textContent = `Browser restart interrupted the run${context.taskstate ? ` at step cursor ${context.taskstate.stepcursor}` : \"\"}; the crash restore stays inside the session consent model.`;\n banner.append(title);\n banner.append(button(\"Resume the interrupted run\", async () => { const result = await request({ kind: \"resumerun\" }) as { executed: number; remaining: number }; status(`Resumed the run: ${result.executed} of ${result.remaining} remaining steps executed.`); await refresh(); }));\n banner.append(\" \", button(\"Dismiss crash banner\", async () => { await request({ kind: \"clearautosnapshot\" }).catch(() => undefined); status(\"Crash banner dismissed; the saved sessions stay available for restore.\"); await refresh(); }));\n sessionsroot.append(banner);\n }\n if (auto) {\n const state = document.createElement(\"p\");\n state.textContent = `Auto snapshots: every ${auto.interval.period} ms \u00B7 ${auto.count} of ${auto.interval.maxsnapshots} taken \u00B7 expiry ${auto.interval.expiry} ms.`;\n sessionsroot.append(state, button(\"Clear auto snapshot interval\", async () => { await request({ kind: \"clearautosnapshot\" }); status(\"Auto snapshot interval cleared.\"); await refresh(); }));\n }\n const search = document.createElement(\"div\");\n search.className = \"actions\";\n const term = document.createElement(\"input\");\n term.type = \"search\";\n term.placeholder = \"Search sessions by name, url, title or captured text\";\n term.value = sessionsview.term;\n term.addEventListener(\"input\", () => { sessionsview.term = term.value; rendersessions(context); });\n const windowselect = document.createElement(\"select\");\n for (const option of [[\"all\", \"all time\"], [\"hour\", \"last hour\"], [\"day\", \"last day\"], [\"week\", \"last week\"]] as const) {\n const candidate = document.createElement(\"option\");\n candidate.value = option[0];\n candidate.textContent = option[1];\n candidate.selected = sessionsview.window === option[0];\n windowselect.append(candidate);\n }\n windowselect.addEventListener(\"change\", () => { sessionsview.window = windowselect.value as typeof sessionsview.window; rendersessions(context); });\n search.append(term, windowselect);\n sessionsroot.append(search);\n const importfile = document.createElement(\"input\");\n importfile.type = \"file\";\n importfile.accept = \"application/json\";\n importfile.addEventListener(\"change\", async () => {\n const file = importfile.files?.[0];\n if (!file) return;\n const content = await file.text();\n const review = await request({ kind: \"loadsessionfile\", content }) as { formatversion: number; records: Array<{ id: string; name: string; tabs: number }>; bytesize: number };\n sessionsview.importreview = { records: review.records, file: JSON.parse(content) };\n status(`Session file loaded: ${review.records.length} record${review.records.length === 1 ? \"\" : \"s\"} await review.`);\n await refresh();\n });\n sessionsroot.append(importfile);\n if (sessionsview.importreview) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const title = document.createElement(\"p\");\n title.textContent = `Import review: ${sessionsview.importreview.records.map(record => `${record.name} (${record.tabs} tabs)`).join(\", \")}.`;\n review.append(title, button(\"Approve full record import\", async () => { const result = await request({ kind: \"importsessionrecords\", file: sessionsview.importreview?.file }) as { imported: number }; sessionsview.importreview = undefined; status(`Imported ${result.imported} session record${result.imported === 1 ? \"\" : \"s\"} after review.`); await refresh(); }), \" \", button(\"Cancel import\", async () => { sessionsview.importreview = undefined; status(\"Import cancelled.\"); await refresh(); }));\n sessionsroot.append(review);\n }\n const now = Date.now();\n const windowspan: Record<typeof sessionsview.window, number> = { all: Number.POSITIVE_INFINITY, hour: 3_600_000, day: 86_400_000, week: 604_800_000 };\n const records = (memory?.records ?? []).filter(record => {\n if (now - record.createdat > windowspan[sessionsview.window]) return false;\n if (!sessionsview.term.trim()) return true;\n const haystack = [record.name, record.folder ?? \"\", ...record.tags, ...record.tabs.flatMap(tab => [tab.url, tab.title, ...tab.forms.map(form => form.value)])].join(\" \").toLowerCase();\n return sessionsview.term.trim().toLowerCase().split(/\\s+/).every(term => haystack.includes(term));\n });\n if (sessionsview.diffselection.length >= 2) {\n const [left, right] = sessionsview.diffselection;\n sessionsroot.append(button(\"Diff the two selected sessions\", async () => { const result = await request({ kind: \"sessiondiff\", left, right }) as { changes: Array<{ class: string; subject: string; detail: string }> }; status(`Session diff: ${result.changes.length} change${result.changes.length === 1 ? \"\" : \"s\"}.`); await refresh(); }));\n }\n const groups = new Map<string, sessionrecord[]>();\n for (const record of records) {\n const key = record.folder ?? \"\";\n groups.set(key, [...(groups.get(key) ?? []), record]);\n }\n for (const [folder, entries] of groups) {\n const group = document.createElement(\"details\");\n group.className = \"sessiongroup\";\n group.open = true;\n const summary = document.createElement(\"summary\");\n summary.textContent = folder === \"\" ? \"Saved sessions\" : `Folder ${folder} (${entries.length})`;\n group.append(summary);\n for (const record of entries) group.append(sessionrow(record, context.plan));\n sessionsroot.append(group);\n }\n if (records.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No saved session matches the search yet; run a capturesession step to snapshot the browsing session.\";\n sessionsroot.append(empty);\n }\n if (memory && memory.diffs.length > 0) {\n const diff = memory.diffs[0];\n if (diff) {\n const diffview = document.createElement(\"details\");\n diffview.className = \"sessiongroup\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Latest session diff (${diff.changes.length} changes)`;\n diffview.append(summary);\n for (const change of diff.changes) {\n const line = document.createElement(\"p\");\n line.textContent = `${change.class} ${change.subject}: ${change.detail}`;\n line.dataset.class = change.class;\n diffview.append(line);\n }\n sessionsroot.append(diffview);\n }\n }\n if (sessionsview.restorereview) renderrestorereview(sessionsview.restorereview);\n}\n\n/** Renders one saved session row with its name, folder, tags, timestamp, restored badge and the restore, diff and export actions; the snapshot action runs through the reviewed capturesession step of the approved plan. */\nfunction sessionrow(record: sessionrecord, plan?: agentplan): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n row.dataset.selected = sessionsview.diffselection.includes(record.id) ? \"true\" : \"false\";\n const title = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = record.restoredat !== undefined ? \"true\" : \"false\";\n badge.textContent = record.restoredat !== undefined ? \"restored\" : record.auto === true ? \"auto\" : \"saved\";\n title.append(`${record.name} \u00B7 ${new Date(record.createdat).toLocaleString()} \u00B7 ${record.tabs.length} tabs${record.folder !== undefined ? ` \u00B7 folder ${record.folder}` : \"\"}${record.tags.length > 0 ? ` \u00B7 ${record.tags.join(\", \")}` : \"\"}`, badge);\n row.append(title);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Restore under review\", async () => { sessionsview.restorereview = record; await refresh(); }, record.sectionsexpired === true));\n actions.append(\" \", button(sessionsview.diffselection.includes(record.id) ? \"Unselect diff\" : \"Select diff\", async () => {\n sessionsview.diffselection = sessionsview.diffselection.includes(record.id) ? sessionsview.diffselection.filter(id => id !== record.id) : [...sessionsview.diffselection, record.id].slice(-2);\n await refresh();\n }));\n actions.append(\" \", button(\"Export reviewed file\", async () => { const result = await request({ kind: \"exportsessionfile\", ids: [record.id] }) as { bytes: number }; status(`Exported the session file of ${result.bytes} bytes through the download flow.`); }));\n const capturestep = plan?.state === \"approved\" ? plan.steps.find(step => step.kind === \"capturesession\") : undefined;\n if (capturestep) actions.append(\" \", button(\"Run reviewed snapshot step\", async () => { const result = await request({ kind: \"execute\", stepid: capturestep.id }) as { summary: string }; status(result.summary); await refresh(); }));\n row.append(actions);\n return row;\n}\n\n/** Renders the restore review of one saved session: every tab, form state and capture is listed before the approval reopens anything. */\nfunction renderrestorereview(record: sessionrecord): void {\n if (!sessionsroot) return;\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const title = document.createElement(\"p\");\n title.textContent = `Restore review of ${record.name}: ${record.tabs.length} tabs, ${record.tabs.reduce((total, tab) => total + tab.forms.length, 0)} captured form fields, ${record.captures.length} linked captures.`;\n review.append(title);\n for (const tab of record.tabs) {\n const line = document.createElement(\"p\");\n line.textContent = `Tab ${tab.index}: ${tab.title || tab.url} \u00B7 ${tab.forms.length} form fields \u00B7 scroll ${tab.scrollx},${tab.scrolly}`;\n review.append(line);\n }\n for (const entry of record.storage) {\n const line = document.createElement(\"p\");\n line.textContent = `Local storage of ${entry.origin}: ${entry.keys.length} keys captured.`;\n review.append(line);\n }\n for (const entry of record.cookies) {\n const line = document.createElement(\"p\");\n line.textContent = `Cookies of ${entry.origin}: ${entry.names.length} names captured, values held back.`;\n review.append(line);\n }\n review.append(button(\"Approve restore\", async () => { const result = await request({ kind: \"approverestore\", sessionid: record.id }) as { restored: number; skippedorigins: string[] }; sessionsview.restorereview = undefined; status(`Restored ${result.restored} tabs${result.skippedorigins.length > 0 ? `; skipped ${result.skippedorigins.join(\", \")}` : \"\"}.`); await refresh(); }), \" \", button(\"Cancel restore\", async () => { sessionsview.restorereview = undefined; status(\"Restore cancelled.\"); await refresh(); }));\n sessionsroot.append(review);\n}\n\n/** Renders the control flow summary of one reviewed step: the branch paths with the else path preview, the loop bounds and bodies, the parallel branches with the join policy and the try retry and timeout policies. */\nfunction controlreviewtext(control: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } | undefined): string {\n if (control === undefined) return \"\";\n if (control.kind === \"condition\") return ` \u00B7 condition ${control.expression ?? \"expression\"}`;\n if (control.kind === \"branch\") return ` \u00B7 paths ${(control.paths ?? []).join(\", \")} \u00B7 else ${control.elsepath ?? \"else\"} when no path matches`;\n if (control.kind === \"loop\") return ` \u00B7 loops ${control.list ?? \"list\"} binding ${control.item ?? \"item\"} and ${control.index ?? \"index\"} per iteration \u00B7 safety bound ${control.bound ?? 1000}`;\n if (control.kind === \"repeatuntil\") return ` \u00B7 repeats until convergence \u00B7 safety bound ${control.bound ?? 1000}`;\n if (control.kind === \"whileloop\") return ` \u00B7 while the condition holds \u00B7 safety bound ${control.bound ?? \"reviewed\"}`;\n if (control.kind === \"foreach\") return ` \u00B7 foreach ${control.selector ?? \"selector\"} binding ${control.item ?? \"item\"} and ${control.index ?? \"index\"} per element`;\n if (control.kind === \"parallel\") return ` \u00B7 branches ${(control.branches ?? []).join(\", \")} \u00B7 join ${control.strategy ?? \"last\"} \u00B7 on failure ${control.onfail ?? \"continue\"}`;\n return ` \u00B7 try with catch${control.rerun === true ? \" and rerun\" : \"\"}${control.attempts !== undefined ? ` \u00B7 ${control.attempts} attempt${control.attempts === 1 ? \"\" : \"s\"} of ${control.backoff ?? \"fixed\"} backoff` : \"\"}${control.stepms !== undefined ? ` \u00B7 step budget ${control.stepms} ms` : \"\"}${control.runms !== undefined ? ` \u00B7 run budget ${control.runms} ms` : \"\"}`;\n}\n\n/** Renders one control flow decision of the runlog: the chosen branch path highlighted, the loop iterations as a collapsible group, the retry attempts with their backoff countdowns, the parallel branch lanes, the join result with the merged variables, the catch path of a try block and the timeout aborts with the exceeded budget. */\nfunction rendercontroldecision(entry: runlogentry): HTMLElement {\n const block = document.createElement(\"details\");\n block.className = \"sessiongroup\";\n const control = entry.details?.control as { kind?: string; branch?: { path: string; reason: string }; loops?: Array<{ path: string; ok: boolean }>; retries?: Array<{ attempt: number; delay: number; errorclass: string }>; timeouts?: Array<{ budget: number; scope: string }>; join?: { strategy: string; conflicts: string[]; merged: string[] }; branches?: Array<{ branchid: string; ok: boolean; summary: string; cancelled?: boolean }>; catch?: { errorclass: string; rerun: boolean } } | undefined;\n const summary = document.createElement(\"summary\");\n summary.textContent = `control flow \u00B7 ${control?.kind ?? \"decision\"} \u00B7 ${entry.summary}`;\n block.append(summary);\n if (control?.branch !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `Chose the path ${control.branch.path}: ${control.branch.reason}`;\n line.dataset.class = \"added\";\n line.dataset.branch = control.branch.path;\n block.append(line);\n }\n if (control?.loops !== undefined && control.loops.length > 0) {\n const group = document.createElement(\"details\");\n group.className = \"sessiongroup\";\n const groupsummary = document.createElement(\"summary\");\n groupsummary.textContent = `Loop iterations (${control.loops.length})`;\n group.append(groupsummary);\n for (const counter of control.loops) {\n const line = document.createElement(\"p\");\n line.textContent = `${counter.path} \u00B7 ${counter.ok ? \"completed\" : \"failed\"}`;\n line.dataset.class = counter.ok ? \"added\" : \"changed\";\n group.append(line);\n }\n block.append(group);\n }\n if (control?.retries !== undefined && control.retries.length > 0) {\n for (const attempt of control.retries) {\n const line = document.createElement(\"p\");\n line.textContent = `Retry attempt ${attempt.attempt} after a ${attempt.delay} ms backoff countdown for the ${attempt.errorclass} error class.`;\n line.dataset.class = \"changed\";\n block.append(line);\n }\n }\n if (control?.timeouts !== undefined && control.timeouts.length > 0) {\n for (const abort of control.timeouts) {\n const line = document.createElement(\"p\");\n line.textContent = `Timeout abort: the ${abort.scope} exceeded its reviewed budget of ${abort.budget} milliseconds.`;\n line.dataset.class = \"changed\";\n line.dataset.timeout = \"true\";\n block.append(line);\n }\n }\n if (control?.branches !== undefined && control.branches.length > 0) {\n const lanes = document.createElement(\"details\");\n lanes.className = \"sessiongroup\";\n const lannessummary = document.createElement(\"summary\");\n lannessummary.textContent = `Parallel branch lanes (${control.branches.length})`;\n lanes.append(lannessummary);\n for (const outcome of control.branches) {\n const lane = document.createElement(\"p\");\n lane.textContent = `lane ${outcome.branchid} \u00B7 ${outcome.cancelled === true ? \"cancelled\" : outcome.ok ? \"completed\" : \"failed\"} \u00B7 ${outcome.summary}`;\n lane.dataset.class = outcome.ok && outcome.cancelled !== true ? \"added\" : \"changed\";\n lanes.append(lane);\n }\n block.append(lanes);\n }\n if (control?.join !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `Join under the ${control.join.strategy} strategy merged ${control.join.merged.join(\", \") || \"no variable\"}${control.join.conflicts.length > 0 ? ` with the conflicts ${control.join.conflicts.join(\", \")}` : \" with no conflict\"}.`;\n line.dataset.class = control.join.conflicts.length > 0 ? \"changed\" : \"added\";\n block.append(line);\n }\n if (control?.catch !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `The catch handler ran after the ${control.catch.errorclass} failure${control.catch.rerun ? \" and reran the fragile body\" : \"\"}.`;\n line.dataset.class = \"changed\";\n block.append(line);\n }\n return block;\n}\n\n/** Renders the workflow view: the composed workflows with their run and dry run actions behind the plan review, the approval prompt of the first real run with the expanded step list, the live step timeline with checkpoint markers and dry run marks, the variable values per scope, the inline expression results, the active block highlight, the runlog stream and the single step execution from the step context. */\nfunction renderworkflows(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[]; provenance: workflowprovenance[] } }): void {\n if (!workflowsroot) return;\n workflowsroot.replaceChildren();\n const state = context.workflow;\n const runs = state?.runs ?? [];\n const running = runs.filter(run => run.state === \"running\");\n const latest = runs[0];\n const title = document.createElement(\"p\");\n title.textContent = `${state?.workflows.length ?? 0} composed workflow${(state?.workflows.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${running.length} running in the background \u00B7 ${state?.templates.length ?? 0} shared step template${(state?.templates.length ?? 0) === 1 ? \"\" : \"s\"}.`;\n workflowsroot.append(title);\n for (const record of state?.workflows ?? []) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = record.risk === \"sensitive\" ? \"sensitive\" : record.risk;\n headline.append(`${record.name} v${record.version} \u00B7 ${record.steps.length} steps \u00B7 ${record.origins.join(\", \")}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n const planstep = (kind: \"runworkflow\" | \"dryrun\"): toolstep | undefined => (context.plan?.state === \"approved\" ? context.plan.steps.find(step => step.kind === kind && (() => { try { return JSON.parse(step.options ?? \"{}\").workflowid === record.id; } catch { return false; } })()) : undefined);\n const runstepofplan = planstep(\"runworkflow\");\n const drystepofplan = planstep(\"dryrun\");\n actions.append(button(\"Review expanded steps\", async () => { const review = await request({ kind: \"workflowreview\", workflowid: record.id }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string; bindings?: unknown[]; expression?: { operator: string; result: string }; extract?: { groups: string[] }; control?: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } }> }; workflowview.review = { workflowid: record.id, name: record.name, risk: record.risk, steps: review.steps }; status(`Workflow review: ${review.steps.length} expanded steps of ${record.name}.`); await refresh(); }));\n actions.append(\" \", button(\"Approve run review\", async () => { const result = await request({ kind: \"approveworkflowrun\", workflowid: record.id }) as { steps: number }; status(`Run review approved: ${result.steps} steps shown; the plan review still gates every run.`); await refresh(); }));\n actions.append(\" \", button(\"Run reviewed workflow\", async () => { if (!runstepofplan) { status(\"No approved runworkflow step of this workflow is in the plan.\", true); return; } const result = await request({ kind: \"execute\", stepid: runstepofplan.id }) as { summary: string }; status(result.summary); await refresh(); }, runstepofplan === undefined));\n actions.append(\" \", button(\"Dry run\", async () => { if (!drystepofplan) { status(\"No approved dryrun step of this workflow is in the plan.\", true); return; } const result = await request({ kind: \"execute\", stepid: drystepofplan.id }) as { summary: string }; status(result.summary); await refresh(); }, drystepofplan === undefined));\n row.append(actions);\n workflowsroot.append(row);\n }\n if ((state?.workflows.length ?? 0) === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No composed workflow yet; run a composeworkflow step to freeze a reviewed step list.\";\n workflowsroot.append(empty);\n }\n if (workflowview.review) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Workflow approval of ${workflowview.review.name} (${workflowview.review.risk} for review): every expanded step shows before the first real run.`;\n review.append(headline);\n const list = document.createElement(\"ol\");\n for (const step of workflowview.review.steps) {\n const line = document.createElement(\"li\");\n line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.target !== undefined ? ` \u00B7 ${step.target}` : \"\"}${step.expression !== undefined ? ` \u00B7 expression ${step.expression.operator} into ${step.expression.result}` : \"\"}${step.extract !== undefined && step.extract.groups.length > 0 ? ` \u00B7 extracts ${step.extract.groups.join(\", \")}` : \"\"}${Array.isArray(step.bindings) && step.bindings.length > 0 ? ` \u00B7 ${step.bindings.length} binding${step.bindings.length === 1 ? \"\" : \"s\"}` : \"\"}${controlreviewtext(step.control)}`;\n list.append(line);\n if (step.control !== undefined && (step.control.kind === \"loop\" || step.control.kind === \"repeatuntil\")) {\n const boundrow = document.createElement(\"div\");\n boundrow.className = \"actions\";\n const boundlabel = document.createElement(\"label\");\n boundlabel.textContent = `Safety bound of ${step.label}: `;\n const boundinput = document.createElement(\"input\");\n boundinput.type = \"number\";\n boundinput.min = \"1\";\n boundinput.value = String(step.control.bound ?? 1000);\n boundlabel.append(boundinput);\n boundrow.append(boundlabel, \" \", button(\"Apply bound before a run\", async () => {\n const bound = Number(boundinput.value);\n if (!Number.isInteger(bound) || bound < 1) { status(\"The loop safety bound must be a positive integer with no code ceiling.\", true); return; }\n const result = await request({ kind: \"setloopbound\", workflowid: workflowview.review?.workflowid, stepid: step.id, bound }) as { version: number };\n status(`Loop bound applied: the workflow was recomposed as version ${result.version} and the older version survives for the audit trail.`);\n await refresh();\n }));\n list.append(boundrow);\n }\n }\n review.append(list);\n review.append(button(\"Close workflow review\", async () => { workflowview.review = undefined; status(\"Workflow review closed.\"); await refresh(); }));\n workflowsroot.append(review);\n }\n if (latest) {\n const timeline = document.createElement(\"details\");\n timeline.className = \"sessiongroup\";\n timeline.open = latest.state === \"running\" || latest.state === \"paused\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Run ${latest.id.slice(0, 8)} of ${latest.workflowid.slice(0, 8)}: ${latest.state}${latest.dryrun === true ? \" (dry run)\" : \"\"} at step cursor ${latest.cursor}.`;\n timeline.append(summary);\n const controls = document.createElement(\"div\");\n controls.className = \"actions\";\n controls.append(button(\"Pause run\", async () => { const result = await request({ kind: \"pauseworkflowrun\", runid: latest.id }) as { state: string }; status(`Workflow run ${result.state}.`); await refresh(); }, latest.state !== \"running\"));\n controls.append(\" \", button(\"Resume run\", async () => { const result = await request({ kind: \"resumeworkflowrun\", runid: latest.id }) as { state: string; cursor: number }; status(`Workflow run resumed and ended ${result.state} at cursor ${result.cursor}.`); await refresh(); }, latest.state !== \"paused\"));\n controls.append(\" \", button(\"Cancel run\", async () => { const result = await request({ kind: \"cancelworkflowrun\", runid: latest.id, reason: \"sidepanel cancel\" }) as { state: string }; status(`Workflow run ${result.state}.`); await refresh(); }, latest.state === \"done\" || latest.state === \"cancelled\"));\n timeline.append(controls);\n const record = state?.workflows.find(entry => entry.id === latest.workflowid);\n if (record) {\n const steps = document.createElement(\"ol\");\n for (const [index, step] of record.steps.entries()) {\n const line = document.createElement(\"li\");\n const entry = state?.log.find(candidate => candidate.stepid === step.id);\n const done = index < latest.cursor;\n line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"})${done ? ` \u00B7 done${entry?.checkpoint === true ? \" \u00B7 checkpointed\" : \"\"}` : \"\"}${entry !== undefined ? ` \u00B7 ${entry.state}: ${entry.summary}` : \"\"}`;\n line.dataset.class = entry?.state === \"failed\" || entry?.state === \"refused\" ? \"changed\" : done ? \"added\" : \"unavailable\";\n if (step.block !== undefined && index === latest.cursor) line.dataset.blockactive = \"true\";\n const singlestep = document.createElement(\"div\");\n singlestep.className = \"actions\";\n singlestep.append(button(\"Run single step\", async () => { const outcome = await request({ kind: \"executeworkflowstep\", runid: latest.id, stepid: step.id }) as { steps: Array<{ stepid: string; state: string; summary: string }> }; status(outcome.steps[0] ? `Single step ${outcome.steps[0].state}: ${outcome.steps[0].summary}` : \"The single step returned no outcome.\"); await refresh(); }));\n line.append(singlestep);\n steps.append(line);\n }\n timeline.append(steps);\n }\n const runlog = document.createElement(\"div\");\n for (const entry of state?.log ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.state} \u00B7 ${entry.label} \u00B7 ${entry.duration} ms${entry.produced !== undefined && entry.produced.length > 0 ? ` \u00B7 produced ${entry.produced.join(\", \")}` : \"\"}${entry.consumed !== undefined && entry.consumed.length > 0 ? ` \u00B7 consumed ${entry.consumed.join(\", \")}` : \"\"} \u00B7 ${entry.summary}`;\n line.dataset.class = entry.state === \"failed\" || entry.state === \"refused\" ? \"changed\" : \"added\";\n runlog.append(line);\n if (entry.details !== undefined && entry.details.control !== undefined) runlog.append(rendercontroldecision(entry));\n }\n timeline.append(runlog);\n workflowsroot.append(timeline);\n const scopes = state?.scopes ?? [];\n if (scopes.length > 0) {\n const scopeview = document.createElement(\"details\");\n scopeview.className = \"sessiongroup\";\n const scopesummary = document.createElement(\"summary\");\n scopesummary.textContent = `Variables per scope (${scopes.reduce((total, scope) => total + scope.variables.length, 0)} values)`;\n scopeview.append(scopesummary);\n for (const scope of scopes) {\n const line = document.createElement(\"p\");\n line.textContent = `Scope ${scope.name}${scope.parent !== undefined ? ` (child of ${scope.parent})` : \"\"}: ${scope.variables.length === 0 ? \"no variable\" : scope.variables.map(variable => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(\", \")}]` : String(variable.value)} (${variable.kind})`).join(\" \u00B7 \")}`;\n scopeview.append(line);\n }\n workflowsroot.append(scopeview);\n }\n const provenance = state?.provenance ?? [];\n if (provenance.length > 0) {\n const provenanceview = document.createElement(\"details\");\n provenanceview.className = \"sessiongroup\";\n const provsummary = document.createElement(\"summary\");\n provsummary.textContent = `Provenance (${provenance.length} entries)`;\n provenanceview.append(provsummary);\n for (const entry of provenance.slice(-12)) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.kind} \u00B7 ${entry.name} = ${Array.isArray(entry.value) ? `[${entry.value.join(\", \")}]` : String(entry.value)}`;\n provenanceview.append(line);\n }\n workflowsroot.append(provenanceview);\n }\n }\n}\n\n/** Saves one file from the panel through a local blob download so workflow exports and share bundles leave the browser only by the user's hand. */\nfunction savefile(filename: string, contents: string): void {\n const url = URL.createObjectURL(new Blob([contents], { type: \"application/octet-stream\" }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = filename;\n anchor.click();\n setTimeout(() => URL.revokeObjectURL(url), 10_000);\n}\n\n/** Renders the workflow editor view of the 1.1.53 release: the canvas with draggable nodes, typed binding sockets and block containers, the mini map with viewport navigation, the zoom that keeps labels readable, the undo and redo stacks, the block palette with search, the step library of every reviewed kind grouped by category, the step inspector with options, bindings and nested params, the variable inspector, the run log with breakpoint marks, the run history with filters, the version timeline with diffs and rollbacks, the import review before activation, the export and share buttons, the background run toggle, the watchdog status and the per site policy override editor. */\nfunction renderworkfloweditor(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[] }; editor?: { versions: workflowversion[]; diffs: versiondiff[]; history: runhistoryentry[]; breakpoints: string[]; overrides: siteoverride[]; imports: Array<{ id: string; workflowid: string; name: string; version: number; steps: number; risk: string; importedat: number; filename?: string }>; backgroundruns: Record<string, boolean>; watchdog: { config?: watchdogconfig; events: watchdogrecord[] } } }): void {\n if (!workfloweditorroot) return;\n workfloweditorroot.replaceChildren();\n const editor = context.editor;\n const workflows = context.workflow?.workflows ?? [];\n const title = document.createElement(\"p\");\n title.textContent = `${workflows.length} workflow${workflows.length === 1 ? \"\" : \"s\"} in the library \u00B7 ${editor?.versions.length ?? 0} version${(editor?.versions.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.history.length ?? 0} run history entr${(editor?.history.length ?? 0) === 1 ? \"y\" : \"ies\"} \u00B7 ${editor?.imports.length ?? 0} pending import${(editor?.imports.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.overrides.length ?? 0} site override${(editor?.overrides.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.watchdog.events.length ?? 0} watchdog event${(editor?.watchdog.events.length ?? 0) === 1 ? \"\" : \"s\"}.`;\n workfloweditorroot.append(title);\n const openrow = document.createElement(\"div\");\n openrow.className = \"actions\";\n for (const record of workflows) {\n openrow.append(button(`${record.name} v${record.version}`, async () => {\n const loaded = await request({ kind: \"editormodel\", workflowid: record.id }) as { model: editormodel };\n editorview.workflowid = record.id;\n editorview.model = loaded.model;\n editorview.selected = [];\n editorview.inspector = \"\";\n status(`Opened ${record.name} v${record.version} on the canvas with ${loaded.model.nodes.length} nodes.`);\n await refresh();\n }), \" \");\n }\n if (editorview.model !== undefined) openrow.append(button(\"Close canvas\", async () => { editorview.workflowid = \"\"; editorview.model = undefined; editorview.selected = []; editorview.inspector = \"\"; editorview.diff = undefined; status(\"Canvas closed; the stored versions survive.\"); await refresh(); }));\n workfloweditorroot.append(openrow);\n const model = editorview.model;\n if (model !== undefined) {\n /** Renders one canvas node element with its typed sockets, breakpoint mark, selection outline and pointer drag wiring. */\n const nodeelement = (node: editornode): HTMLElement => {\n const element = document.createElement(\"div\");\n element.className = \"editornode\";\n element.style.left = `${node.x}px`;\n element.style.top = `${node.y}px`;\n const id = node.id ?? node.step?.id ?? node.invocation?.block ?? \"\";\n element.dataset.selected = editorview.selected.includes(id) ? \"true\" : \"false\";\n element.dataset.breakpoint = node.step?.breakpoint === true ? \"true\" : \"false\";\n element.dataset.invocation = node.invocation !== undefined ? \"true\" : \"false\";\n const kind = document.createElement(\"p\");\n kind.className = \"nodekind\";\n kind.textContent = node.step !== undefined ? node.step.kind : `block ${node.invocation?.block ?? \"\"}`;\n element.append(kind);\n const label = document.createElement(\"p\");\n label.textContent = node.step !== undefined ? node.step.label : (node.invocation?.label ?? \"\");\n element.append(label);\n if (node.invocation !== undefined) {\n const nested = model.blocks.find(block => block.name === node.invocation?.block);\n for (const entry of nested?.steps ?? []) {\n const child = document.createElement(\"p\");\n child.textContent = entry && \"kind\" in entry ? `\u00B7 ${entry.label} (${entry.kind})` : `\u00B7 block ${(entry as { block: string }).block}`;\n element.append(child);\n }\n }\n const sockets = document.createElement(\"p\");\n const targets = node.invocation !== undefined ? [id, ...(model.blocks.find(block => block.name === node.invocation?.block)?.steps ?? []).flatMap(entry => \"id\" in entry ? [entry.id] : [])] : [id];\n for (const edge of model.edges.filter(candidate => targets.includes(candidate.to))) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket in\";\n socket.textContent = `${edge.variable} (${edge.kind})`;\n sockets.append(socket, \" \");\n }\n for (const edge of model.edges.filter(candidate => candidate.from === id)) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket out\";\n socket.textContent = `${edge.variable} \u2192`;\n sockets.append(socket, \" \");\n }\n if (node.invocation?.params !== undefined && node.invocation.params.length > 0) {\n for (const param of node.invocation.params) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket\";\n socket.textContent = `${param.name}: ${param.kind}`;\n sockets.append(socket, \" \");\n }\n }\n element.append(sockets);\n element.addEventListener(\"click\", () => { editorview.selected = [id]; editorview.inspector = id; void refresh(); });\n if (node.step !== undefined) {\n element.addEventListener(\"pointerdown\", event => {\n if (event.button !== 0) return;\n const startx = event.clientX;\n const starty = event.clientY;\n const originx = node.x;\n const originy = node.y;\n element.setPointerCapture(event.pointerId);\n const move = (moveevent: PointerEvent): void => { element.style.left = `${originx + moveevent.clientX - startx}px`; element.style.top = `${originy + moveevent.clientY - starty}px`; };\n const drop = (upevent: PointerEvent): void => {\n element.removeEventListener(\"pointermove\", move);\n element.removeEventListener(\"pointerup\", drop);\n void (async () => {\n if (editorview.model === undefined) return;\n try {\n editorview.model = snapnode(editorview.model, id, originx + upevent.clientX - startx, originy + upevent.clientY - starty);\n status(`Snapped ${id} onto the block grid; drop it near a block column to attach.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n })();\n };\n element.addEventListener(\"pointermove\", move);\n element.addEventListener(\"pointerup\", drop);\n });\n }\n return element;\n };\n const canvascard = document.createElement(\"div\");\n canvascard.className = \"sessionrow\";\n const toolbar = document.createElement(\"div\");\n toolbar.className = \"actions\";\n toolbar.append(button(\"Undo\", async () => { if (editorview.model === undefined) return; editorview.model = undoedit(editorview.model); status(\"Canvas edit undone; the redo stack keeps it.\"); await refresh(); }, (model.undo ?? []).length === 0));\n toolbar.append(\" \", button(\"Redo\", async () => { if (editorview.model === undefined) return; editorview.model = redoedit(editorview.model); status(\"Canvas edit redone.\"); await refresh(); }, (model.redo ?? []).length === 0));\n toolbar.append(\" \", button(\"Toggle breakpoint\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") { status(\"Select a step node first.\", true); return; } editorview.model = markbreakpoint(editorview.model, editorview.inspector); status(`Breakpoint toggled on ${editorview.inspector}; a debug run pauses before it.`); await refresh(); }));\n toolbar.append(\" \", button(\"Remove selected\", async () => { if (editorview.model === undefined || editorview.selected.length === 0) { status(\"Select a node first.\", true); return; } try { for (const id of editorview.selected) editorview.model = removenode(editorview.model, id); editorview.selected = []; editorview.inspector = \"\"; status(\"Node removed with its edges; undo brings it back.\"); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n toolbar.append(\" \", button(\"Move up\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") return; const index = editorview.model.nodes.findIndex(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector); try { if (index > 0) editorview.model = reordersteps(editorview.model, editorview.inspector, index - 1); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n toolbar.append(\" \", button(\"Move down\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") return; const index = editorview.model.nodes.findIndex(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector); try { if (index >= 0 && index < editorview.model.nodes.length - 1) editorview.model = reordersteps(editorview.model, editorview.inspector, index + 1); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n const grouprow = document.createElement(\"div\");\n grouprow.className = \"actions\";\n const groupinput = document.createElement(\"input\");\n groupinput.type = \"text\";\n groupinput.placeholder = \"blockname\";\n grouprow.append(groupinput, \" \", button(\"Group selection into block\", async () => {\n if (editorview.model === undefined || editorview.selected.length === 0) { status(\"Select step nodes first.\", true); return; }\n try { editorview.model = groupselect(editorview.model, editorview.selected, groupinput.value.trim()); editorview.selected = []; status(`Grouped the selection into the block ${groupinput.value.trim()}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n canvascard.append(toolbar, grouprow);\n const canvas = document.createElement(\"div\");\n canvas.className = \"editorcanvas\";\n const layer = document.createElement(\"div\");\n layer.style.position = \"absolute\";\n layer.style.transformOrigin = \"0 0\";\n layer.style.left = \"0\";\n layer.style.top = \"0\";\n layer.style.width = `${model.layout.width}px`;\n layer.style.height = `${model.layout.height}px`;\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n layer.style.transform = `translate(${-Math.max(0, model.layout.viewportx)}px, ${-Math.max(0, model.layout.viewporty)}px) scale(${zoom})`;\n for (const block of model.blocks) {\n const members = model.nodes.filter(node => node.invocation?.block === block.name);\n if (members.length === 0) continue;\n const container = document.createElement(\"div\");\n container.className = \"editorblock\";\n const left = Math.min(...members.map(node => node.x)) - 14;\n const top = Math.min(...members.map(node => node.y)) - 14;\n container.style.left = `${left}px`;\n container.style.top = `${top}px`;\n container.style.width = `${Math.max(...members.map(node => node.x)) - left + 234}px`;\n container.style.height = `${Math.max(...members.map(node => node.y)) - top + 110}px`;\n const name = document.createElement(\"span\");\n name.textContent = block.name;\n container.append(name);\n layer.append(container);\n }\n for (const node of model.nodes) layer.append(nodeelement(node));\n canvas.append(layer);\n canvascard.append(canvas);\n const minimap = document.createElement(\"div\");\n minimap.className = \"editorminimap\";\n const projection = renderminimap(model);\n for (const dot of projection.nodes) {\n const point = document.createElement(\"span\");\n point.className = \"dot\";\n point.style.left = `${Math.min(dot.x, model.minimap.width - 5)}px`;\n point.style.top = `${Math.min(dot.y, model.minimap.height - 5)}px`;\n minimap.append(point);\n }\n const rect = document.createElement(\"span\");\n rect.className = \"viewportrect\";\n rect.style.left = `${Math.max(0, model.minimap.viewport.x)}px`;\n rect.style.top = `${Math.max(0, model.minimap.viewport.y)}px`;\n rect.style.width = `${Math.max(8, model.minimap.viewport.width)}px`;\n rect.style.height = `${Math.max(6, model.minimap.viewport.height)}px`;\n minimap.append(rect);\n minimap.addEventListener(\"click\", event => {\n void (async () => {\n if (editorview.model === undefined) return;\n const bounds = minimap.getBoundingClientRect();\n try {\n editorview.model = minimapfocus(editorview.model, event.clientX - bounds.left, event.clientY - bounds.top);\n status(\"Canvas jumped to the mini map region.\");\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n })();\n });\n canvascard.append(minimap);\n const zoomrow = document.createElement(\"div\");\n zoomrow.className = \"actions\";\n const zoominput = document.createElement(\"input\");\n zoominput.type = \"number\";\n zoominput.min = \"0.1\";\n zoominput.step = \"0.1\";\n zoominput.value = String(zoom);\n zoomrow.append(zoominput, \" \", button(\"Apply zoom\", async () => {\n if (editorview.model === undefined) return;\n try { const applied = zoomcanvas(editorview.model, Number(zoominput.value)); editorview.model = applied.model; status(`Canvas zoom ${Number(zoominput.value)} with label scale ${applied.labelscale.toFixed(2)} so every step label stays readable.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n const searchinput = document.createElement(\"input\");\n searchinput.type = \"text\";\n searchinput.placeholder = \"search steps by label, kind or variable\";\n searchinput.value = editorview.stepsearch;\n searchinput.addEventListener(\"input\", () => { editorview.stepsearch = searchinput.value; });\n zoomrow.append(searchinput, \" \", button(\"Search steps\", async () => { await refresh(); }));\n canvascard.append(zoomrow);\n const results = searchsteps(model, editorview.stepsearch);\n if (results.length > 0) {\n const list = document.createElement(\"ul\");\n for (const result of results) {\n const line = document.createElement(\"li\");\n line.textContent = `${result.label} (${result.kind}) matched ${result.matched.join(\", \")}`;\n list.append(line);\n }\n canvascard.append(list);\n }\n workfloweditorroot.append(canvascard);\n const inspector = model.nodes.find(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector);\n if (inspector !== undefined) {\n const card = document.createElement(\"div\");\n card.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = inspector.step !== undefined ? `Step inspector of ${inspector.step.id}` : `Invocation inspector of block ${inspector.invocation?.block ?? \"\"}`;\n card.append(headline);\n if (inspector.step !== undefined) {\n const inspectedstep = inspector.step;\n const grid = document.createElement(\"div\");\n grid.className = \"editorgrid\";\n const labelinput = document.createElement(\"input\");\n labelinput.type = \"text\";\n labelinput.value = inspectedstep.label;\n const targetinput = document.createElement(\"input\");\n targetinput.type = \"text\";\n targetinput.placeholder = \"css target\";\n targetinput.value = inspectedstep.target ?? \"\";\n const valueinput = document.createElement(\"input\");\n valueinput.type = \"text\";\n valueinput.placeholder = \"value\";\n valueinput.value = inspectedstep.value ?? \"\";\n const optionsinput = document.createElement(\"input\");\n optionsinput.type = \"text\";\n optionsinput.placeholder = \"json options\";\n optionsinput.value = inspectedstep.options ?? \"\";\n for (const [labeltext, input] of [[\"label\", labelinput], [\"target\", targetinput], [\"value\", valueinput], [\"options json\", optionsinput]] as Array<[string, HTMLInputElement]>) {\n const fieldlabel = document.createElement(\"label\");\n fieldlabel.textContent = labeltext;\n fieldlabel.append(input);\n grid.append(fieldlabel);\n }\n card.append(grid, button(\"Save step edits\", async () => {\n if (editorview.model === undefined || inspectedstep === undefined) return;\n const options = optionsinput.value.trim() === \"\" ? undefined : optionsinput.value.trim();\n try {\n editorview.model = editstep(editorview.model, { ...inspectedstep, label: labelinput.value.trim(), ...(targetinput.value.trim() !== \"\" ? { target: targetinput.value.trim() } : {}), ...(valueinput.value.trim() !== \"\" ? { value: valueinput.value.trim() } : {}), ...(options !== undefined ? { options } : {}) });\n status(`Saved the edits of ${inspectedstep.id}; undo covers them.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n const bindings = document.createElement(\"details\");\n bindings.className = \"sessiongroup\";\n const bindingssummary = document.createElement(\"summary\");\n bindingssummary.textContent = `Bindings and nested params (${model.edges.filter(edge => edge.to === inspectedstep.id || edge.from === inspectedstep.id).length} edges)`;\n bindings.append(bindingssummary);\n for (const edge of model.edges.filter(candidate => candidate.to === inspectedstep?.id)) {\n const line = document.createElement(\"p\");\n line.textContent = `${edge.variable} (${edge.kind}) from ${edge.from}${edge.path !== undefined ? ` path ${edge.path}` : \"\"}`;\n line.append(\" \", button(\"Remove binding\", async () => { if (editorview.model === undefined) return; try { editorview.model = removeedge(editorview.model, edge.from, edge.to, edge.variable); status(`Removed the binding ${edge.variable}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n bindings.append(line);\n }\n const source = document.createElement(\"select\");\n for (const node of model.nodes) {\n if (node.step === undefined || node.step.id === inspectedstep.id) continue;\n const option = document.createElement(\"option\");\n option.value = node.step.id;\n option.textContent = `${node.step.id} (${node.step.kind})`;\n source.append(option);\n }\n const variableinput = document.createElement(\"input\");\n variableinput.type = \"text\";\n variableinput.placeholder = \"variable\";\n const kindselect = document.createElement(\"select\");\n for (const kind of [\"string\", \"number\", \"boolean\", \"list\", \"element\"] as variablekind[]) {\n const option = document.createElement(\"option\");\n option.value = kind;\n option.textContent = kind;\n kindselect.append(option);\n }\n const pathinput = document.createElement(\"input\");\n pathinput.type = \"text\";\n pathinput.placeholder = \"path into outcome details\";\n bindings.append(source, \" \", variableinput, \" \", kindselect, \" \", pathinput, \" \", button(\"Bind variable\", async () => {\n if (editorview.model === undefined) return;\n try {\n editorview.model = addedge(editorview.model, { from: source.value, to: inspectedstep?.id ?? \"\", variable: variableinput.value.trim(), kind: kindselect.value as variablekind, ...(pathinput.value.trim() !== \"\" ? { path: pathinput.value.trim() } : {}) });\n status(`Bound ${variableinput.value.trim()} from ${source.value}.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n card.append(bindings);\n }\n if (inspector.invocation !== undefined) {\n const paramgrid = document.createElement(\"div\");\n paramgrid.className = \"editorgrid\";\n const paramname = document.createElement(\"input\");\n paramname.type = \"text\";\n paramname.placeholder = \"param name\";\n const paramkind = document.createElement(\"select\");\n for (const kind of [\"string\", \"number\", \"boolean\", \"list\", \"element\"] as variablekind[]) {\n const option = document.createElement(\"option\");\n option.value = kind;\n option.textContent = kind;\n paramkind.append(option);\n }\n const paramdefault = document.createElement(\"input\");\n paramdefault.type = \"text\";\n paramdefault.placeholder = \"default value\";\n paramgrid.append(paramname, paramkind, paramdefault);\n card.append(paramgrid, button(\"Bind nested param\", async () => {\n if (editorview.model === undefined) return;\n try {\n const parseddefault = paramdefault.value.trim() === \"\" ? undefined : paramkind.value === \"number\" ? Number(paramdefault.value) : paramkind.value === \"boolean\" ? paramdefault.value === \"true\" : paramkind.value === \"list\" ? paramdefault.value.split(\",\").map(part => part.trim()) : paramdefault.value;\n editorview.model = bindparam(editorview.model, inspector.invocation?.block ?? \"\", { name: paramname.value.trim(), kind: paramkind.value as variablekind, ...(parseddefault !== undefined ? { default: parseddefault } : {}) });\n status(`Bound the nested param ${paramname.value.trim()} into ${inspector.invocation?.block ?? \"\"}.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n }\n workfloweditorroot.append(card);\n }\n const saverow = document.createElement(\"div\");\n saverow.className = \"sessionrow\";\n const nameinput = document.createElement(\"input\");\n nameinput.type = \"text\";\n nameinput.value = model.name;\n const originsinput = document.createElement(\"input\");\n originsinput.type = \"text\";\n originsinput.value = model.origins.join(\", \");\n const noteinput = document.createElement(\"input\");\n noteinput.type = \"text\";\n noteinput.placeholder = \"change note for the version timeline\";\n const versioninput = document.createElement(\"input\");\n versioninput.type = \"number\";\n versioninput.min = \"1\";\n versioninput.value = String(model.version + 1);\n saverow.append(nameinput, \" \", originsinput, \" \", versioninput, \" \", noteinput, \" \", button(\"Save canvas as new version\", async () => {\n if (editorview.model === undefined) return;\n editorview.model = { ...editorview.model, name: nameinput.value.trim(), origins: originsinput.value.split(\",\").map(origin => origin.trim()).filter(origin => origin !== \"\"), version: Number(versioninput.value) };\n try {\n const saved = await request({ kind: \"editorsave\", model: editorview.model, note: noteinput.value.trim() }) as { workflowid: string; version: number; steps: number; risk: string };\n status(`Saved ${saved.workflowid} as version ${saved.version}: ${saved.steps} expanded steps graded ${saved.risk} through the full grammar.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n workfloweditorroot.append(saverow);\n } else {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No canvas open; open a composed workflow above or import a workflow file below.\";\n workfloweditorroot.append(empty);\n }\n const palettecard = document.createElement(\"details\");\n palettecard.className = \"sessiongroup\";\n const palettesummary = document.createElement(\"summary\");\n palettesummary.textContent = \"Block palette and step library\";\n palettecard.append(palettesummary);\n const paletteactions = document.createElement(\"div\");\n paletteactions.className = \"actions\";\n const paletteinput = document.createElement(\"input\");\n paletteinput.type = \"text\";\n paletteinput.placeholder = \"search the palette by block or category\";\n paletteinput.value = editorview.palettesearch;\n paletteinput.addEventListener(\"input\", () => { editorview.palettesearch = paletteinput.value; });\n const libraryinput = document.createElement(\"input\");\n libraryinput.type = \"text\";\n libraryinput.placeholder = \"search the step library by kind or category\";\n libraryinput.value = editorview.librarysearch;\n libraryinput.addEventListener(\"input\", () => { editorview.librarysearch = libraryinput.value; });\n paletteactions.append(paletteinput, \" \", libraryinput, \" \", button(\"Load palette and library\", async () => {\n const loaded = await request({ kind: \"steplibrarystore\" }) as { categories: string[]; palette: palettenode[]; library: steplibraryentry[] };\n editorview.palette = loaded.palette;\n editorview.library = loaded.library;\n status(`Loaded ${loaded.palette.length} palette blocks and ${loaded.library.length} library kinds.`);\n await refresh();\n }));\n palettecard.append(paletteactions);\n const palettebody = document.createElement(\"div\");\n palettebody.className = \"editorpalette\";\n if (editorview.palette === undefined) {\n const hint = document.createElement(\"p\");\n hint.textContent = \"Load the palette to browse the curated drop blocks and every reviewed action kind grouped by category.\";\n palettebody.append(hint);\n } else {\n for (const category of palettecategories) {\n const blocks = editorview.palette.filter(node => node.category === category && `${node.label} ${node.kind} ${node.category}`.toLowerCase().includes(editorview.palettesearch.toLowerCase()));\n if (blocks.length === 0) continue;\n const head = document.createElement(\"p\");\n head.className = \"palettecategory\";\n head.textContent = category;\n palettebody.append(head);\n for (const block of blocks) {\n palettebody.append(button(block.label, async () => {\n if (editorview.model === undefined) { status(\"Open a canvas first.\", true); return; }\n try { editorview.model = addnode(editorview.model, { id: block.kind, kind: block.kind as actionkind, label: block.label }); status(`Dropped ${block.label} onto the canvas; the step inspector edits its target and options.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \");\n }\n }\n }\n if (editorview.library !== undefined) {\n for (const category of palettecategories) {\n const kinds = editorview.library.filter(entry => entry.category === category && `${entry.kind} ${entry.category}`.toLowerCase().includes(editorview.librarysearch.toLowerCase()));\n if (kinds.length === 0) continue;\n const head = document.createElement(\"p\");\n head.className = \"palettecategory\";\n head.textContent = `${category} library`;\n palettebody.append(head);\n const list = document.createElement(\"ul\");\n for (const entry of kinds) {\n const line = document.createElement(\"li\");\n line.textContent = `${entry.kind}${entry.optionschema.length > 0 ? ` \u00B7 options: ${entry.optionschema.map(option => `${option.name} ${option.kind}${option.required === true ? \" (required)\" : \"\"}`).join(\", \")}` : \"\"}`;\n list.append(line);\n }\n palettebody.append(list);\n }\n }\n palettecard.append(palettebody);\n workfloweditorroot.append(palettecard);\n if (model !== undefined && editor !== undefined) {\n const versioncard = document.createElement(\"details\");\n versioncard.className = \"sessiongroup\";\n const versionopen = editorview.diff !== undefined;\n if (versionopen) versioncard.open = true;\n const versionsummary = document.createElement(\"summary\");\n versionsummary.textContent = `Version timeline (${editor.versions.filter(entry => entry.workflowid === editorview.workflowid).length} versions of this workflow)`;\n versioncard.append(versionsummary);\n for (const version of editor.versions.filter(entry => entry.workflowid === editorview.workflowid)) {\n const line = document.createElement(\"p\");\n line.className = \"diffrow\";\n line.textContent = `v${version.version} \u00B7 ${new Date(version.createdat).toISOString()} \u00B7 ${version.steps} steps \u00B7 ${version.risk ?? \"ungraded\"}${version.rollback === true ? \" \u00B7 rollback\" : \"\"} \u00B7 ${version.note}`;\n line.append(\" \", button(\"Roll back here\", async () => {\n try {\n const rolled = await request({ kind: \"rollbackversion\", workflowid: editorview.workflowid, version: version.version }) as { version: number; reviewstate: string };\n status(`Rolled back to v${version.version}; stored as v${rolled.version} and ${rolled.reviewstate} until the rollback review approves it.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n versioncard.append(line);\n }\n const diffrow = document.createElement(\"div\");\n diffrow.className = \"actions\";\n const frominput = document.createElement(\"input\");\n frominput.type = \"number\";\n frominput.min = \"1\";\n frominput.placeholder = \"from\";\n const toinput = document.createElement(\"input\");\n toinput.type = \"number\";\n toinput.min = \"1\";\n toinput.placeholder = \"to\";\n diffrow.append(frominput, \" \", toinput, \" \", button(\"Diff versions\", async () => {\n try {\n const diff = await request({ kind: \"diffversions\", workflowid: editorview.workflowid, from: Number(frominput.value), to: Number(toinput.value) }) as versiondiff;\n editorview.diff = diff;\n status(`Diffed v${diff.from} into v${diff.to}: ${diff.added.length} added, ${diff.removed.length} removed, ${diff.changed.length} changed.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n versioncard.append(diffrow);\n if (editorview.diff !== undefined) {\n const diff = editorview.diff;\n const card = document.createElement(\"div\");\n card.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Version diff v${diff.from} \u2192 v${diff.to}`;\n card.append(headline);\n for (const added of diff.added) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"added\"; line.textContent = `+ ${added.stepid} (${added.kind}) ${added.label}`; card.append(line); }\n for (const removed of diff.removed) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"removed\"; line.textContent = `- ${removed.stepid} (${removed.kind}) ${removed.label}`; card.append(line); }\n for (const changed of diff.changed) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"changed\"; line.textContent = `~ ${changed.stepid} (${changed.kind}) ${changed.label}: ${changed.changes.join(\", \")}`; card.append(line); }\n card.append(button(\"Close diff\", async () => { editorview.diff = undefined; await refresh(); }));\n versioncard.append(card);\n }\n workfloweditorroot.append(versioncard);\n const backgroundrow = document.createElement(\"div\");\n backgroundrow.className = \"actions\";\n const backgroundcheck = document.createElement(\"input\");\n backgroundcheck.type = \"checkbox\";\n backgroundcheck.checked = editor.backgroundruns[editorview.workflowid] === true;\n const backgroundlabel = document.createElement(\"label\");\n backgroundlabel.append(backgroundcheck, \" keep runs of this workflow executing with the panel closed (checkpoints restore on every worker wake)\");\n backgroundrow.append(backgroundlabel);\n backgroundrow.append(button(\"Apply background toggle\", async () => {\n const result = await request({ kind: \"setbackgroundrun\", workflowid: editorview.workflowid, enabled: backgroundcheck.checked }) as { enabled: boolean };\n status(result.enabled ? \"Background runs stay alive with the panel closed; every step checkpoints.\" : \"Background runs off; a closed panel pauses the next run at its last checkpoint.\");\n await refresh();\n }));\n workfloweditorroot.append(backgroundrow);\n }\n if (context.workflow !== undefined) {\n const logcard = document.createElement(\"details\");\n logcard.className = \"sessiongroup\";\n const logsummary = document.createElement(\"summary\");\n logsummary.textContent = `Run log and variable inspector of the newest run (${context.workflow.log.length} entries)`;\n logcard.append(logsummary);\n const breakpoints = new Set([...(editor?.breakpoints ?? []), ...(context.workflow.workflows.find(record => record.id === editorview.workflowid)?.steps.flatMap(step => step.breakpoint === true ? [step.id] : []) ?? [])]);\n for (const entry of context.workflow.log) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.state} \u00B7 ${entry.label}${breakpoints.has(entry.stepid) ? \" \u00B7 breakpoint\" : \"\"} \u00B7 ${entry.duration} ms \u00B7 ${entry.summary}`;\n line.dataset.class = entry.state === \"failed\" || entry.state === \"refused\" ? \"changed\" : \"added\";\n logcard.append(line);\n }\n if (context.workflow.log.length === 0) { const empty = document.createElement(\"p\"); empty.textContent = \"No run log entry yet; run the workflow from the workflows view.\"; logcard.append(empty); }\n for (const scope of context.workflow.scopes) {\n const line = document.createElement(\"p\");\n line.textContent = `Scope ${scope.name}: ${scope.variables.length === 0 ? \"no variable\" : scope.variables.map(variable => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(\", \")}]` : String(variable.value)} (${variable.kind})`).join(\" \u00B7 \")}`;\n logcard.append(line);\n }\n workfloweditorroot.append(logcard);\n }\n const historycard = document.createElement(\"details\");\n historycard.className = \"sessiongroup\";\n if (editorview.history !== undefined) historycard.open = true;\n const historysummary = document.createElement(\"summary\");\n historysummary.textContent = `Run history (${editorview.history?.length ?? editor?.history.length ?? 0} entries)`;\n historycard.append(historysummary);\n const historyfilters = document.createElement(\"div\");\n historyfilters.className = \"actions\";\n const workflowselect = document.createElement(\"select\");\n const anyoption = document.createElement(\"option\");\n anyoption.value = \"\";\n anyoption.textContent = \"every workflow\";\n workflowselect.append(anyoption);\n for (const record of workflows) { const option = document.createElement(\"option\"); option.value = record.id; option.textContent = record.name; workflowselect.append(option); }\n workflowselect.value = editorview.historyfilter.workflowid;\n const outcomeinput = document.createElement(\"input\");\n outcomeinput.type = \"text\";\n outcomeinput.placeholder = \"outcome filter\";\n outcomeinput.value = editorview.historyfilter.outcome;\n historyfilters.append(workflowselect, \" \", outcomeinput, \" \", button(\"Apply history filters\", async () => {\n editorview.historyfilter = { workflowid: workflowselect.value, outcome: outcomeinput.value.trim() };\n try {\n const report = await request({ kind: \"runhistory\", ...(workflowselect.value !== \"\" ? { workflowid: workflowselect.value } : {}), ...(outcomeinput.value.trim() !== \"\" ? { outcome: outcomeinput.value.trim() } : {}) }) as { entries: runhistoryentry[] };\n editorview.history = report.entries;\n status(`Run history: ${report.entries.length} entries match the filters.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n historyfilters.append(button(\"Keep every entry\", async () => { await request({ kind: \"setrunhistoryretention\" }); status(\"Run history keeps every entry; no code ceiling applies.\"); await refresh(); }));\n historycard.append(historyfilters);\n const historyentries = editorview.history ?? editor?.history ?? [];\n for (const entry of historyentries.slice(0, 40)) {\n const line = document.createElement(\"div\");\n line.className = \"historyrow\";\n line.dataset.outcome = entry.outcome;\n const detail = document.createElement(\"p\");\n detail.textContent = `${entry.outcome} \u00B7 ${entry.steps}/${entry.total} steps \u00B7 ${entry.duration} ms \u00B7 ${entry.cause}${entry.dryrun === true ? \" \u00B7 dry run\" : \"\"} \u00B7 ${new Date(entry.startedat).toISOString()}`;\n line.append(detail);\n historycard.append(line);\n }\n workfloweditorroot.append(historycard);\n const filecard = document.createElement(\"details\");\n filecard.className = \"sessiongroup\";\n const filesummary = document.createElement(\"summary\");\n filesummary.textContent = \"Import, export and template sharing\";\n filecard.append(filesummary);\n const formatselect = document.createElement(\"select\");\n for (const format of [\"json\", \"yaml\"] as exportformat[]) { const option = document.createElement(\"option\"); option.value = format; option.textContent = format; formatselect.append(option); }\n const contentsinput = document.createElement(\"textarea\");\n contentsinput.rows = 4;\n contentsinput.placeholder = \"paste a workflow file to import\";\n const filenameinput = document.createElement(\"input\");\n filenameinput.type = \"text\";\n filenameinput.placeholder = \"source filename\";\n const importactions = document.createElement(\"div\");\n importactions.className = \"actions\";\n importactions.append(contentsinput, \" \", filenameinput, \" \", formatselect, \" \", button(\"Import workflow file\", async () => {\n if (contentsinput.value.trim() === \"\") { status(\"Paste the workflow file contents first.\", true); return; }\n try {\n const imported = await request({ kind: \"importworkflow\", contents: contentsinput.value, format: formatselect.value, ...(filenameinput.value.trim() !== \"\" ? { filename: filenameinput.value.trim() } : {}) }) as { importid: string; workflowid: string; name: string; version: number; steps: number; risk: string; templates: number };\n const review = await request({ kind: \"workflowreview\", workflowid: imported.workflowid }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> };\n editorview.importreview = { importid: imported.importid, workflowid: imported.workflowid, name: imported.name, version: imported.version, risk: imported.risk, steps: review.steps };\n status(`Imported ${imported.name} v${imported.version} with ${imported.steps} steps and ${imported.templates} templates; review before activation.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(importactions);\n if (editorview.importreview !== undefined) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Import review of ${editorview.importreview.name} v${editorview.importreview.version} (${editorview.importreview.risk} for review): every expanded step shows before activation and nothing runs until approval.`;\n review.append(headline);\n const list = document.createElement(\"ol\");\n for (const step of editorview.importreview.steps) { const line = document.createElement(\"li\"); line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.target !== undefined ? ` \u00B7 ${step.target}` : \"\"})`; list.append(line); }\n review.append(list);\n review.append(button(\"Approve import\", async () => {\n try { const approved = await request({ kind: \"approveimport\", importid: editorview.importreview?.importid }) as { reviewstate: string }; status(`Import approved: ${approved.reviewstate}; the workflow runs behind the same gates.`); editorview.importreview = undefined; } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \", button(\"Reject import\", async () => {\n try { await request({ kind: \"rejectimport\", importid: editorview.importreview?.importid }); status(\"Import rejected; the pending record left the library.\"); editorview.importreview = undefined; } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(review);\n }\n for (const pending of editor?.imports ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `Pending import ${pending.name} v${pending.version} (${pending.steps} steps, ${pending.risk})${pending.filename !== undefined ? ` from ${pending.filename}` : \"\"}`;\n line.append(\" \", button(\"Review steps\", async () => {\n try {\n const steps = await request({ kind: \"workflowreview\", workflowid: pending.workflowid }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> };\n editorview.importreview = { importid: pending.id, workflowid: pending.workflowid, name: pending.name, version: pending.version, risk: pending.risk, steps: steps.steps };\n status(`Import review of ${pending.name}: ${steps.steps.length} expanded steps.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(line);\n }\n const exportrow = document.createElement(\"div\");\n exportrow.className = \"actions\";\n const noteinput = document.createElement(\"input\");\n noteinput.type = \"text\";\n noteinput.placeholder = \"change note inside the file\";\n exportrow.append(noteinput, \" \", button(\"Export open workflow\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n try {\n const exported = await request({ kind: \"exportworkflow\", workflowid: editorview.workflowid, format: formatselect.value, ...(noteinput.value.trim() !== \"\" ? { note: noteinput.value.trim() } : {}) }) as { contents: string; filename: string; format: string };\n savefile(exported.filename, exported.contents);\n status(`Exported ${exported.filename} (${exported.contents.length} characters, ${exported.format}); the export review held every secret back.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n }), \" \", button(\"Share with templates\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n try {\n const shared = await request({ kind: \"shareworkflow\", workflowid: editorview.workflowid, format: formatselect.value, ...(noteinput.value.trim() !== \"\" ? { note: noteinput.value.trim() } : {}) }) as { contents: string; filename: string };\n savefile(shared.filename, shared.contents);\n status(`Packed the share bundle ${shared.filename}; templates travel with the workflow.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n }));\n filecard.append(exportrow);\n workfloweditorroot.append(filecard);\n const watchdogcard = document.createElement(\"details\");\n watchdogcard.className = \"sessiongroup\";\n const watchdogsummary = document.createElement(\"summary\");\n const watchdogconfig = editor?.watchdog.config;\n watchdogsummary.textContent = `Watchdog status (${editor?.watchdog.events.length ?? 0} events)`;\n watchdogcard.append(watchdogsummary);\n const watchdoggrid = document.createElement(\"div\");\n watchdoggrid.className = \"editorgrid\";\n const enabledcheck = document.createElement(\"input\");\n enabledcheck.type = \"checkbox\";\n enabledcheck.checked = watchdogconfig?.enabled === true;\n const thresholdinput = document.createElement(\"input\");\n thresholdinput.type = \"number\";\n thresholdinput.min = \"1\";\n thresholdinput.placeholder = \"stall threshold ms\";\n thresholdinput.value = watchdogconfig !== undefined ? String(watchdogconfig.stallthreshold) : \"\";\n const actionselect = document.createElement(\"select\");\n for (const action of [\"retry\", \"pause\", \"cancel\"]) { const option = document.createElement(\"option\"); option.value = action; option.textContent = action; actionselect.append(option); }\n actionselect.value = watchdogconfig?.action ?? \"pause\";\n const zombieinput = document.createElement(\"input\");\n zombieinput.type = \"number\";\n zombieinput.min = \"1\";\n zombieinput.placeholder = \"zombie window ms\";\n zombieinput.value = watchdogconfig?.zombiewindow !== undefined ? String(watchdogconfig.zombiewindow) : \"\";\n for (const [labeltext, control] of [[\"enabled\", enabledcheck], [\"stall threshold ms\", thresholdinput], [\"recovery action\", actionselect], [\"zombie window ms\", zombieinput]] as Array<[string, HTMLElement]>) { const fieldlabel = document.createElement(\"label\"); fieldlabel.textContent = labeltext; fieldlabel.append(control); watchdoggrid.append(fieldlabel); }\n watchdogcard.append(watchdoggrid);\n const watchdogactions = document.createElement(\"div\");\n watchdogactions.className = \"actions\";\n watchdogactions.append(button(\"Save watchdog config\", async () => {\n try {\n await request({ kind: \"setwatchdog\", config: { enabled: enabledcheck.checked, stallthreshold: Number(thresholdinput.value), action: actionselect.value as \"retry\" | \"pause\" | \"cancel\", ...(zombieinput.value.trim() !== \"\" ? { zombiewindow: Number(zombieinput.value) } : {}) } });\n status(\"Watchdog saved; thresholds stay user values with no code ceiling.\");\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \", button(\"Scan now\", async () => {\n try { const scan = await request({ kind: \"watchdogscan\" }) as { events: watchdogrecord[] }; status(`Watchdog scan: ${scan.events.length} stalled or zombie run${scan.events.length === 1 ? \"\" : \"s\"} recovered.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n watchdogcard.append(watchdogactions);\n for (const event of (editor?.watchdog.events ?? []).slice(0, 15)) {\n const line = document.createElement(\"p\");\n line.textContent = `${event.verdict} \u00B7 ${event.action} \u00B7 ${new Date(event.at).toISOString()} \u00B7 ${event.outcome}`;\n watchdogcard.append(line);\n }\n workfloweditorroot.append(watchdogcard);\n const overridecard = document.createElement(\"details\");\n overridecard.className = \"sessiongroup\";\n const overridesummary = document.createElement(\"summary\");\n overridesummary.textContent = `Per site policy overrides (${editor?.overrides.length ?? 0})`;\n overridecard.append(overridesummary);\n const overridegrid = document.createElement(\"div\");\n overridegrid.className = \"editorgrid\";\n const patterninput = document.createElement(\"input\");\n patterninput.type = \"text\";\n patterninput.placeholder = \"https://origin or https://*.origin\";\n const knobinputs: Array<[string, HTMLInputElement]> = [];\n for (const knob of [\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"]) {\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.min = \"1\";\n input.placeholder = knob;\n knobinputs.push([knob, input]);\n const fieldlabel = document.createElement(\"label\");\n fieldlabel.textContent = knob;\n fieldlabel.append(input);\n overridegrid.append(fieldlabel);\n }\n const patternlabel = document.createElement(\"label\");\n patternlabel.textContent = \"origin pattern\";\n patternlabel.append(patterninput);\n overridegrid.prepend(patternlabel);\n overridecard.append(overridegrid, button(\"Attach override\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n const deltas: Record<string, number> = {};\n for (const [knob, input] of knobinputs) if (input.value.trim() !== \"\" && Number.isFinite(Number(input.value)) && Number(input.value) > 0) deltas[knob] = Number(input.value);\n try { await request({ kind: \"setsiteoverride\", workflowid: editorview.workflowid, pattern: patterninput.value.trim(), deltas }); status(`Attached the override ${patterninput.value.trim()} with ${Object.keys(deltas).length} knob delta${Object.keys(deltas).length === 1 ? \"\" : \"s\"}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n for (const override of editor?.overrides ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `${override.pattern} of ${override.workflowid}: ${Object.entries(override.deltas).map(([knob, delta]) => `${knob} ${delta}`).join(\", \") || \"no delta\"}`;\n line.append(\" \", button(\"Remove override\", async () => { try { await request({ kind: \"removesiteoverride\", id: override.id }); status(`Removed the override ${override.pattern}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n overridecard.append(line);\n }\n workfloweditorroot.append(overridecard);\n}\n\n\n/** Renders the trigger section: every armed rule grouped per workflow with its enable and disable toggle, the next scheduled fire of cron and interval rules, the fire history, the visit rule creation from the current page, rule duplication to a second workflow, the manual run step preview with approve and cancel, webhook rule status with secret rotation and the fire retention setting. */\nfunction rendertriggers(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[] }; trigger?: { rules: Array<{ id: string; kind: string; workflowid: string; workflowname?: string; label: string; enabled: boolean; paused?: boolean; cooldown: number; lastfireat?: number; nextfireat?: number; fires: number; launches: number; suppressions: number; summary: Record<string, unknown> }>; queued: number }; triggerretention?: number }): void {\n if (!triggersroot) return;\n triggersroot.replaceChildren();\n const rules = context.trigger?.rules ?? [];\n const queued = context.trigger?.queued ?? 0;\n const workflows = context.workflow?.workflows ?? [];\n const title = document.createElement(\"p\");\n title.textContent = `${rules.length} armed rule${rules.length === 1 ? \"\" : \"s\"} across ${new Set(rules.map(rule => rule.workflowid)).size} workflow${new Set(rules.map(rule => rule.workflowid)).size === 1 ? \"\" : \"s\"} \u00B7 ${queued} queued fire${queued === 1 ? \"\" : \"s\"}${context.session?.pausedat !== undefined ? \" held while the session is paused\" : \"\"}.`;\n triggersroot.append(title);\n const byworkflow = new Map<string, typeof rules>();\n for (const rule of rules) {\n const group = byworkflow.get(rule.workflowid) ?? [];\n group.push(rule);\n byworkflow.set(rule.workflowid, group);\n }\n for (const [workflowid, group] of byworkflow) {\n const workflowname = group[0]?.workflowname ?? workflowid;\n const box = document.createElement(\"details\");\n box.className = \"sessiongroup\";\n box.open = true;\n const summary = document.createElement(\"summary\");\n summary.textContent = `${workflowname} \u00B7 ${group.length} rule${group.length === 1 ? \"\" : \"s\"}`;\n box.append(summary);\n for (const rule of group) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = rule.enabled ? (rule.paused === true ? \"paused\" : \"enabled\") : \"disabled\";\n const match = rule.summary.pattern !== undefined ? String(rule.summary.pattern) : rule.summary.origins !== undefined ? (rule.summary.origins as string[]).join(\", \") : rule.summary.cron !== undefined ? `${String(rule.summary.cron)}${rule.summary.timezone !== undefined ? ` (${String(rule.summary.timezone)})` : \"\"}` : rule.summary.period !== undefined ? `every ${String(rule.summary.period)} ms${rule.summary.jitter !== undefined ? ` \u00B1 ${String(rule.summary.jitter)} ms` : \"\"}` : rule.summary.title !== undefined ? String(rule.summary.title) : rule.summary.command !== undefined ? String(rule.summary.command) : rule.summary.events !== undefined ? (rule.summary.events as string[]).join(\", \") : rule.kind === \"urllist\" ? `${(rule.summary.urls as string[] | undefined)?.length ?? 0} urls` : rule.kind === \"webhook\" ? `webhook with ${String(rule.summary.fields ?? 0)} schema fields` : \"toolbar button\";\n headline.append(`${rule.label} \u00B7 ${rule.kind} \u00B7 ${match} \u00B7 cooldown ${rule.cooldown} ms \u00B7 ${rule.fires} fire${rule.fires === 1 ? \"\" : \"s\"}, ${rule.launches} launch${rule.launches === 1 ? \"\" : \"es\"}, ${rule.suppressions} suppressed${rule.nextfireat !== undefined ? ` \u00B7 next fire ${new Date(rule.nextfireat).toISOString()}` : \"\"}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(rule.enabled ? \"Disable\" : \"Enable\", async () => { await request({ kind: \"toggletrigger\", ruleid: rule.id, enabled: !rule.enabled }); status(`The ${rule.kind} rule is now ${rule.enabled ? \"disabled\" : \"enabled\"}.`); await refresh(); }));\n actions.append(\" \", button(\"Fire history\", async () => { const result = await request({ kind: \"triggerhistory\", ruleid: rule.id }) as { fires: Array<{ id: string; ruleid: string; at: number; cause: string; url?: string; title?: string }> }; triggerview.history = result.fires; status(`Fire history: ${result.fires.length} fire record${result.fires.length === 1 ? \"\" : \"s\"} of the ${rule.kind} rule.`); await refresh(); }));\n actions.append(\" \", button(\"Fire manually\", async () => { const result = await request({ kind: \"firetrigger\", ruleid: rule.id }) as { fired: boolean; queued?: boolean; suppressed?: string }; status(result.fired ? `The ${rule.kind} rule fired${result.queued === true ? \" and queued for the busy run\" : \"\"}.` : `The ${rule.kind} rule suppressed the fire: ${result.suppressed ?? \"review gate\"}.`); await refresh(); }));\n if (rule.kind === \"webhook\") actions.append(\" \", button(\"Rotate secret\", async () => { const result = await request({ kind: \"rotatetriggersecret\", ruleid: rule.id }) as { secret: string }; status(`The webhook secret rotated to ${result.secret}; it was shown once and never leaves the store.`); await refresh(); }));\n if (workflows.length > 1) actions.append(\" \", button(\"Duplicate to second workflow\", async () => { const target = workflows.find(record => record.id !== rule.workflowid); if (!target) { status(\"No second composed workflow exists to duplicate the rule to.\", true); return; } await request({ kind: \"duplicatetrigger\", ruleid: rule.id, workflowid: target.id }); status(`Duplicated the ${rule.kind} rule to ${target.name}.`); await refresh(); }));\n row.append(actions);\n box.append(row);\n }\n const workflowactions = document.createElement(\"div\");\n workflowactions.className = \"actions\";\n workflowactions.append(button(\"Create visit rule from current page\", async () => { await request({ kind: \"createvisitrule\", workflowid }); status(`Armed a visit rule of the current page origin for ${workflowname}.`); await refresh(); }));\n workflowactions.append(\" \", button(\"Manual run preview\", async () => { const result = await request({ kind: \"manualrun\", workflowid }) as { manualrun: { id: string; workflowid: string; preview: Array<{ stepid: string; kind: string; label: string; block?: string; control?: Record<string, unknown> }> }; at: number }; triggerview.manual = { ...result.manualrun, at: Date.now() }; status(`Manual run preview: ${result.manualrun.preview.length} steps of ${workflowname}; nothing runs before the confirmation.`); await refresh(); }));\n box.append(workflowactions);\n triggersroot.append(box);\n }\n if (rules.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No armed trigger rule yet; arm a reviewed rule of any family or create a visit rule from the current page.\";\n triggersroot.append(empty);\n }\n if (triggerview.history !== undefined) {\n const history = document.createElement(\"details\");\n history.className = \"sessiongroup\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Fire history (${triggerview.history.length} records)`;\n history.append(summary);\n for (const fire of triggerview.history.slice(0, 25)) {\n const line = document.createElement(\"p\");\n line.textContent = `${new Date(fire.at).toISOString()} \u00B7 ${fire.cause}${fire.url !== undefined ? ` \u00B7 ${fire.url}` : \"\"}${fire.title !== undefined ? ` \u00B7 ${fire.title}` : \"\"}`;\n history.append(line);\n }\n triggersroot.append(history);\n }\n if (triggerview.manual !== undefined) {\n const preview = document.createElement(\"div\");\n preview.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Manual run step preview: ${triggerview.manual.preview.length} expanded step${triggerview.manual.preview.length === 1 ? \"\" : \"s\"}; approve or cancel before anything runs.`;\n preview.append(headline);\n for (const step of triggerview.manual.preview) {\n const line = document.createElement(\"p\");\n line.textContent = `${step.stepid} \u00B7 ${step.kind} \u00B7 ${step.label}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.control !== undefined ? ` \u00B7 ${Object.entries(step.control).map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(\", \") : String(value)}`).join(\" \u00B7 \")}` : \"\"}`;\n preview.append(line);\n }\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve manual run\", async () => { const result = await request({ kind: \"confirmmanualrun\", previewid: triggerview.manual?.id, confirmed: true }) as { confirmed: boolean; runid?: string; state?: string }; status(`Manual run approved and launched${result.runid !== undefined ? ` as run ${result.runid}` : \"\"}; the run ended ${result.state ?? \"running\"}.`); triggerview.manual = undefined; await refresh(); }));\n actions.append(\" \", button(\"Cancel manual run\", async () => { await request({ kind: \"confirmmanualrun\", previewid: triggerview.manual?.id, confirmed: false }); status(\"Manual run cancelled after the step preview; nothing ran.\"); triggerview.manual = undefined; await refresh(); }));\n preview.append(actions);\n triggersroot.append(preview);\n }\n const settings = document.createElement(\"details\");\n settings.className = \"sessiongroup\";\n const settingsummary = document.createElement(\"summary\");\n settingsummary.textContent = \"Trigger settings\";\n settings.append(settingsummary);\n const retention = document.createElement(\"p\");\n retention.textContent = `Fire record retention: ${context.triggerretention === undefined ? \"keep every fire record\" : `${context.triggerretention} record${context.triggerretention === 1 ? \"\" : \"s\"}`}; the rule counters always survive and no code ceiling applies.`;\n settings.append(retention);\n const retentionactions = document.createElement(\"div\");\n retentionactions.className = \"actions\";\n retentionactions.append(button(\"Keep every fire record\", async () => { await request({ kind: \"settriggerretention\" }); status(\"Trigger fire retention keeps every record.\"); await refresh(); }));\n retentionactions.append(\" \", button(\"Keep last 100 fire records\", async () => { await request({ kind: \"settriggerretention\", retention: 100 }); status(\"Trigger fire retention keeps the last 100 records.\"); await refresh(); }));\n settings.append(retentionactions);\n triggersroot.append(settings);\n}\n\n/** Renders the agent protocol view: the mcp server status with start and stop, the localhost bind state and port, the connected clients with their transports, negotiated capabilities and pairing prompt, the disconnect control, the tool catalog grouped by namespace, the stdio bridge status with restart and the recent tool calls with caller and outcome. */\nfunction renderagentprotocol(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number }; mcp?: { state: string; config: { bind?: string; port: number; transports: string[]; framesize?: number; queuedepth?: number; callretention?: number; enabled: boolean; remote?: boolean }; bind: string; port: number; localhost: boolean; clients: Array<{ id: string; transport: string; paired: boolean; connectedat: number; capabilities?: { protocolversion: string; toolversion: number; tools: number; transports: string[] }; pairedat?: number }>; bridge?: { id: string; host: string; connected: boolean; restarts: number; received: number; sent: number; startedat: number }; calls: Array<{ id: string; clientid: string; tool: string; origin: string; ok: boolean; code?: string; at: number }>; catalog: { tools: Array<{ name: string; version: number; description: string; risk: string; consentmeta?: string; inputschema: { type: string; properties: Record<string, { type: string; description: string; required?: boolean }>; required: string[] } }> }; launches: Array<{ id: string; host: string; pid: number; restart: boolean; at: number }> } }): void {\n if (!agentprotocolroot) return;\n agentprotocolroot.replaceChildren();\n const mcp = context.mcp;\n if (!mcp) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"The agent protocol state is unknown.\";\n agentprotocolroot.append(empty);\n return;\n }\n const running = mcp.state === \"running\";\n const head = document.createElement(\"p\");\n head.textContent = `Server ${mcp.state} \u00B7 ${mcp.bind}:${mcp.port}${mcp.localhost ? \" (localhost bind)\" : \" (remote bind behind the explicit review)\"} \u00B7 transports ${mcp.config.transports.join(\" and \")} \u00B7 ${mcp.catalog.tools.length} tools \u00B7 ${mcp.clients.length} connected client${mcp.clients.length === 1 ? \"\" : \"s\"}.`;\n agentprotocolroot.append(head);\n const controls = document.createElement(\"div\");\n controls.className = \"actions\";\n controls.append(button(running ? \"Stop server\" : \"Start server\", async () => { await request({ kind: running ? \"mcpserverstop\" : \"mcpserverstart\" }); status(running ? \"The mcp server stopped; no tool call passes the gates.\" : \"The mcp server started on the localhost bind; every client waits for the pairing approval.\"); await refresh(); }));\n const bindinput = document.createElement(\"input\");\n bindinput.placeholder = \"bind address (empty keeps localhost)\";\n bindinput.value = mcp.config.bind ?? \"\";\n const portinput = document.createElement(\"input\");\n portinput.placeholder = \"port\";\n portinput.value = String(mcp.config.port);\n controls.append(\" \", bindinput, \" \", portinput, \" \", button(\"Save config\", async () => { await request({ kind: \"mcpserverconfig\", bind: bindinput.value, port: Number(portinput.value), ...(bindinput.value.trim() !== \"\" && bindinput.value.trim() !== \"127.0.0.1\" && bindinput.value.trim() !== \"localhost\" && bindinput.value.trim() !== \"::1\" ? { remote: true } : {}) }); status(`Saved the mcp server config for ${bindinput.value.trim() === \"\" ? \"127.0.0.1\" : bindinput.value.trim()}:${portinput.value}.`); await refresh(); }));\n agentprotocolroot.append(controls);\n if (mcp.bridge !== undefined) {\n const bridge = document.createElement(\"p\");\n bridge.textContent = `Stdio bridge ${mcp.bridge.connected ? \"connected\" : \"disconnected\"} on the ${mcp.bridge.host} host \u00B7 ${mcp.bridge.restarts} restart${mcp.bridge.restarts === 1 ? \"\" : \"s\"} \u00B7 ${mcp.bridge.received} inbound and ${mcp.bridge.sent} outbound frame${mcp.bridge.sent === 1 ? \"\" : \"s\"}${mcp.launches.length > 0 ? ` \u00B7 last launch pid ${mcp.launches[0]?.pid ?? \"unknown\"}` : \" \u00B7 no host launch reported yet\"}.`;\n agentprotocolroot.append(bridge);\n const bridgeactions = document.createElement(\"div\");\n bridgeactions.className = \"actions\";\n bridgeactions.append(button(\"Restart bridge\", async () => { await request({ kind: \"mcpbridge\", action: \"restart\" }); status(\"The stdio bridge restart ran; the browser exposes the native messaging host only under a native messaging permission.\"); await refresh(); }));\n agentprotocolroot.append(bridgeactions);\n }\n const clientsbox = document.createElement(\"details\");\n clientsbox.className = \"sessiongroup\";\n clientsbox.open = true;\n const clientsummary = document.createElement(\"summary\");\n clientsummary.textContent = `Connected clients (${mcp.clients.length})`;\n clientsbox.append(clientsummary);\n for (const client of mcp.clients) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = client.paired ? \"paired\" : \"waiting for approval\";\n headline.append(`${client.id} \u00B7 ${client.transport}${client.capabilities !== undefined ? ` \u00B7 protocol ${client.capabilities.protocolversion} \u00B7 tool floor ${client.capabilities.toolversion} \u00B7 ${client.capabilities.tools} tools` : \" \u00B7 not negotiated yet\"}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n if (!client.paired) {\n actions.append(button(\"Approve pairing\", async () => { await request({ kind: \"mcpclientdecision\", clientid: client.id, approved: true }); status(`Approved the pairing of the client ${client.id}; its tool calls now pass the same consent gates.`); await refresh(); }));\n actions.append(\" \", button(\"Refuse pairing\", async () => { await request({ kind: \"mcpclientdecision\", clientid: client.id, approved: false }); status(`Refused and disconnected the client ${client.id}.`); await refresh(); }));\n }\n actions.append(button(\"Disconnect\", async () => { await request({ kind: \"mcpclientdisconnect\", clientid: client.id }); status(`Disconnected the client ${client.id}; its record stays for the audit trail.`); await refresh(); }));\n row.append(actions);\n clientsbox.append(row);\n }\n if (mcp.clients.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No connected client yet; a paired client speaks json rpc frames over the stdio bridge or an http post envelope.\";\n clientsbox.append(empty);\n }\n agentprotocolroot.append(clientsbox);\n const catalogbox = document.createElement(\"details\");\n catalogbox.className = \"sessiongroup\";\n const catalogsummary = document.createElement(\"summary\");\n catalogsummary.textContent = `Tool catalog (${mcp.catalog.tools.length} tools by namespace)`;\n catalogbox.append(catalogsummary);\n const bynamespace = new Map<string, typeof mcp.catalog.tools>();\n for (const tool of mcp.catalog.tools) {\n const namespace = tool.name.split(\".\")[0] ?? \"browser\";\n const group = bynamespace.get(namespace) ?? [];\n group.push(tool);\n bynamespace.set(namespace, group);\n }\n for (const [namespace, tools] of bynamespace) {\n const domain = document.createElement(\"details\");\n domain.className = \"sessiongroup\";\n const domainsummary = document.createElement(\"summary\");\n domainsummary.textContent = `${namespace} (${tools.length} tools)`;\n domain.append(domainsummary);\n for (const tool of tools) {\n const line = document.createElement(\"p\");\n line.textContent = `${tool.name} v${tool.version} \u00B7 ${tool.risk} \u00B7 ${tool.description.split(\".\")[0] ?? tool.description}${tool.consentmeta !== undefined ? ` \u00B7 review: ${tool.consentmeta}` : \"\"}`;\n domain.append(line);\n }\n catalogbox.append(domain);\n }\n agentprotocolroot.append(catalogbox);\n const callsbox = document.createElement(\"details\");\n callsbox.className = \"sessiongroup\";\n const callssummary = document.createElement(\"summary\");\n callssummary.textContent = `Recent tool calls (${mcp.calls.length})`;\n callsbox.append(callssummary);\n for (const call of mcp.calls.slice(0, 25)) {\n const line = document.createElement(\"p\");\n line.textContent = `${new Date(call.at).toISOString()} \u00B7 ${call.clientid} \u00B7 ${call.tool} \u00B7 ${call.origin} \u00B7 ${call.ok ? \"ran behind the gates\" : `refused${call.code !== undefined ? ` (${call.code})` : \"\"}`}`;\n callsbox.append(line);\n }\n if (mcp.calls.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No tool call yet; every call records the client, tool and outcome without payloads.\";\n callsbox.append(empty);\n }\n agentprotocolroot.append(callsbox);\n}\n"],
5
- "mappings": "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",
6
- "names": ["node", "node", "next", "node", "record", "interrupted", "body", "frames", "actions", "term", "options", "noteinput"]
4
+ "sourcesContent": ["import type { actionrisk, blockinvocation, delaystep, expressiontype, nestedparam, regexrule, runlogentry, steptemplate, variablebinding, variablekind, variablescope, variablevalue, watchdogconfig, workflowblock, workflowrecord, workflowrun, workflowstep } from \"./types.js\";\nimport type { stepoutcome } from \"./types.js\";\nimport { controlsteps, iscontrolflowkind, validatecontrolpayload } from \"./controlflow.js\";\n\n/**\n * Workflow engine for the 1.1.50 family.\n * Every correlated rule for the reviewed step composition lives in this file: the workflow kind list, the step, block and template normalizers, the composition that validates and freezes a step list, the block expansion that hides no step from review, the pre-run validation of kinds, scopes and bindings, the typed scope stack with shadowing, the variable bindings that link step outputs to names, the expression arithmetic with coercion refusals, the regex extraction with honest no match outcomes, the seeded delay jitter, the run loop with per step checkpoints, the single step execution, the pause, resume and cancel transitions and the pure dry run with read only projections.\n * The engine stays pure: every page, browser and storage effect flows through the injected executor so tests run on plain fixtures, and the risk grading flows through the injected risk callback so the policy table stays the single source of truth.\n */\n\n/** The workflow kinds of the 1.1.50 family: composition, templates, runs, dry runs, jittered delays, element waits, expressions and variable extraction. */\nexport const workflowkinds: string[] = [\"composeworkflow\", \"savetemplate\", \"runworkflow\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\"];\n\n/** The outcome the injected executor returns for one workflow step: control flow executors also return the merged scopes and the iteration runlog entries so the run loop adopts them. */\nexport type stepexecution = { ok: boolean; summary: string; details?: Record<string, unknown>; scopes?: variablescope[]; log?: runlogentry[] };\n\n/** Normalizes one nested parameter of a block invocation: the variable name, the reviewed kind and the optional default value. */\nfunction nestedparamof(value: unknown): nestedparam | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.name)) return undefined;\n if (!variablekinds.includes(candidate.kind as variablekind)) return undefined;\n if (candidate.default !== undefined && ![\"string\", \"number\", \"boolean\"].includes(typeof candidate.default) && !Array.isArray(candidate.default)) return undefined;\n return { name: candidate.name, kind: candidate.kind as variablekind, ...(candidate.default !== undefined ? { default: candidate.default as string | number | boolean | string[] } : {}) };\n}\n\n/** Normalizes one workflow step: id, kind, label, the optional target, value and JSON options, the output bindings, the inline expression, the inline regex rule, the breakpoint marker and the nested block parameters. */\nexport function workflowstepof(value: unknown): workflowstep | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.id !== \"string\" || !candidate.id.trim()) return undefined;\n if (typeof candidate.kind !== \"string\" || !/^[a-z]+$/.test(candidate.kind)) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n if (candidate.target !== undefined && (typeof candidate.target !== \"string\" || !candidate.target)) return undefined;\n if (candidate.value !== undefined && typeof candidate.value !== \"string\") return undefined;\n if (candidate.options !== undefined && typeof candidate.options !== \"string\") return undefined;\n if (candidate.breakpoint !== undefined && typeof candidate.breakpoint !== \"boolean\") return undefined;\n const bindings = Array.isArray(candidate.bindings) ? candidate.bindings.flatMap(binding => bindingof(binding) !== undefined ? [bindingof(binding) as variablebinding] : []) : undefined;\n if (candidate.bindings !== undefined && bindings === undefined) return undefined;\n if (Array.isArray(candidate.bindings) && bindings !== undefined && bindings.length !== (candidate.bindings as unknown[]).length) return undefined;\n const expression = candidate.expression === undefined ? undefined : expressionof(candidate.expression);\n if (candidate.expression !== undefined && expression === undefined) return undefined;\n const extract = candidate.extract === undefined ? undefined : regexruleof(candidate.extract);\n if (candidate.extract !== undefined && extract === undefined) return undefined;\n const params = Array.isArray(candidate.params) ? candidate.params.flatMap(param => nestedparamof(param) !== undefined ? [nestedparamof(param) as nestedparam] : []) : undefined;\n if (candidate.params !== undefined && params === undefined) return undefined;\n if (Array.isArray(candidate.params) && params !== undefined && params.length !== (candidate.params as unknown[]).length) return undefined;\n return { id: candidate.id, kind: candidate.kind as workflowstep[\"kind\"], label: candidate.label, ...(candidate.target !== undefined ? { target: candidate.target } : {}), ...(candidate.value !== undefined ? { value: candidate.value } : {}), ...(candidate.options !== undefined ? { options: candidate.options } : {}), ...(bindings !== undefined && bindings.length > 0 ? { bindings } : {}), ...(expression !== undefined ? { expression } : {}), ...(extract !== undefined ? { extract } : {}), ...(candidate.breakpoint === true ? { breakpoint: true } : {}), ...(params !== undefined && params.length > 0 ? { params } : {}) };\n}\n\n/** Normalizes one block invocation: the referenced block name and the human readable label. */\nexport function blockinvocationof(value: unknown): blockinvocation | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.block !== \"string\" || !candidate.block.trim()) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n const params = Array.isArray(candidate.params) ? candidate.params.flatMap(param => nestedparamof(param) !== undefined ? [nestedparamof(param) as nestedparam] : []) : undefined;\n if (candidate.params !== undefined && params === undefined) return undefined;\n if (Array.isArray(candidate.params) && params !== undefined && params.length !== (candidate.params as unknown[]).length) return undefined;\n return { block: candidate.block, label: candidate.label, ...(params !== undefined && params.length > 0 ? { params } : {}) };\n}\n\n/** Normalizes one reusable workflow block: the unique name, the label and the child steps with nested block invocations. */\nexport function workflowblockof(value: unknown): workflowblock | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.name)) return undefined;\n if (typeof candidate.label !== \"string\" || !candidate.label.trim()) return undefined;\n if (!Array.isArray(candidate.steps)) return undefined;\n const steps: Array<workflowstep | blockinvocation> = [];\n for (const entry of candidate.steps) {\n const step = workflowstepof(entry);\n if (step) { steps.push(step); continue; }\n const invocation = blockinvocationof(entry);\n if (invocation) { steps.push(invocation); continue; }\n return undefined;\n }\n return { name: candidate.name, label: candidate.label, steps };\n}\n\n/** Normalizes one shareable step template: the id, the unique name, the origin, the step and the share time. */\nexport function steptemplateof(value: unknown): steptemplate | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.id !== \"string\" || !candidate.id.trim()) return undefined;\n if (typeof candidate.name !== \"string\" || !candidate.name.trim()) return undefined;\n if (typeof candidate.origin !== \"string\" || !candidate.origin.trim()) return undefined;\n const step = workflowstepof(candidate.step);\n if (!step) return undefined;\n if (typeof candidate.sharedat !== \"number\" || !Number.isFinite(candidate.sharedat)) return undefined;\n return { id: candidate.id, name: candidate.name, origin: candidate.origin, step, sharedat: candidate.sharedat };\n}\n\n/** Normalizes one variable binding that links a step output path to a named variable of a typed kind. */\nfunction bindingof(value: unknown): variablebinding | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.variable !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.variable)) return undefined;\n if (!variablekinds.includes(candidate.kind as variablekind)) return undefined;\n if (typeof candidate.stepid !== \"string\" || !candidate.stepid.trim()) return undefined;\n if (candidate.path !== undefined && (typeof candidate.path !== \"string\" || !candidate.path.trim())) return undefined;\n return { variable: candidate.variable, kind: candidate.kind as variablekind, stepid: candidate.stepid, ...(candidate.path !== undefined ? { path: candidate.path } : {}) };\n}\n\n/** The typed variable kinds of the scope grammar. */\nconst variablekinds: variablekind[] = [\"string\", \"number\", \"boolean\", \"list\", \"element\"];\n\n/** The reviewed expression operators of the workflow grammar. */\nexport const expressionoperators: string[] = [\"add\", \"subtract\", \"multiply\", \"divide\", \"modulo\", \"equal\", \"notequal\", \"less\", \"greater\", \"lessequal\", \"greaterequal\", \"and\", \"or\", \"not\", \"concat\", \"contains\", \"length\"];\n\n/** Normalizes one reviewed expression: the operands, the operator and the result variable with its result kind. */\nexport function expressionof(value: unknown): expressiontype | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n const left = operandof(candidate.left);\n if (!left) return undefined;\n const right = candidate.right === undefined ? undefined : operandof(candidate.right);\n if (candidate.right !== undefined && right === undefined) return undefined;\n if (typeof candidate.operator !== \"string\" || !expressionoperators.includes(candidate.operator)) return undefined;\n if (typeof candidate.result !== \"string\" || !/^[a-z][a-z0-9]*$/.test(candidate.result)) return undefined;\n if (!variablekinds.includes(candidate.resultkind as variablekind)) return undefined;\n return { left, ...(right !== undefined ? { right } : {}), operator: candidate.operator as expressiontype[\"operator\"], result: candidate.result, resultkind: candidate.resultkind as variablekind };\n}\n\n/** Normalizes one expression operand: a variable reference or a literal of a reviewed primitive kind. */\nfunction operandof(value: unknown): { ref?: string; literal?: string | number | boolean } | undefined {\n if (value === undefined) return undefined;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return { literal: value };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.ref === \"string\" && /^[a-z][a-z0-9]*$/.test(candidate.ref)) return { ref: candidate.ref };\n if (typeof candidate.literal === \"string\" || typeof candidate.literal === \"number\" || typeof candidate.literal === \"boolean\") return { literal: candidate.literal };\n return undefined;\n}\n\n/** Normalizes one reviewed regex rule: the pattern, the flag set and the named capture group list. */\nexport function regexruleof(value: unknown): regexrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const candidate = value as Record<string, unknown>;\n if (typeof candidate.pattern !== \"string\" || !candidate.pattern.trim()) return undefined;\n if (typeof candidate.flags !== \"string\" || !/^[dgimsuvy]*$/.test(candidate.flags)) return undefined;\n const groups = Array.isArray(candidate.groups) ? candidate.groups.flatMap(group => typeof group === \"string\" && /^[a-z][a-z0-9]*$/.test(group) ? [group] : []) : [];\n if (candidate.groups !== undefined && groups.length !== (candidate.groups as unknown[]).length) return undefined;\n return { pattern: candidate.pattern, flags: candidate.flags, groups };\n}\n\n/** Flattens nested blocks into one executable step list; every flattened step carries the innermost block name so runs highlight the active block, and the nested parameters of an invocation stamp onto the first step of its region so the run binds them into the block scope. Unknown or cyclic block references are refused. */\nexport function expandblocks(steps: Array<workflowstep | blockinvocation>, blocks: workflowblock[]): workflowstep[] {\n const byname = new Map(blocks.map(block => [block.name, block]));\n const expanded: workflowstep[] = [];\n const visit = (entries: Array<workflowstep | blockinvocation>, path: string[], inside: string | undefined, params?: nestedparam[]): void => {\n let stamped = params === undefined;\n for (const entry of entries) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) {\n const marked = inside === undefined ? entry : { ...entry, block: inside };\n if (!stamped && params !== undefined) { expanded.push({ ...marked, params }); stamped = true; } else expanded.push(marked);\n continue;\n }\n const invocation = blockinvocationof(entry);\n if (!invocation) throw new Error(\"The step list entry is neither a reviewed step nor a block invocation.\");\n if (path.includes(invocation.block)) throw new Error(`The block ${invocation.block} recurs inside itself and cannot expand.`);\n const block = byname.get(invocation.block);\n if (!block) throw new Error(`The block ${invocation.block} is not defined in the workflow.`);\n visit(block.steps, [...path, invocation.block], invocation.block, invocation.params ?? params);\n }\n };\n visit(steps, [], undefined);\n if (expanded.length === 0) throw new Error(\"A workflow needs at least one executable step after block expansion.\");\n return expanded;\n}\n\n/** Composes one workflow record: validates the name, version, origin grants, steps and blocks, expands every block so no step stays hidden, grades the review risk through the injected risk table and freezes the result. */\nexport function composeworkflow(input: { id?: string; name: string; version: number; origins: string[]; steps: Array<workflowstep | blockinvocation>; blocks?: workflowblock[]; now: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): workflowrecord {\n if (typeof input.name !== \"string\" || !input.name.trim()) throw new Error(\"The workflow name must be a non-empty string.\");\n if (typeof input.version !== \"number\" || !Number.isInteger(input.version) || input.version < 1) throw new Error(\"The workflow version must be a positive integer.\");\n if (!Array.isArray(input.origins) || input.origins.length === 0) throw new Error(\"A workflow needs at least one granted HTTPS origin.\");\n const origins = input.origins.map(origin => {\n try { return new URL(origin).origin; } catch { throw new Error(`The workflow origin ${origin} is not a valid url.`); }\n });\n if (origins.some(origin => !origin.startsWith(\"https://\"))) throw new Error(\"Workflow origins must use HTTPS.\");\n const blocks = input.blocks ?? [];\n if (blocks.some((block, index) => blocks.findIndex(other => other.name === block.name) !== index)) throw new Error(\"Workflow block names must stay unique.\");\n for (const entry of input.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) {\n if (input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} is not a reviewed action kind.`);\n }\n }\n for (const block of blocks) for (const entry of block.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} inside block ${block.name} is not a reviewed action kind.`);\n }\n const steps = expandblocks(input.steps, blocks);\n for (const step of steps) {\n if (input.kindallowed && !input.kindallowed(step.kind)) throw new Error(`The workflow step kind ${step.kind} is not a reviewed action kind.`);\n if (iscontrolflowkind(step.kind)) {\n validatecontrolpayload(step);\n for (const child of controlsteps(step)) {\n if (input.kindallowed && !input.kindallowed(child.kind)) throw new Error(`The workflow step kind ${child.kind} inside the control payload of ${step.id} is not a reviewed action kind.`);\n }\n }\n if (step.bindings) for (const binding of step.bindings) {\n if (!steps.some(other => other.id === binding.stepid)) throw new Error(`The binding of ${binding.variable} references the unknown step ${binding.stepid}.`);\n }\n }\n const riskof = input.riskof ?? ((): actionrisk => \"sensitive\");\n const gradedkinds = steps.flatMap(step => [step.kind, ...controlsteps(step).map(child => child.kind)]);\n const risk: actionrisk = gradedkinds.some(kind => riskof(kind) === \"sensitive\") ? \"sensitive\" : gradedkinds.some(kind => riskof(kind) === \"interaction\") ? \"interaction\" : \"read\";\n const record: workflowrecord = { id: input.id ?? crypto.randomUUID(), name: input.name, version: input.version, origins: [...new Set(origins)], steps, blocks, risk, createdat: input.now };\n return deepfreeze(record);\n}\n\n/** Freezes a composed workflow record so later mutations of the shared object graph never rewrite a reviewed workflow. */\nfunction deepfreeze(record: workflowrecord): workflowrecord {\n for (const step of record.steps) Object.freeze(step);\n for (const block of record.blocks) for (const entry of block.steps) if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) Object.freeze(entry);\n Object.freeze(record.blocks);\n Object.freeze(record.steps);\n return Object.freeze(record);\n}\n\n/** Validates a composed workflow before any run: the expanded step list, every step kind against the injected allowlist, the bindings against earlier steps and every variable reference against the bindings, the inputs and the root scope. */\nexport function validateworkflow(record: workflowrecord, options?: { kindallowed?: (kind: string) => boolean; inputs?: string[] }): { allowed: boolean; reason?: string } {\n if (record.steps.length === 0) return { allowed: false, reason: \"A workflow needs at least one reviewed step.\" };\n const defined = new Set(options?.inputs ?? []);\n const byid = new Map(record.steps.map((step, index) => [step.id, { step, index }]));\n for (let index = 0; index < record.steps.length; index += 1) {\n const step = record.steps[index] as workflowstep;\n if (options?.kindallowed && !options.kindallowed(step.kind)) return { allowed: false, reason: `The workflow step kind ${step.kind} is not a reviewed action kind.` };\n if (step.bindings) for (const binding of step.bindings) {\n const source = byid.get(binding.stepid);\n if (!source) return { allowed: false, reason: `The binding of ${binding.variable} references the unknown step ${binding.stepid}.` };\n if (source.index >= index) return { allowed: false, reason: `The binding of ${binding.variable} must link an earlier step than ${step.id}.` };\n defined.add(binding.variable);\n }\n if (step.expression) {\n for (const operand of [step.expression.left, step.expression.right]) {\n if (operand?.ref && !defined.has(operand.ref)) return { allowed: false, reason: `The expression of step ${step.id} references the undefined variable ${operand.ref}.` };\n }\n defined.add(step.expression.result);\n }\n if (step.extract) for (const group of step.extract.groups) defined.add(group);\n }\n return { allowed: true };\n}\n\n/** Opens one child scope for a block invocation; the parent chain stays intact so resolution walks outward. */\nexport function pushscope(scopes: variablescope[], name: string, parent?: string): variablescope[] {\n return [...scopes, { name, variables: [], ...(parent !== undefined ? { parent } : {}) }];\n}\n\n/** Closes the newest scope and keeps every parent scope intact. */\nexport function popscope(scopes: variablescope[]): variablescope[] {\n if (scopes.length === 0) return scopes;\n return scopes.slice(0, -1);\n}\n\n/** Resolves one variable from the nearest scope outward through the parent chain; shadowing follows the newest scope first. */\nexport function resolvevariable(scopes: variablescope[], name: string): variablevalue | undefined {\n for (let index = scopes.length - 1; index >= 0; index -= 1) {\n const scope = scopes[index] as variablescope;\n const found = scope.variables.find(variable => variable.name === name);\n if (found) return found;\n if (scope.parent === undefined) continue;\n const parentindex = scopes.findIndex(candidate => candidate.name === scope.parent);\n if (parentindex >= 0 && parentindex < index) {\n const inherited = resolvevariable([scopes[parentindex] as variablescope], name);\n if (inherited) return inherited;\n }\n }\n return undefined;\n}\n\n/** Writes one variable into the newest scope, replacing a same named value of that scope only. */\nexport function setvariable(scopes: variablescope[], name: string, kind: variablekind, value: string | number | boolean | string[], now: number): variablescope[] {\n if (scopes.length === 0) scopes = [{ name: \"root\", variables: [] }];\n const target = scopes[scopes.length - 1] as variablescope;\n const variables = [...target.variables.filter(variable => variable.name !== name), { name, kind, value, setat: now }];\n return [...scopes.slice(0, -1), { ...target, variables }];\n}\n\n/** Coerces one raw binding value into the reviewed variable kind; mismatched values are refused instead of silently rewritten. */\nfunction coercevariable(value: unknown, kind: variablekind): string | number | boolean | string[] {\n if (kind === \"number\") {\n const parsed = typeof value === \"number\" ? value : typeof value === \"string\" && value.trim() !== \"\" ? Number(value) : NaN;\n if (!Number.isFinite(parsed)) throw new Error(\"The bound value is not a finite number.\");\n return parsed;\n }\n if (kind === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw new Error(\"The bound value is not a boolean.\");\n }\n if (kind === \"list\") {\n if (Array.isArray(value)) return value.map(item => String(item));\n if (typeof value === \"string\") return value.length === 0 ? [] : value.split(\",\");\n throw new Error(\"The bound value is not a list.\");\n }\n if (kind === \"element\") {\n if (typeof value === \"string\" && value.trim()) return value;\n throw new Error(\"The bound value is not an element reference.\");\n }\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n throw new Error(\"The bound value is not a string.\");\n}\n\n/** Reads one dotted path out of a step outcome; an absent path returns the outcome summary. */\nfunction outcomedetail(outcome: stepoutcome, path: string | undefined): unknown {\n if (!path) return outcome.summary;\n let current: unknown = outcome.details ?? {};\n for (const segment of path.split(\".\")) {\n if (!current || typeof current !== \"object\" || Array.isArray(current)) return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/** Resolves every binding whose source step already produced an outcome into the newest scope; the engine runs this before each step so following steps read fresh values. */\nexport function bindvariables(scopes: variablescope[], bindings: variablebinding[], outputs: Record<string, stepoutcome>, now: number): { scopes: variablescope[]; produced: string[] } {\n let current = scopes;\n const produced: string[] = [];\n for (const binding of bindings) {\n const outcome = outputs[binding.stepid];\n if (!outcome) continue;\n const raw = outcomedetail(outcome, binding.path);\n if (raw === undefined) throw new Error(`The binding of ${binding.variable} found no value at ${binding.path ?? \"the summary\"} of step ${binding.stepid}.`);\n current = setvariable(current, binding.variable, binding.kind, coercevariable(raw, binding.kind), now);\n produced.push(binding.variable);\n }\n return { scopes: current, produced };\n}\n\n/** Resolves one expression operand: a variable reference resolved from the nearest scope outward or a literal; list values flow through so the list operators handle them while every other operator refuses them at coercion. */\nfunction operandvalue(operand: { ref?: string; literal?: string | number | boolean }, scopes: variablescope[]): string | number | boolean | string[] {\n if (operand.ref !== undefined) {\n const resolved = resolvevariable(scopes, operand.ref);\n if (!resolved) throw new Error(`The expression references the undefined variable ${operand.ref}.`);\n return resolved.value;\n }\n if (operand.literal === undefined) throw new Error(\"The expression operand needs a variable reference or a literal.\");\n return operand.literal;\n}\n\n/** Evaluates one reviewed expression between variables: arithmetic, comparison and logic operators with operand coercion and mismatched operator refusals, resolving references from the nearest scope outward; list operands join only the contains and length operators while every other operator refuses them at coercion. */\nexport function expressioneval(expression: expressiontype, scopes: variablescope[]): string | number | boolean {\n const left = operandvalue(expression.left, scopes);\n const right = expression.right === undefined ? undefined : operandvalue(expression.right, scopes);\n const operand = (value: string | number | boolean | string[] | undefined): string | number | boolean => {\n if (Array.isArray(value)) throw new Error(\"The expression operand is a list and needs the contains or length operator.\");\n if (value === undefined) throw new Error(\"The expression operand is missing.\");\n return value;\n };\n const numbervalue = (value: string | number | boolean | string[] | undefined): number => {\n const primitive = operand(value);\n if (typeof primitive === \"number\") return primitive;\n if (typeof primitive === \"string\" && primitive.trim() !== \"\") {\n const parsed = Number(primitive);\n if (Number.isFinite(parsed)) return parsed;\n }\n throw new Error(\"The arithmetic operand is not a number.\");\n };\n const booleanvalue = (value: string | number | boolean | string[] | undefined): boolean => {\n const primitive = operand(value);\n if (typeof primitive === \"boolean\") return primitive;\n throw new Error(\"The logic operand is not a boolean.\");\n };\n const stringvalue = (value: string | number | boolean | string[] | undefined): string => {\n const primitive = operand(value);\n if (typeof primitive === \"string\") return primitive;\n if (typeof primitive === \"number\" || typeof primitive === \"boolean\") return String(primitive);\n throw new Error(\"The text operand is not a string.\");\n };\n switch (expression.operator) {\n case \"add\": return numbervalue(left) + numbervalue(right);\n case \"subtract\": return numbervalue(left) - numbervalue(right);\n case \"multiply\": return numbervalue(left) * numbervalue(right);\n case \"divide\": {\n const divisor = numbervalue(right);\n if (divisor === 0) throw new Error(\"The expression divides by zero.\");\n return numbervalue(left) / divisor;\n }\n case \"modulo\": {\n const divisor = numbervalue(right);\n if (divisor === 0) throw new Error(\"The expression divides by zero.\");\n return numbervalue(left) % divisor;\n }\n case \"equal\": return left === right;\n case \"notequal\": return left !== right;\n case \"less\": return numbervalue(left) < numbervalue(right);\n case \"greater\": return numbervalue(left) > numbervalue(right);\n case \"lessequal\": return numbervalue(left) <= numbervalue(right);\n case \"greaterequal\": return numbervalue(left) >= numbervalue(right);\n case \"and\": return booleanvalue(left) && booleanvalue(right);\n case \"or\": return booleanvalue(left) || booleanvalue(right);\n case \"not\": return !booleanvalue(left);\n case \"concat\": return `${stringvalue(left)}${stringvalue(right)}`;\n case \"contains\": {\n if (Array.isArray(left)) return left.includes(stringvalue(right));\n return stringvalue(left).includes(stringvalue(right));\n }\n case \"length\": {\n if (Array.isArray(left)) return left.length;\n return stringvalue(left).length;\n }\n default: throw new Error(\"The reviewed expression operator is unknown.\");\n }\n}\n\n/** Applies one reviewed regex rule to text and stores the named capture groups as string variables; the no match case is an honest outcome instead of a crash. */\nexport function regexextract(rule: regexrule, text: string, now: number): { matched: boolean; variables: variablevalue[] } {\n const pattern = new RegExp(rule.pattern, rule.flags);\n const match = pattern.exec(text);\n if (!match) return { matched: false, variables: [] };\n const variables: variablevalue[] = [];\n for (const group of rule.groups) {\n const value = match.groups?.[group];\n variables.push({ name: group, kind: \"string\", value: typeof value === \"string\" ? value : \"\", setat: now });\n }\n return { matched: true, variables };\n}\n\n/** Plans the element wait polling: how many probe passes fit inside the reviewed timeout window at the reviewed poll interval; a zero timeout or a zero poll interval runs a single immediate probe. */\nexport function waitelementplan(wait: { timeout: number; poll: number }): { probes: number; lastwait: number } {\n if (wait.timeout <= 0 || wait.poll <= 0) return { probes: 1, lastwait: 0 };\n const probes = Math.floor(wait.timeout / wait.poll) + 1;\n return { probes, lastwait: wait.timeout % wait.poll };\n}\n\n/** Samples one delay inside the reviewed jitter window from a seeded random source: the window spans base minus half the jitter to base plus half the jitter and never dips below zero. */\nexport function delayjitter(delay: delaystep, seed: number): number {\n if (delay.jitter <= 0) return Math.max(0, delay.base);\n const sample = seededrandom(seed);\n return Math.max(0, delay.base - delay.jitter / 2 + sample * delay.jitter);\n}\n\n/** Deterministic random source of the delay jitter so reviewed windows replay exactly during tests and audits; the seed passes an avalanche mix before the xorshift steps so nearby seeds spread across the whole window. */\nexport function seededrandom(seed: number): number {\n let state = seed >>> 0;\n state ^= state >>> 16;\n state = Math.imul(state, 0x85ebca6b);\n state ^= state >>> 13;\n state = Math.imul(state, 0xc2b2ae35);\n state ^= state >>> 16;\n state = (state >>> 0) || 1;\n state ^= state << 13; state >>>= 0;\n state ^= state >> 17;\n state ^= state << 5; state >>>= 0;\n return state / 0x100000000;\n}\n\n/** Builds one new workflow run: pending state, a zero step cursor and the optional dry run flag. */\nexport function newworkflowrun(input: { id?: string; workflowid: string; dryrun?: boolean; now: number }): workflowrun {\n return { id: input.id ?? crypto.randomUUID(), workflowid: input.workflowid, state: \"pending\", cursor: 0, startedat: input.now, ...(input.dryrun === true ? { dryrun: true } : {}) };\n}\n\n/** Pauses one running workflow run at its last checkpoint; the cursor keeps the completed steps so a resume continues exactly there. */\nexport function pauserun(run: workflowrun, now: number): workflowrun {\n if (run.state !== \"running\") throw new Error(\"Only a running workflow can pause.\");\n return { ...run, state: \"paused\", pausedat: now };\n}\n\n/** Cancels one workflow run and records the reviewed reason; done and already cancelled runs stay untouched. */\nexport function cancelrun(run: workflowrun, reason: string, now: number): workflowrun {\n if (run.state === \"done\" || run.state === \"cancelled\") return run;\n return { ...run, state: \"cancelled\", cancelreason: reason, endedat: now };\n}\n\n/** Substitutes ${name} variable references of one step field from the scopes; undefined references are refused with the variable name. */\nfunction interpolate(text: string, scopes: variablescope[]): { text: string; consumed: string[] } {\n const consumed: string[] = [];\n const resolved = text.replace(/\\$\\{([a-z][a-z0-9]*)\\}/g, (_whole, name: string) => {\n const variable = resolvevariable(scopes, name);\n if (!variable) throw new Error(`The step references the undefined variable ${name}.`);\n consumed.push(name);\n return Array.isArray(variable.value) ? variable.value.join(\",\") : String(variable.value);\n });\n return { text: resolved, consumed };\n}\n\n/** Builds the runlog entry of one finished workflow step. */\nfunction runlogof(step: workflowstep, state: runlogentry[\"state\"], startedat: number, duration: number, summary: string, extra: { block?: string; consumed?: string[]; produced?: string[]; details?: Record<string, unknown>; checkpoint?: boolean }): runlogentry {\n return { stepid: step.id, label: step.label, state, startedat, duration, summary, ...(extra.block !== undefined ? { block: extra.block } : {}), ...(extra.consumed !== undefined && extra.consumed.length > 0 ? { consumed: extra.consumed } : {}), ...(extra.produced !== undefined && extra.produced.length > 0 ? { produced: extra.produced } : {}), ...(extra.checkpoint === true ? { checkpoint: true } : {}), ...(extra.details !== undefined ? { details: extra.details } : {}) };\n}\n\n/** Executes exactly one workflow step outside the run loop: resolves the bindings of earlier steps, evaluates the inline expression and regex rule, interpolates the variable references, dispatches through the injected executor and binds the outcome into the newest scope; a control flow executor returns the merged scopes and its iteration runlog so the step adopts them before its own entry. */\nexport async function runstep(input: { step: workflowstep; scopes: variablescope[]; outputs: Record<string, stepoutcome>; execute: (step: workflowstep, context: { scopes: variablescope[]; block?: string; outputs?: Record<string, stepoutcome> }) => Promise<stepexecution>; now: number; block?: string }): Promise<{ scopes: variablescope[]; log: runlogentry; childlog?: runlogentry[]; output: stepexecution }> {\n const startedat = input.now;\n let scopes = input.scopes;\n const consumed: string[] = [];\n if (input.step.bindings) {\n const bound = bindvariables(scopes, input.step.bindings.filter(binding => input.outputs[binding.stepid] !== undefined), input.outputs, input.now);\n scopes = bound.scopes;\n }\n let produced: string[] = [];\n try {\n if (input.step.expression) {\n const value = expressioneval(input.step.expression, scopes);\n scopes = setvariable(scopes, input.step.expression.result, input.step.expression.resultkind, coercevariable(value, input.step.expression.resultkind), input.now);\n produced = [...produced, input.step.expression.result];\n }\n let stepvalue = input.step.value;\n if (input.step.extract) {\n const text = stepvalue ?? \"\";\n const interpolated = interpolate(text, scopes);\n consumed.push(...interpolated.consumed);\n const extraction = regexextract(input.step.extract, interpolated.text, input.now);\n if (extraction.matched) {\n for (const variable of extraction.variables) scopes = setvariable(scopes, variable.name, \"string\", variable.value, input.now);\n produced = [...produced, ...extraction.variables.map(variable => variable.name)];\n }\n stepvalue = interpolated.text;\n }\n // Control flow steps skip interpolation: the control engine owns variable rebinding inside its payload (the item and index variables of every iteration), so it dispatches the reviewed payload unchanged and interpolates the child steps itself once the iteration scopes are bound.\n const controlled = iscontrolflowkind(input.step.kind);\n const target = !controlled && input.step.target !== undefined ? interpolate(input.step.target, scopes) : undefined;\n if (target) consumed.push(...target.consumed);\n const value = !controlled && stepvalue !== undefined ? interpolate(stepvalue, scopes) : undefined;\n if (value) consumed.push(...value.consumed);\n const options = !controlled && input.step.options !== undefined ? interpolate(input.step.options, scopes) : undefined;\n if (options) consumed.push(...options.consumed);\n const dispatchable: workflowstep = { ...input.step, ...(target !== undefined ? { target: target.text } : {}), ...(value !== undefined ? { value: value.text } : {}), ...(options !== undefined ? { options: options.text } : {}) };\n const output = await input.execute(dispatchable, { scopes, outputs: input.outputs, ...(input.block !== undefined ? { block: input.block } : {}) });\n if (output.scopes !== undefined) scopes = output.scopes;\n const childlog = output.log;\n if (input.step.bindings) {\n const bound = bindvariables(scopes, input.step.bindings, { ...input.outputs, [input.step.id]: { stepid: input.step.id, ok: output.ok, summary: output.summary, ...(output.details !== undefined ? { details: output.details } : {}), at: input.now } }, input.now);\n scopes = bound.scopes;\n produced = [...new Set([...produced, ...bound.produced])];\n }\n const duration = Date.now() - startedat;\n return { scopes, log: runlogof(input.step, output.ok ? \"done\" : \"failed\", startedat, duration, output.summary, { ...(input.block !== undefined ? { block: input.block } : {}), ...(consumed.length > 0 ? { consumed } : {}), ...(produced.length > 0 ? { produced } : {}), ...(output.details !== undefined ? { details: output.details } : {}), ...(output.ok ? { checkpoint: true } : {}) }), ...(childlog !== undefined ? { childlog } : {}), output };\n } catch (error) {\n const duration = Date.now() - startedat;\n const summary = error instanceof Error ? error.message : String(error);\n return { scopes, log: runlogof(input.step, \"failed\", startedat, duration, summary, { ...(input.block !== undefined ? { block: input.block } : {}), ...(consumed.length > 0 ? { consumed } : {}) }), output: { ok: false, summary } };\n }\n}\n\n/** Advances one workflow run one step at a time: gates the run behind the active session, the approved plan and the origin grants, opens a child scope per block region, checkpoints after every completed step and resumes a paused run from its last checkpoint. */\nexport async function runworkflow(input: { record: workflowrecord; run: workflowrun; scopes?: variablescope[]; log?: runlogentry[]; outputs?: Record<string, stepoutcome>; execute: (step: workflowstep, context: { scopes: variablescope[]; block?: string; outputs?: Record<string, stepoutcome> }) => Promise<stepexecution>; now: number; gates?: { sessionactive: boolean; planapproved: boolean; origingranted: (origin: string) => boolean }; oncheckpoint?: (state: { run: workflowrun; scopes: variablescope[]; log: runlogentry[] }) => Promise<void> | void }): Promise<{ run: workflowrun; scopes: variablescope[]; log: runlogentry[]; outputs: Record<string, stepoutcome> }> {\n if (input.gates && !input.gates.sessionactive) throw new Error(\"The workflow refuses to run outside an approved session.\");\n if (input.gates && !input.gates.planapproved) throw new Error(\"The workflow refuses to run without the approved plan review.\");\n if (input.gates) for (const origin of input.record.origins) {\n if (!input.gates.origingranted(origin)) throw new Error(`The workflow origin ${origin} falls outside the session grants.`);\n }\n if (input.run.state === \"done\" || input.run.state === \"failed\" || input.run.state === \"cancelled\") throw new Error(`The workflow run is already ${input.run.state}.`);\n const { pausedat, ...resumed } = input.run;\n void pausedat;\n let run: workflowrun = input.run.state === \"paused\" ? { ...resumed, state: \"running\" } : { ...input.run, state: \"running\" };\n let scopes = input.scopes ?? [{ name: \"root\", variables: [] }];\n const log = [...(input.log ?? [])];\n const outputs: Record<string, stepoutcome> = { ...(input.outputs ?? {}) };\n let activeblock: string | undefined;\n for (let index = run.cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n if (step.block !== undefined && step.block !== activeblock) {\n scopes = pushscope(scopes, step.block, (scopes[scopes.length - 1] as variablescope).name);\n activeblock = step.block;\n // The nested parameters of the block invocation bind into the fresh child scope before its first step runs; a default of the wrong kind fails the run honestly with the parameter name.\n if (step.params) {\n try {\n for (const param of step.params) {\n if (param.default === undefined) continue;\n scopes = setvariable(scopes, param.name, param.kind, coercevariable(param.default, param.kind), input.now);\n }\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return { run: { ...run, state: \"failed\", endedat: Date.now(), failreason: `The nested parameter of block ${step.block} failed: ${reason}` }, scopes, log, outputs };\n }\n }\n } else if (step.block === undefined && activeblock !== undefined) {\n while (scopes.length > 1) scopes = popscope(scopes);\n activeblock = undefined;\n }\n const executed = await runstep({ step, scopes, outputs, execute: input.execute, now: Date.now(), ...(step.block !== undefined ? { block: step.block } : {}) });\n scopes = executed.scopes;\n if (executed.childlog !== undefined) log.push(...executed.childlog);\n log.push(executed.log);\n outputs[step.id] = { stepid: step.id, ok: executed.output.ok, summary: executed.output.summary, ...(executed.output.details !== undefined ? { details: executed.output.details } : {}), at: Date.now() };\n if (!executed.output.ok) {\n run = { ...run, state: \"failed\", endedat: Date.now(), failreason: executed.output.summary };\n return { run, scopes, log, outputs };\n }\n run = { ...run, cursor: index + 1 };\n if (input.oncheckpoint) await input.oncheckpoint({ run, scopes, log });\n }\n run = { ...run, state: \"done\", endedat: Date.now() };\n return { run, scopes, log, outputs };\n}\n\n/** Evaluates every step of a workflow with no page mutation and no storage write: steps with a read only projection record their would be outcome and every other step is refused in the runlog. */\nexport function dryrunworkflow(input: { record: workflowrecord; run: workflowrun; scopes?: variablescope[]; log?: runlogentry[]; now: number; projection: (step: workflowstep) => string | undefined }): { run: workflowrun; scopes: variablescope[]; log: runlogentry[] } {\n const run: workflowrun = { ...input.run, state: \"running\", ...(input.run.dryrun === true ? { dryrun: true } : { dryrun: true }) };\n let scopes = input.scopes ?? [{ name: \"root\", variables: [] }];\n const log = [...(input.log ?? [])];\n for (let index = run.cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n const summary = input.projection(step);\n const entry = summary === undefined\n ? runlogof(step, \"refused\", input.now, 0, `The ${step.kind} step has no read only projection and the dry run refuses it.`, { ...(step.block !== undefined ? { block: step.block } : {}) })\n : runlogof(step, \"done\", input.now, 0, summary, { ...(step.block !== undefined ? { block: step.block } : {}) });\n log.push(entry);\n scopes = setvariable(scopes, `${step.id}outcome`, \"boolean\", entry.state === \"done\", input.now);\n }\n return { run: { ...run, state: \"done\", cursor: input.record.steps.length, endedat: input.now }, scopes, log };\n}\n\n/** One watchdog verdict of a running workflow run: the verdict, the recovery action the configuration picks and the honest reason. */\nexport type watchdogverdict = { runid: string; verdict: \"stalled\" | \"zombie\" | \"healthy\"; action: \"retry\" | \"pause\" | \"cancel\" | \"reap\" | \"none\"; reason: string; lastcompletedat?: number };\n\n/** Scans the running workflow runs for stalled steps and zombie runs: a run grades stalled when no step completed inside the configured threshold and it grades zombie when its executor is gone \u2014 a browser shutdown left it running \u2014 and the window elapsed; the recovery action stays the reviewed user configuration of retry, pause or cancel while a zombie always reaps. */\nexport function watchdogpass(input: { runs: workflowrun[]; lastcompletedat: Record<string, number>; liveexecutors: string[]; config: watchdogconfig; now: number }): watchdogverdict[] {\n const verdicts: watchdogverdict[] = [];\n for (const run of input.runs) {\n if (run.state !== \"running\") continue;\n const lastcompletedat = input.lastcompletedat[run.id] ?? run.startedat;\n const live = input.liveexecutors.includes(run.id);\n const silence = input.now - lastcompletedat;\n if (!live && input.config.zombiewindow !== undefined && silence >= input.config.zombiewindow) {\n verdicts.push({ runid: run.id, verdict: \"zombie\", action: \"reap\", reason: `The run ${run.id} lost its executor ${silence} ms ago and reaps as a zombie of a browser shutdown at its last checkpoint ${run.cursor}.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n continue;\n }\n if (!live) continue;\n if (silence >= input.config.stallthreshold) {\n const action = input.config.action;\n verdicts.push({ runid: run.id, verdict: \"stalled\", action, reason: `The run ${run.id} completed no step for ${silence} ms past the reviewed threshold and the watchdog recovers it with ${action} at cursor ${run.cursor}.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n continue;\n }\n verdicts.push({ runid: run.id, verdict: \"healthy\", action: \"none\", reason: `The run ${run.id} completed its last step ${silence} ms ago and stays healthy.`, ...(lastcompletedat !== run.startedat ? { lastcompletedat } : {}) });\n }\n return verdicts;\n}\n", "import type { actionkind, agentplan, agentsession, allowlistentry, approvaltimeout, attachtarget, captureexport, captureformat, capturenaming, captureoptions, cdpallowlist, cleanuprule, clientidentity, clientrecord, consoleconsentrecord, debuggergrant, delaystep, downloadspec, editormodel, endpointconfig, fieldkind, formprofile, locationconsent, loglevel, loglevelset, mimefilter, mcpserverconfig, observationmode, permissionstate, policyevaluation, quarantineentry, regionrect, rotationrule, runsettings, safetyverdict, siteoverride, sourcemapconsent, spamrule, steptemplate, toolcatalog, tooldef, toolnamespace, toolstep, transformrule, waitstep, watchdogconfig, workflowrecord, workflowstep } from \"./types.js\";\nimport { domainkinds, toolnamespaces } from \"./toolcatalog.js\";\nimport { channeloptionsof, channelorigin, pollcursorof, subscriptionoptionsof } from \"./socketbus.js\";\nimport { apireplayspecof, privatemime } from \"./netwatch.js\";\nimport { blockruleof, cookiedomaingranted, cookierecordof, mockspecof, patternorigin, proxyrouteof, headeruleof } from \"./netcontrol.js\";\nimport { allowlistcovers, breakpointinputof, cdpallowlistof, cdpdomains, cdpeventruleof, methoddomain, overrideinputof, stepmodeof, teardownplanof, watchexpressionof } from \"./cdpbus.js\";\nimport { annotationof, attachtargetof, flowspecof, tracecategories } from \"./profilers.js\";\nimport { agentgrammarvalid, agentpresetof, blackboxruleof, browserpermissions, devicepresetof, familyofkind, locationconsentcovers, locationpresetof, locationrangevalid, networkpresetof, permissiongrantof, permissiongrade, permissionstates, revertplanof } from \"./emulation.js\";\nimport { autointervalof, importsessionfile, restoreplanof, searchqueryof, sessionkinds, snapshotplanof } from \"./sessions.js\";\nimport { composeworkflow, expressionof, expressionoperators, regexruleof, steptemplateof, validateworkflow, workflowblockof, workflowstepof } from \"./workflow.js\";\nimport { branchof, conditionof, controlsteps, foreachof, iscontrolflowkind, loopof, parallelof, repeatuntilof, tryof, whileof } from \"./controlflow.js\";\nimport { armrule, cronparse, triggerfamilyof, triggerpayloadof, triggereventcatalog, webhooksecretok } from \"./trigger.js\";\nimport { formpayloadof, multipartpayloadof, oauthflowof } from \"./netauth.js\";\nimport { loglevels, timelinesources } from \"./runtimeline.js\";\n\nconst sensitiveactions = new Set<actionkind>([\"click\", \"type\", \"navigate\", \"select\", \"presskey\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"reload\", \"back\", \"forward\", \"writestorage\", \"setattribute\", \"removeattribute\", \"evaluate\", \"tabcreate\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowcreate\", \"windowclose\", \"windowresize\", \"downloadfile\", \"clickpoint\", \"shiftclick\", \"dismissdialog\", \"enterframe\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"keyhold\", \"keyrelease\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"openlink\", \"openprivate\", \"reloadcache\", \"stopnav\", \"followlink\", \"spanav\", \"rewritequery\", \"setfragment\", \"navlist\", \"navprofile\", \"handleauth\", \"printpdf\", \"prefetch\", \"preconnect\", \"deeplink\", \"reopentab\", \"pausenav\", \"navrate\", \"openclipboard\", \"batchopen\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"restorelayout\", \"reopenrun\", \"badgetab\", \"fillform\", \"filllabel\", \"fillplaceholder\", \"submitform\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcard\", \"fillcode\", \"consentpassword\", \"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"streamdisk\", \"paginateextract\", \"resumeextract\", \"batchdownload\", \"pausedownload\", \"resumedownload\", \"interceptmime\", \"readclipboard\", \"writeclipboard\", \"copyscreen\", \"quarantinedownload\", \"scanvirus\", \"cleanupartifacts\", \"recordscreen\", \"captureaudio\", \"downloadimages\", \"callrest\", \"callgraphql\", \"sendmessage\", \"blockrequest\", \"mockresponse\", \"rewriteheaders\", \"setcookies\", \"clearcookies\", \"authflow\", \"saveapikey\", \"routeproxy\", \"postform\", \"postfiles\", \"attachcdp\", \"detachcdp\", \"cdpcmd\", \"overridescript\", \"heapshot\", \"profilecpu\", \"capturesourcemaps\", \"emulatedevice\", \"emulatenetwork\", \"emulatelocate\", \"setuseragent\", \"overridepermission\", \"restoresession\", \"exportsessions\", \"importsessions\", \"runworkflow\", \"visitrule\", \"urlrule\", \"menurule\", \"keyrule\", \"buttonrule\", \"cronrule\", \"intervalrule\", \"urllistrule\", \"webhookrule\", \"eventrule\"]);\nconst interactionactions = new Set<actionkind>([\"focus\", \"scroll\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"scrollpage\", \"scrollby\", \"scrollend\", \"scrolltop\", \"fullscreen\", \"zoomset\", \"movepointer\", \"clicktext\", \"clickaria\", \"clickname\", \"expanddetails\", \"pierceshadow\", \"retryaction\", \"capturebodies\", \"setbreakpoint\", \"stepcode\", \"watchexpr\", \"loop\", \"repeatuntil\", \"whileloop\", \"foreach\", \"parallel\", \"trycatch\"]);\nconst readactions = new Set<actionkind>([\"observe\", \"inspect\", \"extract\", \"wait\", \"waitfor\", \"waittext\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"readlinks\", \"readimages\", \"readmeta\", \"readforms\", \"readstorage\", \"highlight\", \"tablist\", \"windowlist\", \"tabsnapshot\", \"mapclicks\", \"verifyvisible\", \"verifyenabled\", \"resolvexpath\", \"a11ytree\", \"readvisible\", \"readertree\", \"detectlists\", \"detecttables\", \"readjson\", \"watchmutate\", \"waitquiet\", \"watchbanner\", \"detectinfinitescroll\", \"detectvirtual\", \"detectlazy\", \"readscrollpos\", \"readlang\", \"readoutline\", \"countpages\", \"listshadow\", \"listframes\", \"classifypage\", \"fingerprintsection\", \"diffsnapshots\", \"readselection\", \"watchfocus\", \"detectsticky\", \"detectscrolllock\", \"readopengraph\", \"detectlanguage\", \"deriveselector\", \"waitload\", \"waiturl\", \"spawait\", \"detecthttp\", \"readredirects\", \"readfinalurl\", \"trailaudit\", \"navintent\", \"checksafe\", \"querytabs\", \"watchtab\", \"findclones\", \"searchtabs\", \"listaudio\", \"snapshotsession\", \"savelayout\", \"attachmeta\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"readerrors\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\", \"handoffcaptcha\", \"scrapetable\", \"importcsv\", \"looprows\", \"transformvalues\", \"deduperows\", \"mergepages\", \"stamplerows\", \"previewgrid\", \"logprovenance\", \"verifydownload\", \"exportnetlog\", \"namecaptures\", \"shotview\", \"shotfullpage\", \"shotelement\", \"shotregion\", \"contactsheet\", \"capturepdf\", \"captureframe\", \"readmedia\", \"readassets\", \"probestream\", \"timelapse\", \"shotcanvas\", \"convertimage\", \"makethumbs\", \"fetchurl\", \"parsejson\", \"parsehtml\", \"opensocket\", \"waitmessage\", \"watchrequests\", \"readheaders\", \"mapapi\", \"subscribesse\", \"longpoll\", \"extractapi\", \"readcookies\", \"watchconsole\", \"watcherrors\", \"watchtasks\", \"watchcdp\", \"measureflow\", \"trackmemory\", \"watchshifts\", \"traceload\", \"annotatetrace\", \"replaytrace\", \"blackboxscripts\", \"persiststate\", \"capturesession\", \"namedsessions\", \"diffsessions\", \"searchsessions\", \"composeworkflow\", \"savetemplate\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\", \"listruns\", \"condition\", \"branch\"]);\nconst allowedactions = new Set<actionkind>([...sensitiveactions, ...interactionactions, ...readactions]);\nconst watchactions = new Set<actionkind>([\"watchmutate\", \"watchbanner\", \"watchfocus\", \"watchtab\"]);\nconst targetactions = new Set<actionkind>([\"inspect\", \"focus\", \"click\", \"type\", \"scroll\", \"select\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"highlight\", \"setattribute\", \"removeattribute\", \"waitfor\", \"shiftclick\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\", \"verifyvisible\", \"verifyenabled\", \"pierceshadow\", \"deriveselector\", \"fingerprintsection\", \"submitform\", \"retryform\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\", \"scrapetable\", \"paginateextract\", \"shotelement\", \"captureframe\", \"shotcanvas\"]);\nconst valueactions = new Set<actionkind>([\"presskey\", \"drag\", \"drop\", \"upload\", \"readattribute\", \"removeattribute\", \"waittext\", \"evaluate\", \"zoomset\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowclose\", \"windowresize\", \"tabcreate\", \"windowcreate\", \"downloadfile\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"keyhold\", \"keyrelease\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"followlink\", \"setfragment\", \"handleauth\", \"navintent\", \"openclipboard\", \"checksafe\", \"reopentab\", \"spanav\", \"duplicatetab\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"focuswindow\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"incognitowindow\", \"asksubmit\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\", \"pausedownload\", \"resumedownload\", \"verifydownload\", \"writeclipboard\", \"quarantinedownload\", \"scanvirus\"]);\nconst tabscommandactions = new Set<actionkind>([\"querytabs\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"watchtab\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"savelayout\", \"restorelayout\", \"findclones\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"listaudio\", \"reopenrun\", \"snapshotsession\"]);\nconst formactions = new Set<actionkind>([\"fillform\", \"filllabel\", \"fillplaceholder\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"submitform\", \"readerrors\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"handoffcaptcha\", \"fillcard\", \"fillcode\", \"consentpassword\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\"]);\n/** Extraction, transform, export and provenance kinds of the forms and data part two family. */\nconst datasetactions = new Set<actionkind>([\"scrapetable\", \"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"importcsv\", \"looprows\", \"transformvalues\", \"deduperows\", \"paginateextract\", \"mergepages\", \"stamplerows\", \"previewgrid\", \"streamdisk\", \"resumeextract\", \"logprovenance\"]);\n/** Export kinds that move extracted data out of local memory to disk, the clipboard or a reviewed sheet endpoint. */\nconst exportactions = new Set<actionkind>([\"exportcsv\", \"exportjson\", \"exportexcel\", \"copytable\", \"pushsheets\", \"streamdisk\"]);\n/** Files, clipboard and downloads kinds of the batch queue, interception, clipboard, quarantine, naming and cleanup family. */\nconst filesactions = new Set<actionkind>([\"batchdownload\", \"pausedownload\", \"resumedownload\", \"verifydownload\", \"interceptmime\", \"exportnetlog\", \"readclipboard\", \"writeclipboard\", \"copyscreen\", \"quarantinedownload\", \"scanvirus\", \"namecaptures\", \"cleanupartifacts\"]);\nconst captureactions = new Set<actionkind>([\"shotview\", \"shotfullpage\", \"shotelement\", \"shotregion\", \"contactsheet\"]);\n/** Media capture part two kinds of the pdf, recording, image, canvas, stream, asset, lapse, conversion and thumbnail family. */\nconst mediaactions = new Set<actionkind>([\"capturepdf\", \"recordscreen\", \"captureaudio\", \"captureframe\", \"downloadimages\", \"shotcanvas\", \"probestream\", \"readmedia\", \"readassets\", \"timelapse\", \"convertimage\", \"makethumbs\"]);\n\nconst httpactions = new Set<actionkind>([\"fetchurl\", \"parsejson\", \"parsehtml\", \"callrest\", \"callgraphql\"]);\n\nconst socketactions = new Set<actionkind>([\"opensocket\", \"sendmessage\", \"waitmessage\", \"subscribesse\", \"longpoll\"]);\n\nconst netwatchactions = new Set<actionkind>([\"watchrequests\", \"readheaders\", \"capturebodies\", \"mapapi\", \"extractapi\"]);\n\n/** Network control kinds of the 1.1.44 family: blocking, mocking, header rewriting, cookies, auth, api keys, proxy routing and uploads. */\nconst controlactions = new Set<actionkind>([\"blockrequest\", \"mockresponse\", \"rewriteheaders\", \"setcookies\", \"readcookies\", \"clearcookies\", \"authflow\", \"saveapikey\", \"routeproxy\", \"postform\", \"postfiles\"]);\n\n/** Debugging kinds of the 1.1.45 family: console, error and task watching stays read only timeline capture. */\nconst debugactions = new Set<actionkind>([\"watchconsole\", \"watcherrors\", \"watchtasks\"]);\n\n/** The devtools protocol kinds of the 1.1.46 debugging family: attach, detach, raw commands, event watches, breakpoints, stepping, watch expressions and script overrides. */\nconst cdpactions = new Set<actionkind>([\"attachcdp\", \"detachcdp\", \"cdpcmd\", \"watchcdp\", \"setbreakpoint\", \"stepcode\", \"watchexpr\", \"overridescript\"]);\n\n/** The profiling kinds of the 1.1.47 debugging part three family: flow measurement, heap snapshots, memory growth tracking, cpu profiles, layout shift watches, trace records, trace annotation, offline trace replay and source map capture. */\nconst profileractions = new Set<actionkind>([\"measureflow\", \"heapshot\", \"trackmemory\", \"profilecpu\", \"watchshifts\", \"traceload\", \"annotatetrace\", \"replaytrace\", \"capturesourcemaps\"]);\n\nconst emulationactions = new Set<actionkind>([\"emulatedevice\", \"emulatenetwork\", \"emulatelocate\", \"setuseragent\", \"overridepermission\", \"blackboxscripts\"]);\n\n/** The session memory kinds of the 1.1.49 family: task state persistence, session capture, restore, naming, diffing, search, export and import. */\nconst sessionactions = new Set<actionkind>([\"persiststate\", \"capturesession\", \"restoresession\", \"namedsessions\", \"diffsessions\", \"searchsessions\", \"exportsessions\", \"importsessions\"]);\n\n/** The workflow kinds of the 1.1.50 and 1.1.51 families: composition, templates, runs, dry runs, jittered delays, element waits, expressions, variable extraction, and the control flow family of conditionals, branching, loops, parallel branches with joins and try catch with retries and timeouts. */\nconst workflowactions = new Set<actionkind>([\"composeworkflow\", \"savetemplate\", \"runworkflow\", \"dryrun\", \"delay\", \"waitelement\", \"compute\", \"extractvars\", \"condition\", \"branch\", \"loop\", \"repeatuntil\", \"whileloop\", \"foreach\", \"parallel\", \"trycatch\"]);\n\n/** The trigger kinds of the 1.1.52 family: page visit, url pattern, context menu, keyboard shortcut, toolbar button, cron, interval, url list, webhook and page event rules that launch reviewed workflows; every rule arms behind the explicit arm review and grades sensitive because it launches runs automatically. */\nconst triggeractions = new Set<actionkind>([\"visitrule\", \"urlrule\", \"menurule\", \"keyrule\", \"buttonrule\", \"cronrule\", \"intervalrule\", \"urllistrule\", \"webhookrule\", \"eventrule\"]);\n\n/** Header names that carry credentials; sending any of them needs the explicit consent that names the header. */\nconst credentialheaders = new Set([\"authorization\", \"proxy-authorization\", \"cookie\", \"cookie2\", \"set-cookie\", \"api-key\", \"x-api-key\", \"x-auth-token\", \"x-session-token\", \"proxy-authorization\"]);\n/** Field kinds the form grammar accepts inside records, profiles and value rules. */\nconst fieldkinds: fieldkind[] = [\"text\", \"email\", \"phone\", \"date\", \"number\", \"select\", \"check\", \"radio\", \"file\", \"password\", \"card\", \"code\"];\nconst layoutmutationactions = new Set<actionkind>([\"grouptabs\", \"colorgroup\", \"collapsegroup\", \"savelayout\", \"restorelayout\"]);\n/** Chromium tab group colors accepted as reviewed group color choices. */\nconst groupcolors = [\"grey\", \"blue\", \"red\", \"yellow\", \"green\", \"pink\", \"purple\", \"cyan\", \"orange\"];\n\n/** Normalizes a user supplied HTTPS endpoint without preserving a provider lock-in. */\nexport function normalizeendpoint(value: string): endpointconfig {\n const endpoint = new URL(value.trim());\n if (endpoint.protocol !== \"https:\") throw new Error(\"Devthink accepts HTTPS endpoints only.\");\n if (endpoint.username || endpoint.password) throw new Error(\"Endpoint credentials are not allowed in the URL.\");\n return { endpoint: endpoint.toString(), origin: endpoint.origin, configuredat: Date.now() };\n}\n\n/** Creates the exact optional host pattern requested from Chromium. */\nexport function hostpattern(origin: string): string {\n const parsed = new URL(origin);\n if (parsed.protocol !== \"https:\") throw new Error(\"Only HTTPS origins can be granted.\");\n return `${parsed.origin}/*`;\n}\n\n/** True when the kind belongs to the session memory family of the 1.1.49 release. */\nexport function issessionkind(kind: actionkind): boolean {\n return sessionactions.has(kind);\n}\n\n/** True when the kind belongs to the workflow family of the 1.1.50 release. */\nexport function isworkflowkind(kind: actionkind): boolean {\n return workflowactions.has(kind);\n}\n\n/** True when the kind belongs to the trigger family of the 1.1.52 release: every trigger kind arms an automatic launcher and needs the explicit arm review. */\nexport function istriggeraction(kind: actionkind): boolean {\n return triggeractions.has(kind);\n}\n\n/** True when the action kind observes the page over a reviewed lifetime window. */\nexport function iswatchkind(kind: actionkind): boolean {\n return watchactions.has(kind);\n}\n\n/** True when the kind belongs to the debugging family of console, error and task watching. */\nexport function isdebugkind(kind: actionkind): boolean {\n return debugactions.has(kind);\n}\n\n/** True when the kind belongs to the devtools protocol family of attaches, raw commands, event watches, breakpoints, stepping, watch expressions and script overrides. */\nexport function iscdpkind(kind: actionkind): boolean {\n return cdpactions.has(kind);\n}\n\n/** True when the kind belongs to the profiling family of flow, heap, cpu, shift, trace and source map instruments. */\nexport function isprofilekind(kind: actionkind): boolean {\n return profileractions.has(kind);\n}\n\n/** True when the kind belongs to the emulation family of device, network, location, agent and permission layers plus blackbox trace shaping. */\nexport function isemulationkind(kind: actionkind): boolean {\n return emulationactions.has(kind);\n}\n\n/** Grades the observation mode of a kind: passive capture, watched lifetimes or diffing passes. */\nexport function observationmodeof(kind: actionkind): observationmode {\n if (watchactions.has(kind) || debugactions.has(kind) || profileractions.has(kind) && kind !== \"heapshot\" && kind !== \"replaytrace\" && kind !== \"annotatetrace\" && kind !== \"capturesourcemaps\" && kind !== \"profilecpu\" || cdpactions.has(kind) && kind === \"watchcdp\" || kind === \"waitquiet\") return \"watching\";\n if (kind === \"diffsnapshots\") return \"diffing\";\n return \"passive\";\n}\n\n/** Defines action risk from the fixed local allowlist. */\nexport function actionrisk(kind: actionkind): \"read\" | \"interaction\" | \"sensitive\" {\n if (!allowedactions.has(kind)) throw new Error(\"Unsupported browser action.\");\n if (sensitiveactions.has(kind)) return \"sensitive\";\n return interactionactions.has(kind) ? \"interaction\" : \"read\";\n}\n\n/** True when the action kind accepts a css selector target or a reviewed targetref. */\nexport function needstarget(kind: actionkind): boolean {\n return targetactions.has(kind);\n}\n\n/** Parses the reviewed JSON options of a step; malformed payloads are rejected early. */\nexport function parseoptions(step: toolstep): Record<string, unknown> {\n if (step.options === undefined) return {};\n let parsed: unknown;\n try { parsed = JSON.parse(step.options); } catch { throw new Error(\"Step options must be a JSON object.\"); }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"Step options must be a JSON object.\");\n return parsed as Record<string, unknown>;\n}\n\n/** Maps an action kind to the optional browser permission it requires, if any. */\nexport function requiredcapability(kind: actionkind): string | undefined {\n if (kind === \"tablist\") return \"tabs\";\n if (kind === \"downloadfile\") return \"downloads\";\n if (kind === \"openclipboard\") return \"clipboardRead\";\n if (kind === \"copytable\") return \"clipboardWrite\";\n if (kind === \"batchdownload\" || kind === \"pausedownload\" || kind === \"resumedownload\" || kind === \"verifydownload\" || kind === \"interceptmime\" || kind === \"quarantinedownload\" || kind === \"scanvirus\") return \"downloads\";\n if (kind === \"readclipboard\") return \"clipboardRead\";\n if (kind === \"writeclipboard\" || kind === \"copyscreen\") return \"clipboardWrite\";\n if (kind === \"downloadimages\") return \"downloads\";\n if (kind === \"authflow\") return \"tabs\";\n if (kind === \"capturesession\" || kind === \"restoresession\") return \"tabs\";\n if (kind === \"exportsessions\") return \"downloads\";\n if (kind === \"openlink\" || kind === \"openprivate\" || kind === \"navlist\" || kind === \"batchopen\" || kind === \"reopentab\" || kind === \"deeplink\") return \"tabs\";\n if (tabscommandactions.has(kind)) return \"tabs\";\n return undefined;\n}\n\n/** True when the kind commands tabs or windows beyond the active tab and needs the optional tabs capability. */\nexport function istabscommandkind(kind: actionkind): boolean {\n return tabscommandactions.has(kind);\n}\n\n/** True when the kind mutates tab groups or layouts and therefore stays inside the active session. */\nexport function islayoutkind(kind: actionkind): boolean {\n return layoutmutationactions.has(kind);\n}\n\n/** True when the kind belongs to the forms and data family. */\nexport function isformkind(kind: actionkind): boolean {\n return formactions.has(kind);\n}\n\n/** True when the kind belongs to the extraction, transform, export and provenance family. */\nexport function isdatasetkind(kind: actionkind): boolean {\n return datasetactions.has(kind);\n}\n\n/** True when the kind exports extracted data out of local memory to disk, the clipboard or a reviewed sheet endpoint. */\nexport function isexportkind(kind: actionkind): boolean {\n return exportactions.has(kind);\n}\n\n/** True when the kind belongs to the files, clipboard and downloads family. */\nexport function isfileskind(kind: actionkind): boolean {\n return filesactions.has(kind);\n}\n\n/** True when the kind belongs to the media capture family of viewport, full page, element, region and contact sheet shots. */\nexport function iscapturekind(kind: actionkind): boolean {\n return captureactions.has(kind);\n}\n\n/** Requires the active tab grant of the live session before any capture kind runs: the session tab and origin must match and the origin grant must cover the active origin. */\nexport function capturegate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** Validates one reviewed capture options payload: format inside the png, jpeg and webp set, quality bounded only by the format range, pixel ratio from one up with no code ceiling, and a known export target. */\nexport function validatecaptureoptions(value: unknown): policyevaluation {\n if (value === undefined) return { allowed: true };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"The reviewed capture options must be an object in options.capture.\" };\n const options = value as Record<string, unknown>;\n if (options.format !== undefined && options.format !== \"png\" && options.format !== \"jpeg\" && options.format !== \"webp\") return { allowed: false, reason: \"The reviewed capture format must be png, jpeg or webp.\" };\n if (options.quality !== undefined && (typeof options.quality !== \"number\" || !Number.isFinite(options.quality) || options.quality < 0 || options.quality > 100)) return { allowed: false, reason: \"The reviewed capture quality must stay between zero and one hundred; any value in that range is the user choice with no code cap.\" };\n if (options.pixelratio !== undefined && (typeof options.pixelratio !== \"number\" || !Number.isFinite(options.pixelratio) || options.pixelratio < 1)) return { allowed: false, reason: \"The reviewed pixel ratio starts at one and climbs to any user configured ceiling with no code ceiling.\" };\n if (options.annotate !== undefined && typeof options.annotate !== \"boolean\") return { allowed: false, reason: \"The reviewed capture annotation flag must be a boolean.\" };\n if (options.exporttarget !== undefined && options.exporttarget !== \"memory\" && options.exporttarget !== \"download\" && options.exporttarget !== \"clipboard\") return { allowed: false, reason: \"The reviewed capture export target must be memory, download or clipboard.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed region rectangle in css pixels; negative coordinates and non positive sizes are refused. */\nexport function validateregionrect(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed regionrect with x, y, width and height in css pixels is required in options.\" };\n const rect = value as Record<string, unknown>;\n for (const field of [\"x\", \"y\", \"width\", \"height\"]) {\n if (typeof rect[field] !== \"number\" || !Number.isFinite(rect[field] as number)) return { allowed: false, reason: `The reviewed regionrect needs a numeric ${field} in css pixels.` };\n }\n if ((rect.x as number) < 0 || (rect.y as number) < 0) return { allowed: false, reason: \"The reviewed regionrect refuses negative coordinates.\" };\n if ((rect.width as number) <= 0 || (rect.height as number) <= 0) return { allowed: false, reason: \"The reviewed regionrect needs positive width and height values.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed capture naming rule against the allowed segment set: run, step, sequence and kind flags only. */\nexport function validatecapturenaming(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed capturenaming rule with run, step, sequence and kind flags is required.\" };\n const rule = value as Record<string, unknown>;\n const segments = [\"run\", \"step\", \"sequence\", \"kind\"];\n for (const key of Object.keys(rule)) {\n if (!segments.includes(key)) return { allowed: false, reason: `The reviewed capturenaming rule refuses the unknown ${key} segment; only run, step, sequence and kind participate.` };\n }\n for (const segment of segments) {\n if (rule[segment] !== undefined && typeof rule[segment] !== \"boolean\") return { allowed: false, reason: `The reviewed capturenaming ${segment} flag must be a boolean.` };\n }\n if (!segments.some(segment => rule[segment] === true)) return { allowed: false, reason: \"The reviewed capturenaming rule needs at least one enabled segment of run, step, sequence and kind.\" };\n return { allowed: true };\n}\n\n/** Routes the capture export target: memory stays local, clipboard needs the clipboardwrite grant and disk writes only run through the reviewed download flow. */\nexport function captureexportgranted(target: captureexport | undefined): policyevaluation {\n if (target === undefined || target === \"memory\") return { allowed: true };\n if (target === \"clipboard\") return { allowed: true, reason: \"The clipboard capture export runs behind the optional clipboardwrite capability, negotiated through the permissions api before the copy.\" };\n if (target === \"download\") return { allowed: true, reason: \"The download capture export runs only through the reviewed download flow behind the optional downloads capability.\" };\n return { allowed: false, reason: \"The capture export target must be memory, download or clipboard; no other disk route exists.\" };\n}\n\n/** Keeps the stitching scroll budget inside the reviewed wait window: the settle windows of every tile must fit the reviewed wait window with no code ceiling on either side. */\nexport function stitchbudgetallowed(tiles: number, settle: number, wait: number): policyevaluation {\n if (tiles <= 0) return { allowed: false, reason: \"The stitch budget needs at least one tile.\" };\n if (settle < 0 || wait < 0) return { allowed: false, reason: \"The reviewed settle and wait windows must be zero or positive milliseconds.\" };\n if (tiles * settle > wait) return { allowed: false, reason: `The stitching scroll budget of ${tiles} tiles at ${settle} milliseconds exceeds the reviewed wait window of ${wait} milliseconds; review a wider window or a smaller settle.` };\n return { allowed: true };\n}\n\n/** Allows beforeafter state capture to wrap any existing action kind except the capture kinds themselves; pixel evidence around sensitive actions grades as reviewable evidence. */\nexport function beforeafterwrapallowed(kind: actionkind): boolean {\n return allowedactions.has(kind) && !captureactions.has(kind);\n}\n\n/** Exposes the capture retention window as a user configured choice; an absent value keeps every capture byte forever with no code ceiling. */\nexport function captureretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.captureretention;\n}\n\n/** Validates the reviewed media capture parameter grammar; pixel ratios, quality values, cell counts and retention windows stay user choices with no code ceilings. */\nfunction validatecapturegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n const optioncheck = validatecaptureoptions(options.capture);\n if (!optioncheck.allowed) return optioncheck;\n if (options.settle !== undefined && (typeof options.settle !== \"number\" || !Number.isFinite(options.settle) || options.settle < 0)) return { allowed: false, reason: \"The reviewed capture settle window must be zero or a positive number of milliseconds.\" };\n if (options.overlap !== undefined && (typeof options.overlap !== \"number\" || !Number.isInteger(options.overlap) || options.overlap < 0)) return { allowed: false, reason: \"The reviewed stitch overlap must be zero or a positive number of rows.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed capture wait window must be zero or a positive number of milliseconds.\" };\n if (options.naming !== undefined) {\n const namingcheck = validatecapturenaming(options.naming);\n if (!namingcheck.allowed) return namingcheck;\n }\n if (kind === \"shotregion\") {\n const rectcheck = validateregionrect(options.regionrect);\n if (!rectcheck.allowed) return rectcheck;\n if (options.reviewed !== true) return { allowed: false, reason: \"Every reviewed regionrect needs the explicit reviewed flag before shotregion runs.\" };\n if (options.container !== undefined && !isnonempty(options.container)) return { allowed: false, reason: \"The reviewed scrollable container selector must be a non-empty string.\" };\n if (options.steps !== undefined && (typeof options.steps !== \"number\" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: \"The reviewed container scroll steps must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"contactsheet\") {\n const elements = options.elements;\n if (!Array.isArray(elements) || elements.length === 0 || !elements.every(item => isnonempty(item))) return { allowed: false, reason: \"A reviewed non-empty list of element selectors is required in options for the contact sheet; the cell count stays the user choice.\" };\n const layout = options.sheet;\n if (layout !== undefined) {\n if (!layout || typeof layout !== \"object\" || Array.isArray(layout)) return { allowed: false, reason: \"The reviewed sheetlayout must be an object with cellsize, columns and label.\" };\n const sheet = layout as Record<string, unknown>;\n if (typeof sheet.cellsize !== \"number\" || !Number.isFinite(sheet.cellsize) || sheet.cellsize <= 0) return { allowed: false, reason: \"The reviewed contact sheet cell size must be a positive number of pixels.\" };\n if (typeof sheet.columns !== \"number\" || !Number.isInteger(sheet.columns) || sheet.columns < 1) return { allowed: false, reason: \"The reviewed contact sheet column count must be a positive integer with no code ceiling.\" };\n if (sheet.label !== undefined && sheet.label !== \"none\" && sheet.label !== \"index\" && sheet.label !== \"selector\" && sheet.label !== \"both\") return { allowed: false, reason: \"The reviewed contact sheet label style must be none, index, selector or both.\" };\n }\n }\n return { allowed: true };\n}\n\n/** Refuses any export that would leave local memory while the session origin grants do not cover the active origin. */\nexport function exportgranted(session: agentsession | undefined, origin: string): policyevaluation {\n if (!origingranted(session, origin)) return { allowed: false, reason: `The export of extracted data from ${origin} needs the session origin grants before it leaves local memory.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed fieldmatch grammar of one form field entry. */\nexport function validatefieldmatch(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed field match is required in options.\" };\n const match = value as Record<string, unknown>;\n if (match.mode !== \"label\" && match.mode !== \"placeholder\" && match.mode !== \"arialabel\" && match.mode !== \"name\") return { allowed: false, reason: \"The reviewed field match mode must be label, placeholder, arialabel or name.\" };\n const key = match.mode === \"label\" ? \"label\" : match.mode === \"placeholder\" ? \"placeholder\" : match.mode === \"arialabel\" ? \"arialabel\" : \"name\";\n if (!isnonempty(match[key])) return { allowed: false, reason: `The reviewed ${match.mode} field match needs a non-empty ${key}.` };\n return { allowed: true };\n}\n\n/** Validates a reviewed structured form record; password entries are refused because passwords need the explicit consentpassword consent. */\nexport function validateformrecord(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed form record with entries is required in options.\" };\n const record = value as Record<string, unknown>;\n if (record.form !== undefined && !isnonempty(record.form)) return { allowed: false, reason: \"The reviewed form record form selector must be a non-empty string.\" };\n if (!Array.isArray(record.entries) || record.entries.length === 0) return { allowed: false, reason: \"The reviewed form record needs a non-empty list of entries.\" };\n for (const item of record.entries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed form record entry must be an object.\" };\n const entry = item as Record<string, unknown>;\n const matchcheck = validatefieldmatch(entry.match);\n if (!matchcheck.allowed) return matchcheck;\n if (typeof entry.kind !== \"string\" || !fieldkinds.includes(entry.kind as fieldkind)) return { allowed: false, reason: \"Every reviewed form record entry needs a known field kind.\" };\n if (typeof entry.value !== \"string\") return { allowed: false, reason: \"Every reviewed form record entry needs a string value.\" };\n if (entry.kind === \"password\") return { allowed: false, reason: \"Password entries are refused inside form records; use consentpassword with a reviewed consent ref.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed valuegen grammar of a generatevalues step. */\nexport function validatevaluegen(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed valuegen rule with a field kind is required in options.\" };\n const rule = value as Record<string, unknown>;\n if (typeof rule.kind !== \"string\" || !fieldkinds.includes(rule.kind as fieldkind)) return { allowed: false, reason: \"The reviewed valuegen kind must be a known field kind.\" };\n if (rule.locale !== undefined && !isnonempty(rule.locale)) return { allowed: false, reason: \"The reviewed valuegen locale must be a non-empty string.\" };\n if (rule.seed !== undefined && (typeof rule.seed !== \"number\" || !Number.isFinite(rule.seed))) return { allowed: false, reason: \"The reviewed valuegen seed must be a finite number.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed list of label or placeholder value pairs for filllabel and fillplaceholder steps. */\nfunction validatefieldpairs(options: Record<string, unknown>, mode: \"label\" | \"placeholder\"): policyevaluation {\n const pairs = options.fields;\n if (!Array.isArray(pairs) || pairs.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of field pairs is required in options.\" };\n for (const item of pairs) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed field pair must be an object.\" };\n const pair = item as Record<string, unknown>;\n if (!isnonempty(pair[mode])) return { allowed: false, reason: `Every reviewed field pair needs a non-empty ${mode}.` };\n if (typeof pair.value !== \"string\" || !pair.value.trim()) return { allowed: false, reason: \"Every reviewed field pair needs a non-empty value.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed card segment grammar of a fillcard step. */\nfunction validatecardsegments(value: unknown): policyevaluation {\n if (!Array.isArray(value) || value.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of card segments is required in options.\" };\n for (const item of value) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every reviewed card segment must be an object.\" };\n const segment = item as Record<string, unknown>;\n const matchcheck = validatefieldmatch(segment.match);\n if (!matchcheck.allowed) return matchcheck;\n if (typeof segment.value !== \"string\" || !segment.value.trim()) return { allowed: false, reason: \"Every reviewed card segment needs a non-empty value.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed forms and data parameter grammar of the form family. */\nfunction validateformgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"fillform\" || (kind === \"saveprofiles\" && options.formrecord !== undefined)) {\n const recordcheck = validateformrecord(options.formrecord);\n if (!recordcheck.allowed) return recordcheck;\n }\n if (kind === \"filllabel\" || kind === \"fillplaceholder\") {\n const paircheck = validatefieldpairs(options, kind === \"filllabel\" ? \"label\" : \"placeholder\");\n if (!paircheck.allowed) return paircheck;\n }\n if (kind === \"generatevalues\" && options.valuegen !== undefined) {\n const rulecheck = validatevaluegen(options.valuegen);\n if (!rulecheck.allowed) return rulecheck;\n }\n if (kind === \"saveprofiles\" && !isnonempty(options.name)) return { allowed: false, reason: \"A reviewed profile name is required in options.\" };\n if (kind === \"submitform\" && !isnonempty(options.consentref)) return { allowed: false, reason: \"A reviewed consent ref of an approved asksubmit ticket is required in options.\" };\n if (kind === \"retryform\") {\n const backoff = options.backoff;\n if (!backoff || typeof backoff !== \"object\" || Array.isArray(backoff)) return { allowed: false, reason: \"A reviewed backoff rule with wait and factor is required in options.\" };\n const rule = backoff as Record<string, unknown>;\n if (typeof rule.wait !== \"number\" || !Number.isFinite(rule.wait) || rule.wait <= 0) return { allowed: false, reason: \"The reviewed retry backoff wait must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof rule.factor !== \"number\" || !Number.isFinite(rule.factor) || rule.factor < 1) return { allowed: false, reason: \"The reviewed retry backoff factor must be one or greater with no code ceiling.\" };\n if (options.attempts !== undefined && (typeof options.attempts !== \"number\" || !Number.isInteger(options.attempts) || options.attempts < 1)) return { allowed: false, reason: \"The reviewed retry attempts must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"runwizard\" && options.steps !== undefined && (typeof options.steps !== \"number\" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: \"The reviewed wizard step count must be a positive integer with no code ceiling.\" };\n if (kind === \"selectchain\") {\n if (!isnonempty(options.child)) return { allowed: false, reason: \"A reviewed child selector of the dependent control is required in options.\" };\n if (!nonnegativeoption(options, \"wait\")) return { allowed: false, reason: \"The reviewed dependent wait must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"picktypeahead\") {\n if (!isnonempty(options.pick)) return { allowed: false, reason: \"A reviewed suggestion entry to pick is required in options.\" };\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The reviewed typeahead timeout must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"pickdate\" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed date must use the yyyy-mm-dd form.\" };\n if (kind === \"fillcard\") {\n const segmentcheck = validatecardsegments(options.segments);\n if (!segmentcheck.allowed) return segmentcheck;\n if (!nonnegativeoption(options, \"pause\")) return { allowed: false, reason: \"The reviewed card typing pause must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"fillcode\" && !isnonempty(options.source)) return { allowed: false, reason: \"A reviewed one time code source is required in options.\" };\n if (kind === \"consentpassword\" && !isnonempty(options.consentref)) return { allowed: false, reason: \"A reviewed consent ref is required in options before any password is filled.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed transform rule: a supported expression, source columns and a target column. */\nexport function validatetransformrule(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed transform rule with an expression, sources and a target is required in options.\" };\n const rule = value as Record<string, unknown>;\n const expression = rule.expression;\n if (typeof expression !== \"string\" || !/^(trim|upper|lower|number|prefix|suffix|replace)(?::.+)?$/.test(expression)) return { allowed: false, reason: \"The reviewed transform expression must be trim, upper, lower, number, prefix, suffix or replace with an optional argument.\" };\n if (expression.startsWith(\"replace\") && !expression.slice(\"replace\".length).includes(\"=>\")) return { allowed: false, reason: \"The reviewed replace expression needs the from=>to separator.\" };\n if (expression.startsWith(\"replace\") && expression.slice(\"replace:\".length).split(\"=>\")[0] === \"\") return { allowed: false, reason: \"The reviewed replace expression needs a non-empty from part.\" };\n if (!Array.isArray(rule.sources) || rule.sources.length === 0 || !rule.sources.every(source => isnonempty(source))) return { allowed: false, reason: \"Every reviewed transform rule needs a non-empty list of source columns.\" };\n if (!isnonempty(rule.target)) return { allowed: false, reason: \"Every reviewed transform rule needs a non-empty target column.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed dataset id list in options. */\nfunction validatedatasetids(options: Record<string, unknown>, key: string): policyevaluation {\n const ids = options[key];\n if (!Array.isArray(ids) || ids.length === 0 || !ids.every(id => isnonempty(id))) return { allowed: false, reason: `A reviewed non-empty list of dataset ids is required in options as ${key}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed extraction, transform, export and provenance parameter grammar of the data family. */\nfunction validatedatagrammar(step: toolstep, options: Record<string, unknown>, origin: string): policyevaluation {\n const kind = step.kind;\n if (kind === \"scrapetable\") {\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed dataset name must be a non-empty string.\" };\n if (options.rowlimit !== undefined && (typeof options.rowlimit !== \"number\" || !Number.isInteger(options.rowlimit) || options.rowlimit < 1)) return { allowed: false, reason: \"The reviewed row limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"paginateextract\") {\n if (!isnonempty(options.next)) return { allowed: false, reason: \"A reviewed next control selector is required in options.\" };\n if (options.pages !== undefined && (typeof options.pages !== \"number\" || !Number.isInteger(options.pages) || options.pages < 1)) return { allowed: false, reason: \"The reviewed page count must be a positive integer with no code ceiling.\" };\n if (!nonnegativeoption(options, \"wait\")) return { allowed: false, reason: \"The reviewed row freshness wait must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"exportcsv\" || kind === \"exportjson\" || kind === \"exportexcel\" || kind === \"copytable\" || kind === \"streamdisk\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed artifact name must be a non-empty string.\" };\n }\n if (kind === \"exportcsv\" && options.delimiter !== undefined && (typeof options.delimiter !== \"string\" || options.delimiter.length !== 1)) return { allowed: false, reason: \"The reviewed csv delimiter must be a single character.\" };\n if (kind === \"streamdisk\" && (typeof options.chunk !== \"number\" || !Number.isInteger(options.chunk) || options.chunk < 1)) return { allowed: false, reason: \"The reviewed streaming chunk size must be a positive integer with no code ceiling.\" };\n if (kind === \"pushsheets\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (!isnonempty(options.sheet)) return { allowed: false, reason: \"A reviewed sheet endpoint url is required in options.\" };\n if (!ishttpsurl(options.sheet)) return { allowed: false, reason: \"The reviewed sheet endpoint url must use HTTPS.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The sheet push needs the explicit reviewed flag before any data leaves local memory.\" };\n }\n if (kind === \"importcsv\") {\n if (typeof options.csv !== \"string\" || !options.csv.trim()) return { allowed: false, reason: \"Reviewed csv content is required in options.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed dataset name must be a non-empty string.\" };\n if (options.mapping !== undefined) {\n const mapping = options.mapping;\n if (!mapping || typeof mapping !== \"object\" || Array.isArray(mapping) || !Object.values(mapping).every(item => typeof item === \"string\")) return { allowed: false, reason: \"The reviewed csv column mapping must be an object of string values.\" };\n }\n }\n if (kind === \"looprows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.variable !== undefined && !isnonempty(options.variable)) return { allowed: false, reason: \"The reviewed row variable name must be a non-empty string.\" };\n const inner = validateinnerstep(options, origin);\n if (!inner.allowed) return inner;\n }\n if (kind === \"transformvalues\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of transform rules is required in options.\" };\n for (const item of rules) {\n const rulecheck = validatetransformrule(item);\n if (!rulecheck.allowed) return rulecheck;\n }\n }\n if (kind === \"deduperows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n const keys = options.keys;\n if (!Array.isArray(keys) || keys.length === 0 || !keys.every(key => isnonempty(key))) return { allowed: false, reason: \"A reviewed non-empty list of dedupe column keys is required in options.\" };\n }\n if (kind === \"mergepages\") {\n const listcheck = validatedatasetids(options, \"datasets\");\n if (!listcheck.allowed) return listcheck;\n }\n if (kind === \"stamplerows\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.url !== undefined && !ishttpsurl(options.url)) return { allowed: false, reason: \"The reviewed source url must use HTTPS.\" };\n }\n if (kind === \"previewgrid\") {\n if (!isnonempty(options.dataset)) return { allowed: false, reason: \"A reviewed dataset id is required in options.\" };\n if (options.sample !== undefined && (typeof options.sample !== \"number\" || !Number.isInteger(options.sample) || options.sample < 1)) return { allowed: false, reason: \"The reviewed sample row count must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"resumeextract\" && !isnonempty(options.session)) return { allowed: false, reason: \"A reviewed extract session id is required in options.\" };\n if (kind === \"logprovenance\" && !isnonempty(options.artifact)) return { allowed: false, reason: \"A reviewed artifact id or name is required in options.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed batch download specification: a non-empty HTTPS url list, an optional filename rule and an optional completion criterion. */\nexport function validatedownloadspec(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed downloadspec with a url list is required in options.\" };\n const spec = value as Record<string, unknown>;\n if (!Array.isArray(spec.urls) || spec.urls.length === 0 || !spec.urls.every(url => ishttpsurl(url))) return { allowed: false, reason: \"The reviewed downloadspec needs a non-empty list of HTTPS urls.\" };\n if (spec.filename !== undefined && !isnonempty(spec.filename)) return { allowed: false, reason: \"The reviewed downloadspec filename rule must be a non-empty string.\" };\n if (spec.complete !== undefined && spec.complete !== \"size\" && spec.complete !== \"checksum\") return { allowed: false, reason: \"The reviewed downloadspec completion criterion must be size or checksum.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed mime interception filter: include and exclude patterns plus the deny default for unlisted mime types. */\nexport function validatemimefilter(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed mimefilter with include and exclude patterns is required in options.\" };\n const filter = value as Record<string, unknown>;\n if (!Array.isArray(filter.include) || filter.include.length === 0 || !filter.include.every(pattern => isnonempty(pattern))) return { allowed: false, reason: \"The reviewed mimefilter needs a non-empty list of include patterns.\" };\n if (filter.exclude !== undefined && (!Array.isArray(filter.exclude) || !filter.exclude.every(pattern => isnonempty(pattern)))) return { allowed: false, reason: \"The reviewed mimefilter exclude patterns must be a list of non-empty strings.\" };\n if (filter.default !== \"deny\" && filter.default !== \"allow\") return { allowed: false, reason: \"The reviewed mimefilter needs the deny or allow default for unlisted mime types.\" };\n return { allowed: true };\n}\n\n/** Validates one reviewed cleanup rule: a positive age window with no code ceiling, an artifact kind and a keep policy. */\nexport function validatecleanuprule(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed cleanuprule with an age, a kind and a keep policy is required.\" };\n const rule = value as Record<string, unknown>;\n if (typeof rule.age !== \"number\" || !Number.isFinite(rule.age) || rule.age <= 0) return { allowed: false, reason: \"The reviewed cleanup age window must be a positive number of milliseconds with no code ceiling.\" };\n if (!isnonempty(rule.kind)) return { allowed: false, reason: \"The reviewed cleanup rule needs a non-empty artifact kind, or any to match every kind.\" };\n if (rule.keep !== \"none\" && rule.keep !== \"latest\" && rule.keep !== \"all\") return { allowed: false, reason: \"The reviewed cleanup keep policy must be none, latest or all.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed files, clipboard and downloads parameter grammar; batch sizes, concurrent windows and cleanup ages stay user configured with no code ceilings. */\nfunction validatefilesgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"batchdownload\") {\n const speccheck = validatedownloadspec(options.downloadspec);\n if (!speccheck.allowed) return speccheck;\n if (options.concurrent !== undefined && (typeof options.concurrent !== \"number\" || !Number.isInteger(options.concurrent) || options.concurrent < 1)) return { allowed: false, reason: \"The reviewed concurrent download window must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"pausedownload\" || kind === \"resumedownload\" || kind === \"verifydownload\" || kind === \"quarantinedownload\" || kind === \"scanvirus\") {\n if (!isnonempty(step.value)) return { allowed: false, reason: \"A reviewed download or quarantine reference is required.\" };\n if (kind === \"verifydownload\") {\n if (options.checksum !== undefined && !isnonempty(options.checksum)) return { allowed: false, reason: \"The reviewed expected checksum must be a non-empty string.\" };\n if (options.bytes !== undefined && (typeof options.bytes !== \"number\" || !Number.isFinite(options.bytes) || options.bytes < 0)) return { allowed: false, reason: \"The reviewed expected size must be zero or a positive number of bytes.\" };\n }\n if (kind === \"scanvirus\" && options.scanner !== undefined && !isnonempty(options.scanner)) return { allowed: false, reason: \"The reviewed scanner name must be a non-empty string.\" };\n if (kind === \"quarantinedownload\" && options.reason !== undefined && !isnonempty(options.reason)) return { allowed: false, reason: \"The reviewed quarantine reason must be a non-empty string.\" };\n }\n if (kind === \"interceptmime\") {\n const filtercheck = validatemimefilter(options.mimefilter);\n if (!filtercheck.allowed) return filtercheck;\n }\n if (kind === \"readclipboard\") {\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"A clipboard read requires a reviewed consent ref of an approved consent prompt in options.\" };\n if (options.prompt !== undefined && !isnonempty(options.prompt)) return { allowed: false, reason: \"The reviewed clipboard consent prompt must be a non-empty string.\" };\n }\n if (kind === \"exportnetlog\" && options.stepid !== undefined && !isnonempty(options.stepid)) return { allowed: false, reason: \"The reviewed netlog step filter must be a non-empty step id.\" };\n if (kind === \"namecaptures\") {\n if (!isnonempty(options.task)) return { allowed: false, reason: \"A reviewed task id is required in options for capture naming.\" };\n if (options.steps !== undefined && (!Array.isArray(options.steps) || options.steps.length === 0 || !options.steps.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed capture steps must be a non-empty list of step ids when present.\" };\n if (options.extension !== undefined && !isnonempty(options.extension)) return { allowed: false, reason: \"The reviewed capture extension must be a non-empty string.\" };\n }\n if (kind === \"cleanupartifacts\" && options.rules !== undefined) {\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"The reviewed cleanup rules must be a non-empty list when present.\" };\n for (const item of rules) {\n const rulecheck = validatecleanuprule(item);\n if (!rulecheck.allowed) return rulecheck;\n }\n }\n return { allowed: true };\n}\n\n/** Requires an approved consent prompt before any clipboard read; every read consumes its own prompt. */\nexport function clipboardconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A clipboard read requires a reviewed consent ref in options.\" };\n return { allowed: true };\n}\n\n/** Refuses to release any quarantined file before a clean scan verdict exists. */\nexport function quarantinereleasegranted(entry: quarantineentry): policyevaluation {\n if (entry.scan !== \"clean\") return { allowed: false, reason: `The quarantined file ${entry.path} cannot leave quarantine with the ${entry.scan} scan verdict; only a clean verdict releases it.` };\n return { allowed: true };\n}\n\n/** Refuses downloads and download interception that fall outside the session origin grants. */\nexport function downloadgranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed download URL is invalid.\" }; }\n if (!origingranted(session, origin)) return { allowed: false, reason: `The download from ${origin} leaves the session origin grants and needs a session grant first.` };\n return { allowed: true };\n}\n\n/** Masks a clipboard payload for every log line; the full text never persists anywhere. */\nexport function maskclipboard(payload: string): string {\n return `[clipboard payload of ${payload.length} character${payload.length === 1 ? \"\" : \"s\"}]`;\n}\n\n/** Requires an asksubmit review step before every form submission step. */\nexport function submitreviewgranted(steps: toolstep[], submitid: string): policyevaluation {\n const position = steps.findIndex(candidate => candidate.id === submitid);\n const asked = steps.some((candidate, index) => candidate.kind === \"asksubmit\" && (position === -1 || index < position));\n return asked ? { allowed: true } : { allowed: false, reason: \"Form submission requires an asksubmit review step before it.\" };\n}\n\n/** Requires a reviewed consent ref before any password field is filled. */\nexport function passwordconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A password fill requires a reviewed consent ref in options.\" };\n return { allowed: true };\n}\n\n/** True when a numeric value passes the Luhn checksum used by card networks. */\nfunction luhnvalid(digits: string): boolean {\n let sum = 0;\n let double = false;\n for (let index = digits.length - 1; index >= 0; index -= 1) {\n let value = Number.parseInt(digits[index] ?? \"\", 10);\n if (!Number.isFinite(value)) return false;\n if (double) { value *= 2; if (value > 9) value -= 9; }\n sum += value;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\n/** Refuses generated values that look like real card numbers or personal identifiers; test prefixed card values stay allowed. */\nexport function generatedvalueallowed(value: string): policyevaluation {\n const compact = value.replace(/[\\s-]/g, \"\");\n if (/^\\d{13,19}$/.test(compact) && luhnvalid(compact) && !compact.startsWith(\"4111\")) return { allowed: false, reason: \"The generated value looks like a real card number and is refused; generated card values use the 4111 test prefix.\" };\n if (/^\\d{3}-\\d{2}-\\d{4}$/.test(value.trim())) return { allowed: false, reason: \"The generated value looks like a personal identifier and is refused.\" };\n return { allowed: true };\n}\n\n/** Requires the origin grants of a saved profile to cover the origin before its values fill a page. */\nexport function profilegrantgranted(profile: formprofile, origin: string): policyevaluation {\n if (!profile.grants.includes(origin)) return { allowed: false, reason: `The saved profile ${profile.name} is not granted to ${origin}; add the origin to the profile grants first.` };\n return { allowed: true };\n}\n\n/** Restricts group and layout mutations to the active session: they refuse without a live session. */\nexport function layoutmutationgranted(session: agentsession | undefined, now: number): policyevaluation {\n if (!session || session.stoppedat || session.expiresat <= now) return { allowed: false, reason: \"Group and layout mutations stay inside the active session.\" };\n return { allowed: true };\n}\n\n/** Requires explicit review before closing a window that holds more than one task tab. */\nexport function windowclosegate(tasktabcount: number, reviewed: boolean): policyevaluation {\n if (tasktabcount > 1 && !reviewed) return { allowed: false, reason: `The window holds ${tasktabcount} task tabs and needs explicit review before it closes.` };\n return { allowed: true };\n}\n\n/** Reads the user configured concurrent task tab ceiling; an absent value never refuses a tab. */\nexport function tasktabceiling(settings: runsettings | undefined): number | undefined {\n const ceiling = settings?.tasktabceiling;\n return typeof ceiling === \"number\" && Number.isFinite(ceiling) && ceiling >= 0 ? ceiling : undefined;\n}\n\n/** Parses the reviewed wait duration of a wait step with no upper bound. */\nexport function waitduration(step: toolstep): number {\n const requested = step.value ? Number.parseInt(step.value, 10) : 250;\n if (!Number.isFinite(requested) || requested < 0) throw new Error(\"Wait duration must be zero or a positive number of milliseconds.\");\n return requested;\n}\n\nfunction isnumericid(value: unknown): value is string {\n return typeof value === \"string\" && /^\\d+$/.test(value);\n}\n\nfunction numericoption(options: Record<string, unknown>, key: string): boolean {\n return options[key] === undefined || (typeof options[key] === \"number\" && Number.isFinite(options[key] as number));\n}\n\n/** True when an optional numeric option is absent or a finite number of zero or more. */\nfunction nonnegativeoption(options: Record<string, unknown>, key: string): boolean {\n return numericoption(options, key) && !(typeof options[key] === \"number\" && (options[key] as number) < 0);\n}\n\nfunction isnonempty(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nfunction ispoint(value: unknown): boolean {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const point = value as Record<string, unknown>;\n return typeof point.x === \"number\" && Number.isFinite(point.x) && typeof point.y === \"number\" && Number.isFinite(point.y);\n}\n\n/** Grades a resolution match count: zero is absent, one is resolved and more than one is refused as ambiguous. */\nexport function resolutionverdict(count: number): \"absent\" | \"resolved\" | \"ambiguous\" {\n if (!Number.isFinite(count) || count <= 0) return \"absent\";\n return count === 1 ? \"resolved\" : \"ambiguous\";\n}\n\n/** Validates the reviewed targetref grammar of every resolution mode and rejects empty references. */\nexport function validatetargetref(reference: unknown): policyevaluation {\n if (!reference || typeof reference !== \"object\" || Array.isArray(reference)) return { allowed: false, reason: \"The reviewed target reference must be an object.\" };\n const ref = reference as Record<string, unknown>;\n if (ref.mode === \"selector\") return isnonempty(ref.selector) ? { allowed: true } : { allowed: false, reason: \"The selector target reference needs a non-empty selector.\" };\n if (ref.mode === \"text\") return isnonempty(ref.text) ? { allowed: true } : { allowed: false, reason: \"The text target reference needs non-empty text.\" };\n if (ref.mode === \"aria\") {\n if (!isnonempty(ref.role)) return { allowed: false, reason: \"The aria target reference needs a non-empty role.\" };\n return isnonempty(ref.name) ? { allowed: true } : { allowed: false, reason: \"The aria target reference needs a non-empty name.\" };\n }\n if (ref.mode === \"name\") return isnonempty(ref.name) ? { allowed: true } : { allowed: false, reason: \"The name target reference needs a non-empty name.\" };\n if (ref.mode === \"xpath\") return isnonempty(ref.xpath) ? { allowed: true } : { allowed: false, reason: \"The xpath target reference needs a non-empty expression.\" };\n if (ref.mode === \"index\") {\n const index = ref.index;\n return typeof index === \"number\" && Number.isInteger(index) && index >= 1 ? { allowed: true } : { allowed: false, reason: \"The index target reference needs a positive integer map number.\" };\n }\n if (ref.mode === \"point\") {\n const pointok = typeof ref.x === \"number\" && Number.isFinite(ref.x) && typeof ref.y === \"number\" && Number.isFinite(ref.y);\n return pointok ? { allowed: true } : { allowed: false, reason: \"The point target reference needs numeric x and y coordinates.\" };\n }\n return { allowed: false, reason: \"The target reference mode must be selector, text, aria, name, xpath, index or point.\" };\n}\n\n/** True when the session origin grants cover the given origin; a session without grants only allows its own origin. */\nexport function origingranted(session: agentsession | undefined, origin: string): boolean {\n if (!session) return false;\n const grants = session.grants ?? [session.origin];\n return grants.includes(origin);\n}\n\n/** Decides whether an unreviewed origin may open: the session grants cover it or a safe checksafe verdict vouches for it. */\nexport function originverified(url: string, grants: string[], verdicts: safetyverdict[]): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed navigation URL is invalid.\" }; }\n if (grants.includes(origin)) return { allowed: true };\n const covered = verdicts.find(verdict => verdict.safe && (verdict.url === url || (safeorigin(verdict.url) === origin)));\n if (covered) return { allowed: true };\n return { allowed: false, reason: `The origin ${origin} is outside the session grants and has no safe checksafe verdict; run checksafe and review it first.` };\n}\n\nfunction safeorigin(url: string): string {\n try { return new URL(url).origin; } catch { return \"\"; }\n}\n\n/** Refuses navigation that would move a granted task tab outside the session origin grants until the user consents. */\nexport function navigationgranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The reviewed navigation URL is invalid.\" }; }\n if (origingranted(session, origin)) return { allowed: true };\n return { allowed: false, reason: `Navigation to ${origin} leaves the task tab origins and needs the user consent of a session grant first.` };\n}\n\n/** Validates the reviewed inner step of a retry or frame wrapper against the same rules as a top-level step. */\nfunction validateinnerstep(options: Record<string, unknown>, origin: string): policyevaluation {\n const stepid = options.stepid;\n const kind = options.kind;\n if (isnonempty(stepid)) {\n if (kind !== undefined) return { allowed: false, reason: \"The reviewed wrapper must reference a step id or an inline step, not both.\" };\n return { allowed: true };\n }\n if (typeof kind !== \"string\" || !kind.trim()) return { allowed: false, reason: \"A reviewed step id or inline step kind is required in options.\" };\n if (kind === \"retryaction\" || kind === \"enterframe\" || kind === \"looprows\") return { allowed: false, reason: \"The reviewed inner step cannot be another wrapper kind.\" };\n if (!allowedactions.has(kind as actionkind)) return { allowed: false, reason: \"The reviewed inner step kind is unsupported.\" };\n const inneroptions = options.options;\n if (inneroptions !== undefined && (!inneroptions || typeof inneroptions !== \"object\" || Array.isArray(inneroptions))) return { allowed: false, reason: \"The reviewed inner step options must be an object.\" };\n const inner: toolstep = {\n id: \"inner\",\n kind: kind as actionkind,\n summary: \"Reviewed inner step.\",\n risk: actionrisk(kind as actionkind),\n ...(isnonempty(options.target) ? { target: options.target } : {}),\n ...(isnonempty(options.value) ? { value: options.value } : {}),\n ...(inneroptions !== undefined ? { options: JSON.stringify(inneroptions) } : {}),\n };\n return validatestep(inner, origin);\n}\n\n/** True when a reviewed https url parses. */\nfunction ishttpsurl(value: unknown): value is string {\n if (typeof value !== \"string\" || !value.trim()) return false;\n try { return new URL(value).protocol === \"https:\"; } catch { return false; }\n}\n\n/** Validates the reviewed navtarget grammar of a navigation step. */\nfunction validatenavtarget(value: unknown, kind: string): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed navtarget with a url is required in options.\" };\n const target = value as Record<string, unknown>;\n if (!ishttpsurl(target.url)) return { allowed: false, reason: \"The reviewed navtarget url must use HTTPS.\" };\n const container = target.container ?? \"tab\";\n if (container !== \"current\" && container !== \"tab\" && container !== \"window\" && container !== \"private\") return { allowed: false, reason: \"The reviewed navtarget container must be current, tab, window or private.\" };\n if (target.position !== undefined && target.position !== \"adjacent\" && target.position !== \"end\") return { allowed: false, reason: \"The reviewed navtarget position must be adjacent or end.\" };\n if (kind === \"openprivate\" && container !== \"private\") return { allowed: false, reason: \"The openprivate step requires the private container.\" };\n if (kind === \"openlink\" && container === \"private\") return { allowed: false, reason: \"The openlink step cannot open the private container; use openprivate.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed waitprofile grammar with its load signals, thresholds and per origin overrides. */\nfunction validatewaitprofile(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed waitprofile with load signals is required in options.\" };\n const profile = value as Record<string, unknown>;\n if (!Array.isArray(profile.signals) || profile.signals.length === 0 || !profile.signals.every(signal => isnonempty(signal))) return { allowed: false, reason: \"The reviewed waitprofile needs a non-empty list of load signals.\" };\n if (!nonnegativeoption(profile, \"idle\")) return { allowed: false, reason: \"The reviewed waitprofile idle threshold must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(profile, \"timeout\")) return { allowed: false, reason: \"The reviewed waitprofile timeout must be zero or a positive number of milliseconds.\" };\n if (profile.overrides !== undefined) {\n if (!Array.isArray(profile.overrides) || profile.overrides.length === 0) return { allowed: false, reason: \"The reviewed waitprofile overrides must be a non-empty list when present.\" };\n for (const entry of profile.overrides) {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) return { allowed: false, reason: \"Every reviewed waitprofile override must be an object with an origin.\" };\n const override = entry as Record<string, unknown>;\n if (!ishttpsurl(override.origin)) return { allowed: false, reason: \"Every reviewed waitprofile override origin must use HTTPS.\" };\n if (override.signals !== undefined && (!Array.isArray(override.signals) || !override.signals.every(signal => isnonempty(signal)))) return { allowed: false, reason: \"The reviewed waitprofile override signals must be a list of non-empty strings.\" };\n if (!nonnegativeoption(override, \"idle\") || !nonnegativeoption(override, \"timeout\")) return { allowed: false, reason: \"The reviewed waitprofile override thresholds must be zero or positive numbers.\" };\n }\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed urlpattern grammar with its match mode plus query and fragment parts. */\nexport function validateurlpattern(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed urlpattern is required in options.\" };\n const pattern = value as Record<string, unknown>;\n if (pattern.mode !== \"exact\" && pattern.mode !== \"prefix\" && pattern.mode !== \"host\" && pattern.mode !== \"pattern\") return { allowed: false, reason: \"The reviewed urlpattern mode must be exact, prefix, host or pattern.\" };\n if (!ishttpsurl(pattern.url)) return { allowed: false, reason: \"The reviewed urlpattern url must use HTTPS.\" };\n if (pattern.query !== undefined) {\n if (!pattern.query || typeof pattern.query !== \"object\" || Array.isArray(pattern.query)) return { allowed: false, reason: \"The reviewed urlpattern query part must be an object of parameter names and values.\" };\n for (const item of Object.values(pattern.query)) if (typeof item !== \"string\") return { allowed: false, reason: \"The reviewed urlpattern query values must be strings.\" };\n }\n if (pattern.fragment !== undefined && !isnonempty(pattern.fragment)) return { allowed: false, reason: \"The reviewed urlpattern fragment must be a non-empty string.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed non-empty list of HTTPS urls in options. */\nfunction validateurllist(options: Record<string, unknown>, key: string): policyevaluation {\n const urls = options[key];\n if (!Array.isArray(urls) || urls.length === 0 || !urls.every(url => ishttpsurl(url))) return { allowed: false, reason: `A reviewed non-empty list of HTTPS urls is required in options as ${key}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed ratelimit grammar of a navrate step; the window and ceiling stay user configured with no hardcoded cap. */\nfunction validateratelimit(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed ratelimit with a window and a ceiling is required in options.\" };\n const limit = value as Record<string, unknown>;\n if (limit.domain !== undefined && !isnonempty(limit.domain)) return { allowed: false, reason: \"The reviewed ratelimit domain must be a non-empty string.\" };\n if (typeof limit.window !== \"number\" || !Number.isFinite(limit.window) || limit.window <= 0) return { allowed: false, reason: \"The reviewed ratelimit window must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof limit.ceiling !== \"number\" || !Number.isInteger(limit.ceiling) || limit.ceiling < 1) return { allowed: false, reason: \"The reviewed ratelimit ceiling must be a positive integer with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed tabquery grammar with url, title, id and pattern matchers; at least one matcher is required. */\nexport function validatetabquery(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed tabquery with at least one matcher is required in options.\" };\n const query = value as Record<string, unknown>;\n const hasmatcher = query.url !== undefined || query.title !== undefined || query.id !== undefined || query.pattern !== undefined;\n if (!hasmatcher) return { allowed: false, reason: \"The reviewed tabquery needs a url, title, id or pattern matcher.\" };\n if (query.url !== undefined && !isnonempty(query.url)) return { allowed: false, reason: \"The reviewed tabquery url matcher must be a non-empty string.\" };\n if (query.title !== undefined && !isnonempty(query.title)) return { allowed: false, reason: \"The reviewed tabquery title matcher must be a non-empty string.\" };\n if (query.pattern !== undefined && !isnonempty(query.pattern)) return { allowed: false, reason: \"The reviewed tabquery pattern matcher must be a non-empty string.\" };\n if (query.id !== undefined && (typeof query.id !== \"number\" || !Number.isInteger(query.id) || query.id < 0)) return { allowed: false, reason: \"The reviewed tabquery id matcher must be a non-negative integer tab id.\" };\n return { allowed: true };\n}\n\n/** Validates a reviewed group color choice against the Chromium tab group palette. */\nfunction validategroupcolor(value: unknown): boolean {\n return typeof value === \"string\" && (groupcolors as string[]).includes(value);\n}\n\n/** Validates a reviewed list of numeric browser ids in options. */\nfunction validateidlist(options: Record<string, unknown>, key: string): boolean {\n const ids = options[key];\n return Array.isArray(ids) && ids.length > 0 && ids.every(id => typeof id === \"number\" && Number.isInteger(id) && id >= 0);\n}\n\n/** Validates the reviewed tab and window parameter grammar of the tabs and windows command family. */\nfunction validatetabsgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"querytabs\" || kind === \"closepattern\") {\n const querycheck = validatetabquery(options.tabquery);\n if (!querycheck.allowed) return querycheck;\n if (kind === \"closepattern\" && options.reviewed !== true) return { allowed: false, reason: \"The close pattern needs the explicit reviewed flag before any tab closes.\" };\n }\n if (kind === \"duplicatetab\" || kind === \"pintab\" || kind === \"mutetab\" || kind === \"movetab\" || kind === \"movetabwindow\" || kind === \"badgetab\" || kind === \"attachmeta\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser tab id is required.\" };\n }\n if (kind === \"focuswindow\" || kind === \"maximizewindow\" || kind === \"minimizewindow\" || kind === \"restorewindow\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser window id is required.\" };\n }\n if (kind === \"pintab\" && typeof options.pinned !== \"boolean\") return { allowed: false, reason: \"A reviewed pinned flag is required in options.\" };\n if (kind === \"mutetab\" && typeof options.muted !== \"boolean\") return { allowed: false, reason: \"A reviewed muted flag is required in options.\" };\n if (kind === \"movetab\") {\n if (typeof options.index !== \"number\" || !Number.isInteger(options.index) || options.index < 0) return { allowed: false, reason: \"A reviewed non-negative target index is required in options.\" };\n }\n if (kind === \"movetabwindow\") {\n if (typeof options.windowid !== \"number\" || !Number.isInteger(options.windowid) || options.windowid < 0) return { allowed: false, reason: \"A reviewed target window id is required in options.\" };\n }\n if (kind === \"grouptabs\") {\n const group = options.group;\n if (!group || typeof group !== \"object\" || Array.isArray(group)) return { allowed: false, reason: \"A reviewed group with a name is required in options.\" };\n const spec = group as Record<string, unknown>;\n if (!isnonempty(spec.name)) return { allowed: false, reason: \"The reviewed group needs a non-empty name.\" };\n if (!validategroupcolor(spec.color)) return { allowed: false, reason: \"The reviewed group color must be a Chromium tab group color.\" };\n if (!validateidlist(spec, \"tabids\")) return { allowed: false, reason: \"The reviewed group needs a non-empty list of member tab ids.\" };\n }\n if (kind === \"colorgroup\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed group name is required in options.\" };\n if (!validategroupcolor(options.color)) return { allowed: false, reason: \"The reviewed group color must be a Chromium tab group color.\" };\n }\n if (kind === \"collapsegroup\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed group name is required in options.\" };\n if (typeof options.collapsed !== \"boolean\") return { allowed: false, reason: \"A reviewed collapsed flag is required in options.\" };\n }\n if (kind === \"discardtab\" || kind === \"reloadtabs\") {\n if (!isnumericid(step.value) && !validateidlist(options, \"tabs\")) return { allowed: false, reason: \"A numeric tab id or a reviewed list of tab ids is required.\" };\n }\n if (kind === \"zoomin\" || kind === \"zoomout\") {\n if (options.step !== undefined && (typeof options.step !== \"number\" || !Number.isFinite(options.step) || options.step <= 0)) return { allowed: false, reason: \"The reviewed zoom step must be a positive number with no code ceiling.\" };\n if (step.value !== undefined && step.value !== \"\" && !isnumericid(step.value)) return { allowed: false, reason: \"The reviewed zoom target must be a numeric tab id.\" };\n }\n if (kind === \"switchtab\") {\n if (options.direction !== \"next\" && options.direction !== \"previous\") return { allowed: false, reason: \"A reviewed switch direction of next or previous is required in options.\" };\n }\n if (kind === \"restorewindow\") {\n const bounds = options.bounds;\n if (bounds !== undefined) {\n if (!bounds || typeof bounds !== \"object\" || Array.isArray(bounds)) return { allowed: false, reason: \"The reviewed window bounds must be an object.\" };\n const shape = bounds as Record<string, unknown>;\n for (const field of [\"left\", \"top\", \"width\", \"height\"]) {\n if (typeof shape[field] !== \"number\" || !Number.isFinite(shape[field])) return { allowed: false, reason: \"The reviewed window bounds need numeric left, top, width and height.\" };\n }\n }\n }\n if (kind === \"scratchwindow\") {\n if (step.value !== undefined && step.value !== \"\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed scratch window url must use HTTPS.\" };\n }\n if (kind === \"incognitowindow\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS url is required to open an incognito window.\" };\n if (kind === \"restoretab\" && step.value !== undefined && step.value !== \"\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed restore url must use HTTPS.\" };\n if (kind === \"savelayout\" || kind === \"restorelayout\") {\n if (!isnonempty(options.name)) return { allowed: false, reason: \"A reviewed layout name is required in options.\" };\n }\n if (kind === \"badgetab\") {\n if (!isnonempty(options.label)) return { allowed: false, reason: \"A reviewed badge label is required in options.\" };\n if (options.taskid !== undefined && !isnonempty(options.taskid)) return { allowed: false, reason: \"The reviewed badge task id must be a non-empty string.\" };\n }\n if (kind === \"attachmeta\") {\n const labels = options.labels;\n const taskrefs = options.taskrefs;\n const haslabels = Array.isArray(labels) && labels.length > 0 && labels.every(label => isnonempty(label));\n const hastaskrefs = Array.isArray(taskrefs) && taskrefs.length > 0 && taskrefs.every(ref => isnonempty(ref));\n if (!haslabels && !hastaskrefs) return { allowed: false, reason: \"Reviewed labels or task refs are required in options to attach metadata.\" };\n if (options.provenance !== undefined && !isnonempty(options.provenance)) return { allowed: false, reason: \"The reviewed provenance must be a non-empty string.\" };\n }\n if (kind === \"reopenrun\" && !isnonempty(options.run)) return { allowed: false, reason: \"A reviewed run id is required in options to reopen its tabs.\" };\n return { allowed: true };\n}\n\n/** True when the kind belongs to the media capture family of pdf documents, recordings, images, canvases, streams, assets, lapses, conversions and thumbnails. */\nexport function ismediakind(kind: actionkind): boolean {\n return mediaactions.has(kind);\n}\n\n/** True when the kind belongs to the network observation family of fetching, parsing and typed calls. */\nexport function ishttpkind(kind: actionkind): boolean {\n return httpactions.has(kind);\n}\n\n/** True when the kind belongs to the socket and stream family of channels, messages, subscriptions and poll loops. */\nexport function issocketkind(kind: actionkind): boolean {\n return socketactions.has(kind);\n}\n\n/** True when the kind belongs to the request observation family of watches, headers, bodies and page api discovery. */\nexport function isnetwatchkind(kind: actionkind): boolean {\n return netwatchactions.has(kind);\n}\n\n/** True when the kind belongs to the network control family of blocking, mocking, header rewriting, cookies, auth, api keys, proxy routing and uploads. */\nexport function iscontrolkind(kind: actionkind): boolean {\n return controlactions.has(kind);\n}\n\n/** Resolves the reviewed risk of one step: capturebodies grades sensitive when the reviewed mime list carries private payload types and extractapi grades sensitive when the replay verb mutates, while every other kind keeps its risk table grade. */\nexport function resolvedrisk(step: toolstep): \"read\" | \"interaction\" | \"sensitive\" {\n if (step.kind === \"capturebodies\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const body = options.body;\n const mimes = body && typeof body === \"object\" && !Array.isArray(body) ? (body as Record<string, unknown>).mimes : undefined;\n if (Array.isArray(mimes) && mimes.some(mime => typeof mime === \"string\" && privatemime(mime))) return \"sensitive\";\n return \"interaction\";\n }\n if (step.kind === \"extractapi\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const replay = options.replay;\n const verb = replay && typeof replay === \"object\" && !Array.isArray(replay) ? (replay as Record<string, unknown>).verb : undefined;\n if (typeof verb === \"string\" && ![\"GET\", \"HEAD\", \"OPTIONS\"].includes(verb.trim().toUpperCase())) return \"sensitive\";\n return \"read\";\n }\n return actionrisk(step.kind);\n}\n\n/** Restricts every outbound channel to a granted origin: wss websocket and https event stream urls map onto their https origin, carry no embedded credentials and stay inside the session origin grants. */\nexport function socketgate(session: agentsession | undefined, url: string): policyevaluation {\n let parsed: URL;\n try { parsed = new URL(url); } catch { return { allowed: false, reason: \"The channel needs a valid url before it can be reviewed.\" }; }\n if (parsed.protocol !== \"wss:\" && parsed.protocol !== \"https:\") return { allowed: false, reason: \"Channels use wss websocket urls or https event stream urls only.\" };\n if (parsed.username || parsed.password) return { allowed: false, reason: \"Channel credentials are not allowed in the url.\" };\n const origin = channelorigin(url);\n if (!origingranted(session, origin)) return { allowed: false, reason: `The channel to ${origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** Requires the user granted request watching before any watchrequests step runs; the observation derives from the page timing buffers and the grant adds no manifest permission. */\nexport function watchgate(session: agentsession | undefined, settings: runsettings | undefined, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the request watch.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot watch requests.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot watch requests.\" };\n if (settings?.webrequestgrant !== true) return { allowed: false, reason: \"Request watching needs the webrequest grant in the review panel first; the observation derives from the page timing buffers and adds no manifest permission.\" };\n return { allowed: true };\n}\n\n/** Requires the host grant for every observed origin before header reads, body captures and endpoint replays touch an exchange. */\nexport function observedorigingranted(session: agentsession | undefined, url: string): policyevaluation {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { return { allowed: false, reason: \"The observed exchange url does not parse for an origin check.\" }; }\n if (!origingranted(session, origin)) return { allowed: false, reason: `The observed origin ${origin} stays outside the session origin grants; grant it before reading headers, bodies or replays.` };\n return { allowed: true };\n}\n\n/** Restricts every outbound request to a granted origin: the url must be a reviewed HTTPS url inside the session origin grants. */\nexport function origincheck(session: agentsession | undefined, url: string): policyevaluation {\n let parsed: URL;\n try { parsed = new URL(url); } catch { return { allowed: false, reason: \"The outbound request needs a valid url before it can be reviewed.\" }; }\n if (parsed.protocol !== \"https:\") return { allowed: false, reason: \"Outbound requests use HTTPS urls only.\" };\n if (parsed.username || parsed.password) return { allowed: false, reason: \"Endpoint credentials are not allowed in the url.\" };\n if (!origingranted(session, parsed.origin)) return { allowed: false, reason: `The outbound request to ${parsed.origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** True when a header name carries credentials and therefore needs the explicit consent that names it. */\nexport function credentialheadername(name: string): boolean {\n return credentialheaders.has(name.trim().toLowerCase());\n}\n\n/** Requires a reviewed consent ref before any custom header leaves the extension; requests without custom headers need no prompt. */\nexport function fetchconsentrefgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const request = options.fetch;\n const headers = request && typeof request === \"object\" && !Array.isArray(request) ? (request as Record<string, unknown>).headers : undefined;\n const names = headers && typeof headers === \"object\" && !Array.isArray(headers) ? Object.keys(headers as Record<string, unknown>) : [];\n if (names.length === 0) return { allowed: true };\n const empty = names.some(name => !name.trim());\n if (empty) return { allowed: false, reason: \"Header allowlists with empty names are refused.\" };\n const credential = names.find(name => credentialheadername(name));\n if (credential !== undefined && !isnonempty(options.consentref)) return { allowed: false, reason: `The credential bearing header ${credential} needs the explicit reviewed consent that names it before it is sent.` };\n if (!isnonempty(options.consentref)) return { allowed: false, reason: `The ${names.length} reviewed custom header${names.length === 1 ? \"\" : \"s\"} need a reviewed consent ref in options before any send.` };\n return { allowed: true };\n}\n\n/** True when one stored fetch consent still covers the origin and every header name inside its expiry window. */\nexport function fetchconsentcovers(consent: { origin: string; headers: Array<{ name: string }>; approved?: boolean; expiresat: number }, origin: string, headernames: string[], now: number): boolean {\n if (consent.approved !== true) return false;\n if (consent.expiresat <= now) return false;\n if (consent.origin !== origin) return false;\n const covered = new Set(consent.headers.map(header => header.name.trim().toLowerCase()));\n return headernames.every(name => covered.has(name.trim().toLowerCase()));\n}\n\n/** True when the reviewed call mutates: rest verbs beyond get, head and options or a graphql mutation; mutating calls grade sensitive. */\nexport function mutationcallof(step: toolstep): boolean {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (step.kind === \"callgraphql\") {\n const request = options.graphql;\n return Boolean(request && typeof request === \"object\" && !Array.isArray(request) && (request as Record<string, unknown>).operationkind === \"mutation\");\n }\n if (step.kind === \"callrest\") {\n const method = typeof options.method === \"string\" ? options.method.trim().toUpperCase() : undefined;\n if (method !== undefined) return ![\"GET\", \"HEAD\", \"OPTIONS\"].includes(method);\n }\n return false;\n}\n\n/** Keeps the reviewed fetch waits inside the reviewed wait budget: the worst case of every timeout plus every backoff wait must fit; every bound itself stays a user choice with no code ceiling. */\nexport function fetchbudgetallowed(timeout: number | undefined, retries: number | undefined, backoff: number | undefined, wait: number | undefined): policyevaluation {\n for (const [label, value] of [[\"timeout\", timeout], [\"retries\", retries], [\"backoff\", backoff]] as Array<[string, number | undefined]>) {\n if (value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)) return { allowed: false, reason: `The reviewed fetch ${label} must be zero or a positive number with no code ceiling.` };\n }\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed fetch wait budget must be zero or a positive number of milliseconds.\" };\n if (wait === undefined || timeout === undefined) return { allowed: true };\n const attempts = Math.max(1, Math.floor((retries ?? 0)) + 1);\n const waits = (backoff ?? 0) * (attempts * (attempts - 1)) / 2;\n const worstcase = timeout * attempts + waits;\n if (worstcase > wait) return { allowed: false, reason: `The fetch worst case of ${worstcase} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or fewer retries.` };\n return { allowed: true };\n}\n\n/** Resolves the outbound url of an http step at review time: the fetch request url of a fetchurl step and nothing for typed calls whose endpoints resolve at execution. */\nexport function outboundtarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const request = options.fetch;\n if (request && typeof request === \"object\" && !Array.isArray(request)) {\n const url = (request as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n return undefined;\n}\n\n/** Validates one reviewed typed endpoint definition: name, method, HTTPS url template with variables, header allowlist with non-empty names and a payload schema with kinds, required flags and defaults. */\nexport function validateendpointrecord(value: unknown): policyevaluation {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"A reviewed endpoint record is required.\" };\n const record = value as Record<string, unknown>;\n if (!isnonempty(record.name)) return { allowed: false, reason: \"The endpoint record needs a reviewed non-empty name.\" };\n if (!isnonempty(record.method)) return { allowed: false, reason: \"The endpoint record needs a reviewed method.\" };\n if (!ishttpsurl(record.url)) return { allowed: false, reason: \"The endpoint record url template must be an HTTPS url.\" };\n if (record.headers !== undefined) {\n if (!record.headers || typeof record.headers !== \"object\" || Array.isArray(record.headers)) return { allowed: false, reason: \"The endpoint header allowlist must be an object of reviewed headers.\" };\n for (const name of Object.keys(record.headers as Record<string, unknown>)) {\n if (!name.trim()) return { allowed: false, reason: \"Endpoint header allowlists with empty names are refused.\" };\n const headervalue = (record.headers as Record<string, unknown>)[name];\n if (typeof headervalue !== \"string\") return { allowed: false, reason: `The endpoint header ${name} needs a reviewed string value.` };\n }\n }\n const schema = record.schema;\n if (!schema || typeof schema !== \"object\" || Array.isArray(schema)) return { allowed: false, reason: \"Every typed endpoint call needs a reviewed payload schema; endpoint records without schemas are refused.\" };\n const fields = (schema as Record<string, unknown>).fields;\n if (!Array.isArray(fields) || fields.length === 0) return { allowed: false, reason: \"The endpoint payload schema needs a non-empty field list.\" };\n for (const item of fields) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every payload schema field must be an object.\" };\n const field = item as Record<string, unknown>;\n if (!isnonempty(field.name)) return { allowed: false, reason: \"Every payload schema field needs a non-empty name.\" };\n if (field.kind !== \"string\" && field.kind !== \"number\" && field.kind !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} must be a string, number or boolean kind.` };\n if (field.required !== undefined && typeof field.required !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} required flag must be a boolean.` };\n if (field.default !== undefined && typeof field.default !== \"string\" && typeof field.default !== \"number\" && typeof field.default !== \"boolean\") return { allowed: false, reason: `The payload schema field ${field.name} default must match its kind.` };\n }\n return { allowed: true };\n}\n\n/** Validates one dotted json path against the path grammar: non-empty segments of names, digits, underscores or hyphens. */\nfunction validpath(path: string): boolean {\n return path.split(\".\").every(segment => /^[A-Za-z0-9_-]+$/.test(segment));\n}\n\n/** Validates the reviewed network observation parameter grammar of the 1.1.42 family: fetch requests with header allowlists, fetch policies with timeout, retries, backoff and follow limit, stream budgets, dotted json paths, html queries, graphql operations and typed endpoint references; every bound stays a user choice with no code ceiling. */\nfunction validatehttpgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"fetchurl\") {\n const request = options.fetch;\n if (!request || typeof request !== \"object\" || Array.isArray(request)) return { allowed: false, reason: \"A reviewed fetch request with a url is required in options.fetch.\" };\n const fetchrequest = request as Record<string, unknown>;\n if (typeof fetchrequest.url !== \"string\" || !fetchrequest.url.trim()) return { allowed: false, reason: \"The reviewed fetch request needs a non-empty url.\" };\n if (fetchrequest.method !== undefined && (typeof fetchrequest.method !== \"string\" || ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(fetchrequest.method.trim().toUpperCase()))) return { allowed: false, reason: \"The reviewed fetch method must be a known HTTP verb.\" };\n if (fetchrequest.headers !== undefined) {\n if (!fetchrequest.headers || typeof fetchrequest.headers !== \"object\" || Array.isArray(fetchrequest.headers)) return { allowed: false, reason: \"The reviewed header allowlist must be an object of custom headers.\" };\n for (const name of Object.keys(fetchrequest.headers as Record<string, unknown>)) {\n if (!name.trim()) return { allowed: false, reason: \"Header allowlists with empty names are refused.\" };\n if (typeof (fetchrequest.headers as Record<string, unknown>)[name] !== \"string\") return { allowed: false, reason: `The reviewed header ${name} needs a string value.` };\n }\n }\n if (fetchrequest.body !== undefined && typeof fetchrequest.body !== \"string\") return { allowed: false, reason: \"The reviewed fetch body must be a string.\" };\n if (fetchrequest.mode !== undefined && fetchrequest.mode !== \"cors\" && fetchrequest.mode !== \"no-cors\" && fetchrequest.mode !== \"same-origin\") return { allowed: false, reason: \"The reviewed fetch mode must be cors, no-cors or same-origin.\" };\n const consentgate = fetchconsentrefgranted(step);\n if (!consentgate.allowed) return consentgate;\n const policycheck = validatefetchoptions(options.fetchoptions);\n if (!policycheck.allowed) return policycheck;\n const fetchpolicy = fetchoptionsvalues(options.fetchoptions);\n const budget = fetchbudgetallowed(fetchpolicy.timeout, fetchpolicy.retries, fetchpolicy.backoff, fetchnumeric(options, \"wait\"));\n if (!budget.allowed) return budget;\n if (options.stream !== undefined) {\n if (!options.stream || typeof options.stream !== \"object\" || Array.isArray(options.stream)) return { allowed: false, reason: \"The reviewed stream window must be an object with an optional byte budget.\" };\n const streambudget = (options.stream as Record<string, unknown>).budget;\n if (streambudget !== undefined && (typeof streambudget !== \"number\" || !Number.isFinite(streambudget) || streambudget < 0)) return { allowed: false, reason: \"The reviewed stream byte budget must be zero or a positive number of bytes with no code ceiling.\" };\n }\n }\n if (kind === \"parsejson\") {\n if (!isnonempty(options.call)) return { allowed: false, reason: \"A reviewed stored call id is required in options.call before the body parses.\" };\n const fields = options.fields;\n if (!Array.isArray(fields) || fields.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of json path rules is required in options.fields.\" };\n for (const item of fields) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every json path rule must be an object.\" };\n const rule = item as Record<string, unknown>;\n if (!isnonempty(rule.name)) return { allowed: false, reason: \"Every json path rule needs a non-empty field name.\" };\n if (typeof rule.path !== \"string\" || !rule.path.trim() || !validpath(rule.path.trim())) return { allowed: false, reason: `The json path of ${rule.name} must be a dotted path of non-empty segments.` };\n if (rule.kind !== undefined && rule.kind !== \"text\" && rule.kind !== \"number\" && rule.kind !== \"boolean\" && rule.kind !== \"json\") return { allowed: false, reason: `The json path kind of ${rule.name} must be text, number, boolean or json.` };\n }\n }\n if (kind === \"parsehtml\") {\n if (!isnonempty(options.call)) return { allowed: false, reason: \"A reviewed stored call id is required in options.call before the markup parses.\" };\n const queries = options.queries;\n if (!Array.isArray(queries) || queries.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of html queries is required in options.queries.\" };\n for (const item of queries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { allowed: false, reason: \"Every html query must be an object.\" };\n const query = item as Record<string, unknown>;\n if (!isnonempty(query.selector)) return { allowed: false, reason: \"Every html query needs a selector from the reviewed selector grammar.\" };\n if (query.attribute !== undefined && !isnonempty(query.attribute)) return { allowed: false, reason: \"The reviewed html query attribute must be a non-empty attribute name.\" };\n if (query.multi !== undefined && typeof query.multi !== \"boolean\") return { allowed: false, reason: \"The reviewed html query multi flag must be a boolean.\" };\n }\n }\n if (kind === \"callrest\" || kind === \"callgraphql\") {\n if (!isnonempty(options.endpoint)) return { allowed: false, reason: \"A reviewed typed endpoint name is required in options.endpoint.\" };\n if (kind === \"callrest\") {\n if (options.payload !== undefined && (!options.payload || typeof options.payload !== \"object\" || Array.isArray(options.payload))) return { allowed: false, reason: \"The reviewed rest payload must be an object of reviewed values.\" };\n if (options.method !== undefined && (typeof options.method !== \"string\" || ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(options.method.trim().toUpperCase()))) return { allowed: false, reason: \"The reviewed endpoint method override must be a known HTTP verb.\" };\n if (options.success !== undefined && (!Array.isArray(options.success) || !options.success.every(code => typeof code === \"number\" && Number.isInteger(code)))) return { allowed: false, reason: \"The reviewed success status list must be a list of integer status codes.\" };\n }\n if (kind === \"callgraphql\") {\n const request = options.graphql;\n if (!request || typeof request !== \"object\" || Array.isArray(request)) return { allowed: false, reason: \"A reviewed graphql request with an operation is required in options.graphql.\" };\n const graphql = request as Record<string, unknown>;\n if (typeof graphql.query !== \"string\" || !graphql.query.trim()) return { allowed: false, reason: \"The reviewed graphql operation text must be a non-empty string.\" };\n if (graphql.operationkind !== \"query\" && graphql.operationkind !== \"mutation\") return { allowed: false, reason: \"The reviewed graphql operation kind must be query or mutation; unknown operation kinds are refused.\" };\n if (graphql.variables !== undefined && (!graphql.variables || typeof graphql.variables !== \"object\" || Array.isArray(graphql.variables))) return { allowed: false, reason: \"The reviewed graphql variables must be an object of reviewed values.\" };\n if (graphql.operationname !== undefined && !isnonempty(graphql.operationname)) return { allowed: false, reason: \"The reviewed graphql operation name must be a non-empty string.\" };\n }\n if (options.apikeys !== undefined && (!Array.isArray(options.apikeys) || !options.apikeys.every(name => isnonempty(name)))) return { allowed: false, reason: \"The reviewed api key reference list must be a list of non-empty stored names.\" };\n const policycheck = validatefetchoptions(options.fetchoptions);\n if (!policycheck.allowed) return policycheck;\n const fetchpolicy = fetchoptionsvalues(options.fetchoptions);\n const budget = fetchbudgetallowed(fetchpolicy.timeout, fetchpolicy.retries, fetchpolicy.backoff, fetchnumeric(options, \"wait\"));\n if (!budget.allowed) return budget;\n }\n return { allowed: true };\n}\n\n/** Validates one reviewed fetch policy object: timeout, retries, backoff base and redirect follow limit stay user choices with no code ceiling. */\nfunction validatefetchoptions(value: unknown): policyevaluation {\n if (value === undefined) return { allowed: true };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return { allowed: false, reason: \"The reviewed fetch options must be an object with timeout, retries, backoff and follow.\" };\n const options = value as Record<string, unknown>;\n for (const key of [\"timeout\", \"backoff\"]) {\n if (options[key] !== undefined && (typeof options[key] !== \"number\" || !Number.isFinite(options[key]) || options[key] < 0)) return { allowed: false, reason: `The reviewed fetch ${key} must be zero or a positive number with no code ceiling.` };\n }\n for (const key of [\"retries\", \"follow\"]) {\n if (options[key] !== undefined && (typeof options[key] !== \"number\" || !Number.isInteger(options[key]) || options[key] < 0)) return { allowed: false, reason: `The reviewed fetch ${key} must be zero or a positive integer with no code ceiling.` };\n }\n return { allowed: true };\n}\n\n/** Reads the numeric fetch policy fields of one reviewed fetch options object. */\nfunction fetchoptionsvalues(value: unknown): { timeout?: number | undefined; retries?: number | undefined; backoff?: number | undefined } {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n const options = value as Record<string, unknown>;\n return { timeout: fetchnumeric(options, \"timeout\"), retries: fetchnumeric(options, \"retries\"), backoff: fetchnumeric(options, \"backoff\") };\n}\n\n/** Reads one numeric fetch policy field from the step options. */\nfunction fetchnumeric(options: Record<string, unknown>, key: string): number | undefined {\n const value = options[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\n/** True when the kind records user activity and needs the reviewed recording consent before it starts. */\nexport function isrecordingkind(kind: actionkind): boolean {\n return kind === \"recordscreen\" || kind === \"captureaudio\";\n}\n\n/** Validates the reviewed socket and stream parameter grammar of the 1.1.43 family: channel urls with protocols, reconnect budgets and backoff ceilings, multiplexed message payloads, message filters with dotted paths and match limits, event subscriptions with cancellation paths and long poll cursors with intervals kept inside the reviewed wait budget; every bound stays a user choice with no code ceiling. */\nfunction validatesocketgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"opensocket\") {\n const channel = channeloptionsof(options.socket);\n if (!channel) return { allowed: false, reason: \"A reviewed socket with a url is required in options.socket.\" };\n if (channel.options.reconnect !== undefined && !Number.isInteger(channel.options.reconnect)) return { allowed: false, reason: \"The reviewed socket reconnect budget must be an integer attempt count with no code ceiling.\" };\n for (const label of [\"backoff\", \"backoffceiling\"] as const) {\n const value = channel.options[label];\n if (value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)) return { allowed: false, reason: `The reviewed socket ${label} must be zero or a positive number of milliseconds with no code ceiling.` };\n }\n if (channel.options.lifetime !== undefined && (typeof channel.options.lifetime !== \"number\" || !Number.isFinite(channel.options.lifetime) || channel.options.lifetime <= 0)) return { allowed: false, reason: \"The reviewed socket lifetime window must be a positive number of milliseconds.\" };\n }\n if (kind === \"sendmessage\") {\n const message = options.message;\n if (!message || typeof message !== \"object\" || Array.isArray(message)) return { allowed: false, reason: \"A reviewed message with a channel, stream and payload is required in options.message.\" };\n const envelope = message as Record<string, unknown>;\n if (!isnonempty(envelope.channel)) return { allowed: false, reason: \"The reviewed message needs the open channel id in options.message.channel.\" };\n if (envelope.stream !== undefined && !isnonempty(envelope.stream)) return { allowed: false, reason: \"The reviewed message stream name must be a non-empty string.\" };\n if (typeof envelope.payload !== \"string\") return { allowed: false, reason: \"The reviewed message payload must be a string.\" };\n }\n if (kind === \"waitmessage\") {\n if (options.filter !== undefined) {\n const filter = options.filter;\n if (!filter || typeof filter !== \"object\" || Array.isArray(filter)) return { allowed: false, reason: \"The reviewed message filter must be an object of stream, path and limit.\" };\n const reviewed = filter as Record<string, unknown>;\n if (reviewed.stream !== undefined && !isnonempty(reviewed.stream)) return { allowed: false, reason: \"The reviewed message filter stream name must be a non-empty string.\" };\n if (reviewed.path !== undefined && (typeof reviewed.path !== \"string\" || !validpath(reviewed.path.trim()))) return { allowed: false, reason: \"The reviewed message filter path must be a dotted path of non-empty segments.\" };\n if (reviewed.limit !== undefined && (typeof reviewed.limit !== \"number\" || !Number.isInteger(reviewed.limit) || reviewed.limit < 1)) return { allowed: false, reason: \"The reviewed message match limit must be a positive integer with no code ceiling.\" };\n }\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed message wait budget must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"subscribesse\") {\n const subscription = subscriptionoptionsof(options.subscription);\n if (!subscription) return { allowed: false, reason: \"A reviewed subscription with an event stream url and a cancellation path is required in options.subscription.\" };\n const rawlifetime = options.subscription && typeof options.subscription === \"object\" && !Array.isArray(options.subscription) ? (options.subscription as Record<string, unknown>).lifetime : undefined;\n if (rawlifetime !== undefined && (typeof rawlifetime !== \"number\" || !Number.isFinite(rawlifetime) || rawlifetime <= 0)) return { allowed: false, reason: \"The reviewed subscription lifetime window must be a positive number of milliseconds.\" };\n }\n if (kind === \"longpoll\") {\n const cursor = pollcursorof(options.poll);\n if (!cursor) return { allowed: false, reason: \"A reviewed poll cursor with a url, cursor field, interval and stop condition is required in options.poll.\" };\n const wait = options.wait;\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed long poll wait budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && cursor.interval > wait) return { allowed: false, reason: `The long poll interval of ${cursor.interval} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter interval.` };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed request observation parameter grammar of the 1.1.43 family: watch windows with user configured match limits, header filters whose redaction list is required before any header value is stored, body filters with url patterns, mime lists and byte ceilings and api replay specs with known verbs and dotted extraction paths. */\nfunction validatenetwatchgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"watchrequests\") {\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined && (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0)) return { allowed: false, reason: \"The reviewed watch window must be zero or a positive number of milliseconds.\" };\n }\n if (options.limit !== undefined && (typeof options.limit !== \"number\" || !Number.isInteger(options.limit) || options.limit < 1)) return { allowed: false, reason: \"The reviewed watch match limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"readheaders\") {\n const headers = options.headers;\n if (!headers || typeof headers !== \"object\" || Array.isArray(headers)) return { allowed: false, reason: \"A reviewed header filter with a name allowlist and a redaction list is required in options.headers.\" };\n const reviewed = headers as Record<string, unknown>;\n if (!Array.isArray(reviewed.allow) || reviewed.allow.length === 0 || !reviewed.allow.every((name): name is string => isnonempty(name))) return { allowed: false, reason: \"The reviewed header allowlist must be a non-empty list of header names.\" };\n if (!Array.isArray(reviewed.redact) || reviewed.redact.length === 0 || !reviewed.redact.every((name): name is string => isnonempty(name))) return { allowed: false, reason: \"Header capture requires a reviewed redaction list before any header value is stored.\" };\n }\n if (kind === \"capturebodies\") {\n const body = options.body;\n if (!body || typeof body !== \"object\" || Array.isArray(body)) return { allowed: false, reason: \"A reviewed body filter with a url pattern, mime list and byte ceiling is required in options.body.\" };\n const reviewed = body as Record<string, unknown>;\n if (reviewed.urlpattern !== undefined && !isnonempty(reviewed.urlpattern)) return { allowed: false, reason: \"The reviewed body url pattern must be a non-empty string.\" };\n if (reviewed.mimes !== undefined && (!Array.isArray(reviewed.mimes) || reviewed.mimes.length === 0 || !reviewed.mimes.every((mime): mime is string => isnonempty(mime)))) return { allowed: false, reason: \"The reviewed body mime list must be a non-empty list of mime types.\" };\n if (reviewed.ceiling !== undefined && (typeof reviewed.ceiling !== \"number\" || !Number.isFinite(reviewed.ceiling) || reviewed.ceiling < 0)) return { allowed: false, reason: \"The reviewed body byte ceiling must be zero or a positive number of bytes with no code ceiling.\" };\n }\n if (kind === \"mapapi\") {\n if (options.limit !== undefined && (typeof options.limit !== \"number\" || !Number.isInteger(options.limit) || options.limit < 1)) return { allowed: false, reason: \"The reviewed mapapi match limit must be a positive integer with no code ceiling.\" };\n }\n if (kind === \"extractapi\") {\n const replay = apireplayspecof(options.replay);\n if (!replay) return { allowed: false, reason: \"A reviewed replay spec with an endpoint is required in options.replay.\" };\n if (!ishttpsurl(replay.endpoint)) return { allowed: false, reason: \"The reviewed replay endpoint must be an HTTPS url.\" };\n if (replay.verb !== undefined && ![\"GET\", \"HEAD\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"].includes(replay.verb)) return { allowed: false, reason: \"The reviewed replay verb must be a known HTTP verb.\" };\n for (const path of replay.paths ?? []) {\n if (!validpath(path.trim())) return { allowed: false, reason: `The reviewed replay extraction path ${path} must be a dotted path of non-empty segments.` };\n }\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed network control parameter grammar of the 1.1.44 family: block rules with url patterns that name their origin, mock fixtures reviewed with their full body, header rewrite rules with named origin patterns and set, append and remove operations, cookie records scoped to granted domains, oauth flows with provider consent refs, api key entries behind explicit consent, proxy routes with required bypass lists, urlencoded form payloads and multipart uploads whose every file carries the explicit reviewed flag; every bound stays a user choice with no code ceiling. */\nfunction validatecontrolgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"blockrequest\") {\n const rule = blockruleof(options.block);\n if (!rule) return { allowed: false, reason: \"A reviewed block rule with a url pattern is required in options.block.\" };\n if (patternorigin(rule.urlpattern) === undefined) return { allowed: false, reason: \"Block rules need an https origin pattern; patterns without a named origin are refused.\" };\n if ((options.block as Record<string, unknown>).reviewed !== true) return { allowed: false, reason: \"The block rule carries the explicit reviewed flag before any request is blocked.\" };\n }\n if (kind === \"mockresponse\") {\n const spec = mockspecof(options.mock);\n if (!spec) return { allowed: false, reason: \"A reviewed mock fixture with a url pattern, status and its reviewed body or a captured body ref is required in options.mock.\" };\n if (patternorigin(spec.urlpattern) === undefined) return { allowed: false, reason: \"Mock fixtures need an https origin pattern; patterns without a named origin are refused.\" };\n if (spec.reviewed !== true) return { allowed: false, reason: \"Every mock fixture is reviewed with its full body or the referenced captured body through the explicit reviewed flag before it serves.\" };\n }\n if (kind === \"rewriteheaders\") {\n const rules = options.rules;\n if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of header rewrite rules is required in options.rules.\" };\n for (const item of rules) {\n const rule = headeruleof(item);\n if (!rule) return { allowed: false, reason: \"Every header rewrite rule needs a url pattern, header name, a set, append or remove operation and its value.\" };\n if (patternorigin(rule.urlpattern) === undefined) return { allowed: false, reason: \"Header rewrite rules must name their origin pattern explicitly; patterns without a named origin are refused.\" };\n }\n }\n if (kind === \"setcookies\") {\n const cookies = options.cookies;\n if (!Array.isArray(cookies) || cookies.length === 0) return { allowed: false, reason: \"A reviewed non-empty list of cookie records is required in options.cookies.\" };\n for (const item of cookies) {\n if (!cookierecordof(item)) return { allowed: false, reason: \"Every cookie record needs a name, domain, path and reviewed string value with an optional expiry.\" };\n }\n }\n if (kind === \"readcookies\" && options.domain !== undefined && !isnonempty(options.domain)) return { allowed: false, reason: \"The reviewed cookie read domain must be a non-empty host.\" };\n if (kind === \"clearcookies\") {\n if (!isnonempty(options.domain)) return { allowed: false, reason: \"A reviewed cookie domain is required before cookies are cleared.\" };\n if (options.names !== undefined && (!Array.isArray(options.names) || options.names.length === 0 || !options.names.every((name): name is string => isnonempty(name)))) return { allowed: false, reason: \"The reviewed cookie clear list must be a non-empty list of cookie names when present.\" };\n }\n if (kind === \"authflow\") {\n const flow = oauthflowof(options.oauth);\n if (!flow) return { allowed: false, reason: \"A reviewed oauth flow with provider, authorize url, token url, scopes and redirect origin is required in options.oauth.\" };\n if (!ishttpsurl(flow.authorizeurl) || !ishttpsurl(flow.tokenurl)) return { allowed: false, reason: \"The oauth authorize and token urls must use HTTPS.\" };\n if (!ishttpsurl(flow.redirectorigin) && !/^https:\\/\\/[^/]+\\/?$/.test(flow.redirectorigin)) return { allowed: false, reason: \"The oauth redirect origin must be an HTTPS origin inside the grants.\" };\n const consent = authconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"saveapikey\") {\n const key = options.key;\n if (!key || typeof key !== \"object\" || Array.isArray(key)) return { allowed: false, reason: \"A reviewed api key entry with name, origin scopes and header is required in options.key.\" };\n const entry = key as Record<string, unknown>;\n if (!isnonempty(entry.name)) return { allowed: false, reason: \"The api key entry needs a reviewed non-empty name.\" };\n if (!Array.isArray(entry.origins) || entry.origins.length === 0 || !entry.origins.every((item): item is string => ishttpsurl(item))) return { allowed: false, reason: \"The api key needs a reviewed non-empty list of HTTPS origin scopes.\" };\n if (!isnonempty(entry.header)) return { allowed: false, reason: \"The api key entry needs a reviewed non-empty header name.\" };\n if (typeof entry.value !== \"string\" || !entry.value) return { allowed: false, reason: \"The api key needs its secret value in the reviewed options; it never enters the audit trail.\" };\n const consent = apikeyconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"routeproxy\") {\n if (!proxyrouteof(options.proxy)) return { allowed: false, reason: \"A reviewed proxy route with scheme, host, port and a non-empty bypass list is required in options.proxy.\" };\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"Proxy routing needs the explicit reviewed consent ref before any route applies.\" };\n }\n if (kind === \"postform\") {\n const form = formpayloadof(options.form);\n if (!form) return { allowed: false, reason: \"A reviewed form payload with a url and a non-empty field list is required in options.form.\" };\n if (!ishttpsurl(form.url)) return { allowed: false, reason: \"The form submission target must use HTTPS.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed rate limit wait budget must be zero or a positive number of milliseconds.\" };\n }\n if (kind === \"postfiles\") {\n const upload = multipartpayloadof(options.upload);\n if (!upload) return { allowed: false, reason: \"A reviewed multipart upload with a url and reviewed files is required in options.upload; every file carries the explicit reviewed flag.\" };\n if (!ishttpsurl(upload.url)) return { allowed: false, reason: \"The multipart upload target must use HTTPS.\" };\n if (options.wait !== undefined && (typeof options.wait !== \"number\" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: \"The reviewed rate limit wait budget must be zero or a positive number of milliseconds.\" };\n }\n return { allowed: true };\n}\n\n/** Requires the reviewed block rule of a live session before any blockrequest runs: the rule must carry the explicit reviewed flag and the session must stay active, unpaused and unexpired; every rule applies for the run only and reverts at run end. */\nexport function blockgate(session: agentsession | undefined, step: toolstep, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the request block.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot block requests.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot block requests.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const rule = options.block;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule) || (rule as Record<string, unknown>).reviewed !== true) return { allowed: false, reason: \"Request blocking needs its reviewed block rule with the explicit reviewed flag before any rule applies.\" };\n if (!blockruleof(rule)) return { allowed: false, reason: \"The block rule needs a url pattern and an optional resource type list.\" };\n return { allowed: true };\n}\n\n/** Scopes every cookie kind to a granted domain of a live session: the domain must equal a granted origin host or sit beneath it, and every other domain is refused. */\nexport function cookiegate(session: agentsession | undefined, domain: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the cookie operation.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot touch cookies.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot touch cookies.\" };\n const grants = session.grants ?? [session.origin];\n if (!cookiedomaingranted(domain, grants)) return { allowed: false, reason: `The cookie domain ${domain} stays outside the session origin grants; cookie control refuses domains beyond the grants.` };\n return { allowed: true };\n}\n\n/** Requires the explicit reviewed consent before routeproxy changes routing: a live session, a reviewed consent ref and a valid route with its bypass list; the route applies for the run only and restores the previous state at run end. */\nexport function proxygate(session: agentsession | undefined, step: toolstep, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the proxy route.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot change routing.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot change routing.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (!isnonempty(options.consentref)) return { allowed: false, reason: \"Proxy routing needs the explicit reviewed consent ref before any route applies.\" };\n if (!proxyrouteof(options.proxy)) return { allowed: false, reason: \"The proxy route needs a scheme, host, port and a non-empty bypass list of origins that stay direct.\" };\n return { allowed: true };\n}\n\n/** Requires the reviewed provider consent prompt ref before any authflow runs. */\nexport function authconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"An oauth flow requires the reviewed provider consent prompt ref in options before it starts.\" };\n return { allowed: true };\n}\n\n/** Requires the explicit consent prompt ref before saveapikey stores a key. */\nexport function apikeyconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"Storing an api key requires the explicit reviewed consent prompt ref in options before anything is stored.\" };\n return { allowed: true };\n}\n\n/** Keeps the rate limit wait inside the reviewed wait budget as user configured behavior: the wait until the reset window passes must fit when a budget was reviewed; both bounds stay user choices with no code ceiling. */\nexport function ratelimitbudgetallowed(wait: number | undefined, budget: number | undefined): policyevaluation {\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The rate limit wait must be zero or a positive number of milliseconds.\" };\n if (budget !== undefined && (typeof budget !== \"number\" || !Number.isFinite(budget) || budget < 0)) return { allowed: false, reason: \"The reviewed rate limit budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && budget !== undefined && wait > budget) return { allowed: false, reason: `The rate limit wait of ${wait} milliseconds exceeds the reviewed budget of ${budget} milliseconds; review a wider budget or submit later.` };\n return { allowed: true };\n}\n\n/** Requires the active tab grant of the live session for every debugging kind: the timeline gate scopes console, error and task capture to the run tab only and refuses every other tab. */\nexport function timelinegate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the timeline capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture the timeline.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture the timeline.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The timeline capture needs the run tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The timeline capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** True when one approved console capture consent of that origin exists; console capture on a new origin prompts once and the approved decision persists. */\nexport function consoleconsentcovers(origin: string, consents: consoleconsentrecord[]): policyevaluation {\n if (consents.some(consent => consent.origin === origin && consent.approved === true)) return { allowed: true };\n return { allowed: false, reason: `Console capture on ${origin} needs the reviewed console consent first; approve the prompt in the review panel.` };\n}\n\n/** Requires the granted origin before stack frames are captured; stack capture outside the granted origin is refused. */\nexport function stackgate(session: agentsession | undefined, origin: string): policyevaluation {\n if (!origingranted(session, origin)) return { allowed: false, reason: `Stack capture of ${origin} stays outside the session origin grants.` };\n return { allowed: true };\n}\n\n/** Keeps the debug watch window inside the reviewed wait budget: the watch wait must fit the reviewed budget when one was reviewed; both bounds stay user choices with no code ceiling. */\nexport function debugwaitbudgetallowed(watchwindow: number | undefined, wait: number | undefined): policyevaluation {\n if (watchwindow !== undefined && (typeof watchwindow !== \"number\" || !Number.isFinite(watchwindow) || watchwindow < 0)) return { allowed: false, reason: \"The debug watch window must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && (typeof wait !== \"number\" || !Number.isFinite(wait) || wait < 0)) return { allowed: false, reason: \"The reviewed debug wait budget must be zero or a positive number of milliseconds.\" };\n if (watchwindow !== undefined && wait !== undefined && watchwindow > wait) return { allowed: false, reason: `The debug watch window of ${watchwindow} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter window.` };\n return { allowed: true };\n}\n\n/** Exposes the timeline retention window as a user configured choice; an absent value keeps every timeline entry forever while the level count summaries always survive. */\nexport function timelineretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.timelineretention;\n}\n\n/** Grades console diffing as read only comparison evidence: the diff compares two stored console outputs and touches no page or browser state. */\nexport function diffreviewgrade(): { risk: \"read\"; mode: \"diffing\"; evidence: \"comparison\" } {\n return { risk: \"read\", mode: \"diffing\", evidence: \"comparison\" };\n}\n\n/** Validates the reviewed debugging parameter grammar of the 1.1.45 family: a watch window inside the reviewed wait budget, level floors from the reviewed level set, source filters from the reviewed source grammar, spam rules with user configured thresholds, serialization depth bounds, rotation rules with no hardcoded entry ceiling and the required redaction pattern list before any console text is captured. */\nfunction validatetimelinegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n let watchwindow: number | undefined;\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed debug watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined) {\n if (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0) return { allowed: false, reason: \"The reviewed debug watch window must be zero or a positive number of milliseconds.\" };\n watchwindow = reviewed.window;\n }\n }\n const budgetcheck = debugwaitbudgetallowed(watchwindow, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n if (options.level !== undefined && !loglevels.includes(options.level as loglevel)) return { allowed: false, reason: `The reviewed level floor must be one of ${loglevels.join(\", \")}.` };\n if (options.sources !== undefined) {\n if (!Array.isArray(options.sources) || options.sources.length === 0 || !options.sources.every(source => timelinesources.includes(source as never))) return { allowed: false, reason: `The reviewed source filters must be a non-empty list of the reviewed timeline sources: ${timelinesources.join(\", \")}.` };\n }\n if (kind === \"watchconsole\") {\n if (options.redact === undefined || !Array.isArray(options.redact) || options.redact.length === 0 || !options.redact.every(pattern => isnonempty(pattern))) return { allowed: false, reason: \"Console capture requires a reviewed non-empty redaction pattern list before any console text is captured.\" };\n if (options.depth !== undefined && (typeof options.depth !== \"number\" || !Number.isInteger(options.depth) || options.depth < 1)) return { allowed: false, reason: \"The reviewed serialization depth bound must be a positive integer with no code ceiling.\" };\n if (options.spam !== undefined) {\n const rule = spamruleof(options.spam);\n if (!rule) return { allowed: false, reason: \"The reviewed spam rule needs a pattern, a window size and a collapse threshold.\" };\n if (rule.collapse < 1) return { allowed: false, reason: \"The reviewed spam collapse threshold must be a positive integer of user configured value with no code ceiling.\" };\n }\n if (options.rotation !== undefined) {\n const rule = rotationruleof(options.rotation);\n if (!rule) return { allowed: false, reason: \"The reviewed rotation rule needs a max entry count and an overflow target.\" };\n }\n }\n if (kind === \"watchtasks\") {\n if (options.threshold !== undefined && (typeof options.threshold !== \"number\" || !Number.isFinite(options.threshold) || options.threshold < 0)) return { allowed: false, reason: \"The reviewed long task threshold must be zero or a positive number of milliseconds with no code ceiling.\" };\n }\n return { allowed: true };\n}\n\n/** Normalizes a reviewed spam rule: the pattern, the window size and the collapse threshold as user configured values. */\nexport function spamruleof(value: unknown): spamrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const entry = value as Record<string, unknown>;\n const pattern = typeof entry.pattern === \"string\" ? entry.pattern : \"\";\n const windowsize = typeof entry.windowsize === \"number\" && Number.isFinite(entry.windowsize) && entry.windowsize >= 0 ? entry.windowsize : undefined;\n const collapse = typeof entry.collapse === \"number\" && Number.isInteger(entry.collapse) ? entry.collapse : undefined;\n if (windowsize === undefined || collapse === undefined) return undefined;\n return { pattern, windowsize, collapse };\n}\n\n/** Normalizes a reviewed log rotation rule: the max entries per run and the overflow target store with no hardcoded entry ceiling. */\nexport function rotationruleof(value: unknown): rotationrule | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const entry = value as Record<string, unknown>;\n const maxentries = typeof entry.maxentries === \"number\" && Number.isInteger(entry.maxentries) && entry.maxentries >= 1 ? entry.maxentries : undefined;\n const overflowtarget = typeof entry.overflowtarget === \"string\" && entry.overflowtarget.trim() ? entry.overflowtarget.trim() : undefined;\n if (maxentries === undefined || overflowtarget === undefined) return undefined;\n return { maxentries, overflowtarget };\n}\n\n/** Requires the active run tab grant of the live session for every devtools protocol kind: the debug gate scopes attaches, commands, watches, breakpoints, steps and overrides to the run tab only and refuses every other tab. */\nexport function debuggate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the devtools protocol step.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot run a devtools protocol step.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot run a devtools protocol step.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The devtools protocol step needs the run tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The devtools protocol step on ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** True when one approved debugger consent of that origin covers every requested domain; the first attachcdp of a run needs the approved record and revocation removes the coverage. */\nexport function debuggerconsentcovers(origin: string, domains: string[], grants: debuggergrant[]): policyevaluation {\n const needed = [...new Set(domains)];\n const covering = grants.find(grant => grant.origin === origin && grant.approved === true && grant.revokedat === undefined && needed.every(domain => grant.domains.includes(domain)));\n if (covering) return { allowed: true };\n if (grants.some(grant => grant.origin === origin && grant.revokedat !== undefined)) return { allowed: false, reason: `The debugger consent on ${origin} was revoked; approve a new prompt before the devtools protocol runs again.` };\n return { allowed: false, reason: `The devtools protocol on ${origin} needs the reviewed debugger consent for ${needed.join(\", \")} first; approve the prompt with the domain allowlist shown in the review panel.` };\n}\n\n/** The profiling target gate of every 1.1.47 kind: the live session run tab and origin grants come first, every iframe, worker and service worker target stays inside the granted origins, and the reviewed debugger grant of the origin covers every profiling instrument because profiling is debugger grade instrumentation. */\nexport function targetgate(input: { session: agentsession | undefined; tabid: number; origin: string; targets: attachtarget[]; grants: debuggergrant[] | undefined; now: number }): policyevaluation {\n const base = debuggate(input.session, input.tabid, input.origin, input.now);\n if (!base.allowed) return base;\n for (const target of input.targets) {\n if (target.kind === \"page\") continue;\n const origincheckresult = origincheck(input.session, target.url);\n if (!origincheckresult.allowed) return { allowed: false, reason: `The ${target.kind} target ${target.url} stays outside the granted origins; profiling refuses to attach.` };\n }\n if (input.grants === undefined) return { allowed: true };\n const consent = debuggerconsentcovers(input.origin, [], input.grants);\n if (!consent.allowed) return { allowed: false, reason: `The profiling step on ${input.origin} needs the reviewed debugger grant of the origin first; approve the prompt with the profiling derivation shown in the review panel.` };\n return { allowed: true };\n}\n\n/** True when one approved source map capture consent of that origin covers the capture; revocation removes the coverage and the next capture needs a new reviewed prompt. */\nexport function sourcemapconsentcovers(origin: string, consents: sourcemapconsent[]): policyevaluation {\n const covering = consents.find(consent => consent.origin === origin && consent.approved === true && consent.revokedat === undefined);\n if (covering) return { allowed: true };\n if (consents.some(consent => consent.origin === origin && consent.revokedat !== undefined)) return { allowed: false, reason: `The source map capture consent on ${origin} was revoked; approve a new prompt before another map file is fetched.` };\n return { allowed: false, reason: `The source map capture on ${origin} needs the reviewed per origin consent first; approve the prompt shown in the review panel.` };\n}\n\n/** Exposes the user configured retention window for the heavy profile bytes; an absent window keeps every snapshot, sample and trace file. */\nexport function profileretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.profileretention;\n}\n\n/** Exposes the user configured trace byte ceiling; an absent value never refuses a trace export because the cap stays a user choice only. */\nexport function traceceilingof(settings: runsettings | undefined): number | undefined {\n return settings?.traceceiling;\n}\n\n/** Validates one breakpoint condition against the reviewed expression grammar: member chains, literals of number, string, boolean and null, comparison and logic operators, negation and parentheses; assignments, calls and statements are refused. */\nexport function validatebreakpointcondition(condition: string): policyevaluation {\n const expression = condition.trim();\n if (expression.length === 0) return { allowed: false, reason: \"The breakpoint condition must not be empty.\" };\n if (/(?<![=!<>])=(?!=)/.test(expression)) return { allowed: false, reason: \"Breakpoint conditions refuse assignment because the reviewed grammar is comparison only.\" };\n if (/[A-Za-z_$][\\w$]*\\s*\\(/.test(expression)) return { allowed: false, reason: \"Breakpoint conditions refuse calls because the reviewed grammar is comparison only.\" };\n const literal = /^(?:-?\\d+(?:\\.\\d+)?|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|true|false|null)$/;\n const tokens = expression.match(/(?:[A-Za-z_$][\\w$]*|-?\\d+(?:\\.\\d+)?|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|===|!==|==|!=|>=|<=|&&|\\|\\||[!.<>()+\\-*\\/%])/g);\n if (tokens === null || tokens.join(\"\") !== expression.replace(/\\s+/g, \"\")) return { allowed: false, reason: \"The breakpoint condition must use the reviewed expression grammar of member chains, literals, comparisons, logic operators, negation and parentheses.\" };\n const identifierlike = /^(?:true|false|null)$/;\n for (const token of tokens) {\n if (literal.test(token) || identifierlike.test(token)) continue;\n if ([\"===\", \"!==\", \"==\", \"!=\", \">=\", \"<=\", \"&&\", \"||\", \"!\", \".\", \"(\", \")\", \"<\", \">\", \"+\", \"-\", \"*\", \"/\", \"%\"].includes(token)) continue;\n if (/^[A-Za-z_$][\\w$]*$/.test(token)) continue;\n return { allowed: false, reason: `The token ${token} of the breakpoint condition stays outside the reviewed expression grammar.` };\n }\n return { allowed: true };\n}\n\n/** Keeps the breakpoint count of one run inside the user configured ceiling: an absent ceiling never refuses a breakpoint because the cap stays a user choice only. */\nexport function breakpointbudgetallowed(active: number, ceiling: number | undefined): policyevaluation {\n if (ceiling === undefined) return { allowed: true };\n if (typeof ceiling !== \"number\" || !Number.isInteger(ceiling) || ceiling < 0) return { allowed: false, reason: \"The reviewed breakpoint ceiling must be zero or a positive integer of user configured value with no code ceiling.\" };\n if (active >= ceiling) return { allowed: false, reason: `The run already holds ${active} active breakpoint${active === 1 ? \"\" : \"s\"} and the reviewed breakpoint ceiling is ${ceiling}; revert one or review a wider ceiling.` };\n return { allowed: true };\n}\n\n/** Exposes the pause capture retention window as a user configured choice; an absent value keeps every pause capture with its call frames. */\nexport function pauseretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.pauseretention;\n}\n\n/** Exposes the user configured breakpoint ceiling; an absent value never refuses a breakpoint because the cap stays a user choice only. */\nexport function breakpointceilingof(settings: runsettings | undefined): number | undefined {\n return settings?.breakpointceiling;\n}\n\n/** Requires the review of every emulation layer before it applies: a live session on the run tab, an approved plan, the explicit reviewed flag on the layer options and the reviewed revert plan beside it. */\nexport function emugate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"emulate the run tab\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Emulation layers need an approved plan before they apply.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n if (options.reviewed !== true) return { allowed: false, reason: `The ${input.step.kind} layer needs the explicit reviewed flag before any mask applies.` };\n if (revertplanof(options.revertplan) === undefined) return { allowed: false, reason: `Every ${input.step.kind} layer needs a reviewed revert plan beside it before any mask applies.` };\n return { allowed: true };\n}\n\n/** Allows layer stacking only when the reviewed plan lists the steps: a second layer of one family needs at least two reviewed steps of that family in the same plan because the last applied layer wins conflicts. */\nexport function emulationstackallowed(plan: agentplan | undefined, kind: actionkind, active: number): policyevaluation {\n if (!plan) return { allowed: false, reason: \"Layer stacking needs the reviewed plan first.\" };\n const listed = plan.steps.filter(step => step.kind === kind).length;\n if (active >= listed) return { allowed: false, reason: `The plan lists ${listed} reviewed ${kind} step${listed === 1 ? \"\" : \"s\"} and ${active} layer${active === 1 ? \"\" : \"s\"} of that family are already active; stacking beyond the reviewed plan is refused.` };\n return { allowed: true };\n}\n\n/** True when one approved location consent of that origin covers the reviewed coordinates; the prompt shows the exact latitude and longitude before emulatelocate applies. */\nexport function locationconsentgate(origin: string, latitude: number, longitude: number, consents: locationconsent[]): policyevaluation {\n if (consents.some(consent => consent.origin === origin && consent.revokedat !== undefined)) return { allowed: false, reason: `The location consent on ${origin} was revoked; approve a new prompt before the location override runs again.` };\n if (locationconsentcovers(origin, latitude, longitude, consents)) return { allowed: true };\n return { allowed: false, reason: `The location override of ${latitude}, ${longitude} on ${origin} needs the reviewed location consent first; approve the prompt with the coordinates shown in the review panel.` };\n}\n\n/** Exposes the user configured retention window for reverted emulation layer states; an absent window keeps every prior state while the layer history always survives. */\nexport function emulationretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.emulationretention;\n}\n\n/** Validates the reviewed emulation parameter grammar of the 1.1.48 family: device presets with width, height, pixel ratio and the mobile flag plus the reviewed reload flag, network presets with latency, download and upload bounds and the offline window, location presets inside the latitude and longitude ranges behind the location consent, agent presets of the reviewed user agent grammar with platform and brand list, permission overrides of the reviewed browser permission set graded by name, blackbox rules of explicit origin patterns with their trace scope, and the reviewed revert plan beside every layer. */\nfunction validateemulationgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (revertplanof(options.revertplan) === undefined) return { allowed: false, reason: `Every ${kind} layer needs a reviewed revert plan before any mask applies.` };\n if (kind === \"emulatedevice\") {\n const preset = devicepresetof(options.device);\n if (!preset) return { allowed: false, reason: \"The device layer needs a reviewed preset with a name, positive integer width and height and a positive pixel ratio.\" };\n if (options.reload !== undefined && typeof options.reload !== \"boolean\") return { allowed: false, reason: \"The reviewed reload flag must be a boolean; the page reloads only when the reviewed plan asks.\" };\n return { allowed: true };\n }\n if (kind === \"emulatenetwork\") {\n const preset = networkpresetof(options.network);\n if (!preset) return { allowed: false, reason: \"The network layer needs a reviewed preset with a name and zero or positive latency, download and upload bounds.\" };\n if (options.window !== undefined && (typeof options.window !== \"number\" || !Number.isFinite(options.window) || options.window < 0)) return { allowed: false, reason: \"The reviewed offline window must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"emulatelocate\") {\n const preset = locationpresetof(options.location);\n if (!preset) return { allowed: false, reason: \"The location layer needs a reviewed preset with a name, a latitude inside -90 and 90, a longitude inside -180 and 180 and a zero or positive accuracy radius.\" };\n if (!locationrangevalid(preset.latitude, preset.longitude)) return { allowed: false, reason: \"The reviewed latitude must stay inside -90 and 90 degrees and the longitude inside -180 and 180 degrees.\" };\n return { allowed: true };\n }\n if (kind === \"setuseragent\") {\n const preset = agentpresetof(options.agent);\n if (!preset) return { allowed: false, reason: \"The agent layer needs a reviewed preset with a user agent string of the reviewed grammar, a platform and a non-empty brand list.\" };\n if (!agentgrammarvalid(preset.useragent)) return { allowed: false, reason: \"The reviewed user agent string must use the reviewed grammar of tokens, separators and version marks without line breaks.\" };\n return { allowed: true };\n }\n if (kind === \"overridepermission\") {\n const grant = permissiongrantof(options.permission);\n if (!grant) return { allowed: false, reason: `The permission override needs a reviewed name of the browser permission set (${browserpermissions.join(\", \")}) and a state of ${permissionstates.join(\", \")}.` };\n void permissiongrade(grant.name);\n return { allowed: true };\n }\n if (kind === \"blackboxscripts\") {\n const rules = Array.isArray(options.rules) ? options.rules.flatMap(rule => { const parsed = blackboxruleof(rule); return parsed !== undefined ? [parsed] : []; }) : [];\n if (rules.length === 0) return { allowed: false, reason: \"The blackbox layer needs a reviewed non-empty rule list where every pattern names its origin explicitly and carries a trace scope.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Validates one permission override name against the reviewed browser permission set. */\nexport function permissionnamevalid(name: string): policyevaluation {\n if (!browserpermissions.includes(name)) return { allowed: false, reason: `The permission ${name} stays outside the reviewed browser permission set: ${browserpermissions.join(\", \")}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed session parameter grammar of the 1.1.49 memory family: snapshot plans with the scope, the section toggles of the reviewed grammar and the optional auto interval whose period, maximum snapshot count and expiry stay user choices with no code ceiling, restore plans with their tab, form and capture policies behind the explicit restore review, session filings with unique reviewed names and folders, diffs of two saved records, searches with the term grammar and the field set, exports behind the explicit export review and imports of the known file format behind the full record review. */\nfunction validatesessiongrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"persiststate\") {\n if (options.resume !== undefined && typeof options.resume !== \"boolean\") return { allowed: false, reason: \"The reviewed resume flag must be a boolean.\" };\n return { allowed: true };\n }\n if (kind === \"capturesession\") {\n const plan = snapshotplanof(options.snapshot);\n if (!plan) return { allowed: false, reason: \"The session capture needs a reviewed snapshot plan with its scope, a non-empty section list of the reviewed grammar (tabs, scroll, forms, storage, cookies) and the capture link flag.\" };\n if (plan.auto !== undefined) {\n const interval = autointervalof((options.snapshot as Record<string, unknown>).auto);\n if (interval === undefined) return { allowed: false, reason: \"The reviewed auto snapshot interval needs a positive period, a positive maximum snapshot count and a zero or positive expiry window with no code ceiling.\" };\n }\n return { allowed: true };\n }\n if (kind === \"restoresession\") {\n if (typeof options.sessionid !== \"string\" || !options.sessionid.trim()) return { allowed: false, reason: \"The session restore needs the reviewed session id of the saved record.\" };\n if (restoreplanof(options.restore) === undefined) return { allowed: false, reason: \"The session restore needs a reviewed restore plan with its tab, form and capture policies.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every session restore needs the explicit restore review with its tabs, form state and captures listed before it reopens anything.\" };\n return { allowed: true };\n }\n if (kind === \"namedsessions\") {\n if (typeof options.sessionid !== \"string\" || !options.sessionid.trim()) return { allowed: false, reason: \"The session filing needs the reviewed session id of the saved record.\" };\n if (typeof options.name !== \"string\" || !options.name.trim()) return { allowed: false, reason: \"The session filing needs a reviewed non-empty session name.\" };\n if (options.folder !== undefined && (typeof options.folder !== \"string\" || !options.folder.trim())) return { allowed: false, reason: \"The reviewed folder name must be a non-empty string.\" };\n if (options.tags !== undefined && (!Array.isArray(options.tags) || !options.tags.every(tag => typeof tag === \"string\" && tag.trim()))) return { allowed: false, reason: \"The reviewed tag list must be a list of non-empty strings.\" };\n return { allowed: true };\n }\n if (kind === \"diffsessions\") {\n if (typeof options.left !== \"string\" || !options.left.trim() || typeof options.right !== \"string\" || !options.right.trim()) return { allowed: false, reason: \"The session diff needs the reviewed ids of both saved sessions.\" };\n return { allowed: true };\n }\n if (kind === \"searchsessions\") {\n if (searchqueryof(options.query) === undefined) return { allowed: false, reason: \"The session search needs a reviewed query with a non-empty term list, fields of the reviewed grammar (urls, titles, names, text) and an optional time window.\" };\n return { allowed: true };\n }\n if (kind === \"exportsessions\") {\n if (options.reviewed !== true) return { allowed: false, reason: \"Session exports need the explicit export review before any session file leaves the device.\" };\n if (options.ids !== undefined && (!Array.isArray(options.ids) || options.ids.length === 0 || !options.ids.every(id => typeof id === \"string\" && id.trim()))) return { allowed: false, reason: \"The reviewed export id list must be a non-empty list of saved session ids.\" };\n return { allowed: true };\n }\n if (kind === \"importsessions\") {\n if (options.reviewed !== true) return { allowed: false, reason: \"Session imports need the explicit full record review before any record joins the library.\" };\n if (importsessionfile(options.file) === undefined) return { allowed: false, reason: \"The session import needs a reviewed file of the known format version with an intact checksum.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Requires the explicit restore review flag and the reviewed restore plan before any session restore reopens a tab; the review lists every tab, form state and capture first. */\nexport function restorereviewgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n if (restoreplanof(options.restore) === undefined) return { allowed: false, reason: \"Every session restore needs a reviewed restore plan with its tab, form and capture policies.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The session restore needs the explicit restore review of its tabs, form state and captures before it reopens anything.\" };\n return { allowed: true };\n}\n\n/** The session consent gate of every session memory step: a live session, an approved plan and the restore review of every restore; crash restore prompts stay inside the same consent model. */\nexport function sessionrestoregate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"run the session memory step\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Session memory steps need an approved plan before they run.\" };\n if (input.step.kind === \"restoresession\") return restorereviewgranted(input.step);\n return { allowed: true };\n}\n\n/** Returns the origins a restore reopens outside the grants so the restore skips and reports them; captures and cookies restore only with their origin grants. */\nexport function restoreoriginsgranted(urls: string[], grants: string[]): { allowed: boolean; skippedorigins: string[] } {\n const covered = new Set(grants);\n const skippedorigins: string[] = [];\n for (const url of urls) {\n let origin = \"\";\n try { origin = new URL(url).origin; } catch { origin = \"\"; }\n if (!origin || !covered.has(origin)) skippedorigins.push(origin || url);\n }\n return { allowed: skippedorigins.length === 0, skippedorigins: [...new Set(skippedorigins)] };\n}\n\n/** Requires session names to stay unique inside the library so a filing never shadows another saved session. */\nexport function sessionnameunique(name: string, records: Array<{ id: string; name: string }>, recordid?: string): policyevaluation {\n if (records.some(record => record.name === name && record.id !== recordid)) return { allowed: false, reason: `The session name ${name} already exists in the library; review a unique name.` };\n return { allowed: true };\n}\n\n/** Requires folder names to stay unique inside the folder tree so one folder never shadows another. */\nexport function sessionfolderunique(name: string, folders: Array<{ name: string }>): policyevaluation {\n if (folders.some(folder => folder.name === name)) return { allowed: false, reason: `The folder name ${name} already exists in the library; review a unique folder name.` };\n return { allowed: true };\n}\n\n/** Exposes the user configured retention window for saved session sections; an absent window keeps every section and no code ceiling applies. */\nexport function snapshotretentionwindow(settings: runsettings | undefined): number | undefined {\n return settings?.sessionretention;\n}\n\n/** Validates the reviewed workflow parameter grammar of the 1.1.50 and 1.1.51 families: composition with the expanded block list so no step stays hidden, shareable step templates, workflow runs behind the explicit run review, dry runs of the known workflow, jittered delays and element waits of user configured bounds with no code ceiling, expressions whose operators match the operand kinds and result kinds, regex rules of bounded backtracking shapes applied to reviewed text, and the control flow payloads of conditionals, branching, loops with user configured safety bounds, foreach selectors, parallel branches with join policies and try catch with retry and timeout policies whose child kinds all stay inside the reviewed vocabulary. */\nfunction validateworkflowgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"composeworkflow\") {\n const payload = options.workflow;\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return { allowed: false, reason: \"The workflow composition needs the reviewed workflow payload with its name, version, origins, steps and blocks.\" };\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.name !== \"string\" || !candidate.name.trim()) return { allowed: false, reason: \"The workflow composition needs a reviewed non-empty name.\" };\n if (typeof candidate.version !== \"number\" || !Number.isInteger(candidate.version) || candidate.version < 1) return { allowed: false, reason: \"The workflow version must be a positive integer.\" };\n if (!Array.isArray(candidate.origins) || candidate.origins.length === 0 || !candidate.origins.every(origin => typeof origin === \"string\" && origin.startsWith(\"https://\"))) return { allowed: false, reason: \"The workflow needs at least one granted HTTPS origin so every step stays inside the grants.\" };\n if (!Array.isArray(candidate.steps) || candidate.steps.length === 0 || !candidate.steps.every(entry => workflowstepof(entry) !== undefined || (entry && typeof entry === \"object\" && typeof (entry as Record<string, unknown>).block === \"string\"))) return { allowed: false, reason: \"The workflow needs a non-empty reviewed step list of the workflow step grammar or block invocations.\" };\n const blocks = Array.isArray(candidate.blocks) ? candidate.blocks.flatMap(block => { const parsed = workflowblockof(block); return parsed !== undefined ? [parsed] : []; }) : [];\n if (Array.isArray(candidate.blocks) && blocks.length !== (candidate.blocks as unknown[]).length) return { allowed: false, reason: \"The reviewed block list must carry unique lowercase names, labels and valid child steps.\" };\n try {\n const record = composeworkflow({ name: candidate.name, version: candidate.version, origins: candidate.origins as string[], steps: (candidate.steps as Array<Record<string, unknown>>).map(entry => \"block\" in entry ? { block: entry.block as string, label: typeof entry.label === \"string\" ? entry.label : entry.block as string } : workflowstepof(entry) as workflowstep), blocks, now: 0, kindallowed: candidatekind => { try { actionrisk(candidatekind as actionkind); return true; } catch { return false; } }, riskof: candidatekind => actionrisk(candidatekind as actionkind) });\n const inputs = Array.isArray(candidate.inputs) ? candidate.inputs.flatMap(name => typeof name === \"string\" ? [name] : []) : undefined;\n const checked = validateworkflow(record, { kindallowed: workflowkind => { try { actionrisk(workflowkind as actionkind); return true; } catch { return false; } }, ...(inputs !== undefined ? { inputs } : {}) });\n if (!checked.allowed) return checked;\n } catch (error) {\n return { allowed: false, reason: error instanceof Error ? error.message : \"The workflow payload failed its composition validation.\" };\n }\n return { allowed: true };\n }\n if (kind === \"savetemplate\") {\n const payload = options.template && typeof options.template === \"object\" && !Array.isArray(options.template) ? options.template as Record<string, unknown> : {};\n const template = steptemplateof({ id: \"templatereview\", origin: \"https://example.com\", sharedat: 0, ...payload });\n if (!template) return { allowed: false, reason: \"The step template needs a reviewed name and a valid workflow step it shares across workflows.\" };\n return { allowed: true };\n }\n if (kind === \"runworkflow\") {\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"The workflow run needs the reviewed id of the composed workflow.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes.\" };\n if (options.variables !== undefined && (!options.variables || typeof options.variables !== \"object\" || Array.isArray(options.variables) || !Object.values(options.variables).every(value => typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\"))) return { allowed: false, reason: \"The reviewed run variables must be an object of string, number or boolean values.\" };\n return { allowed: true };\n }\n if (kind === \"dryrun\") {\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"The dry run needs the reviewed id of the composed workflow.\" };\n return { allowed: true };\n }\n if (kind === \"delay\") {\n const delay = options.delay;\n if (!delay || typeof delay !== \"object\" || Array.isArray(delay)) return { allowed: false, reason: \"The delay needs a reviewed base and jitter window in options.\" };\n const reviewed = delay as Record<string, unknown>;\n if (typeof reviewed.base !== \"number\" || !Number.isFinite(reviewed.base) || reviewed.base < 0) return { allowed: false, reason: \"The reviewed delay base must be zero or a positive number of milliseconds.\" };\n if (typeof reviewed.jitter !== \"number\" || !Number.isFinite(reviewed.jitter) || reviewed.jitter < 0) return { allowed: false, reason: \"The reviewed delay jitter window must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"waitelement\") {\n const wait = options.wait;\n if (!wait || typeof wait !== \"object\" || Array.isArray(wait)) return { allowed: false, reason: \"The element wait needs a reviewed selector, timeout and poll interval in options.\" };\n const reviewed = wait as Record<string, unknown>;\n if (typeof reviewed.selector !== \"string\" || !reviewed.selector.trim()) return { allowed: false, reason: \"The element wait needs a reviewed non-empty selector.\" };\n if (typeof reviewed.timeout !== \"number\" || !Number.isFinite(reviewed.timeout) || reviewed.timeout < 0) return { allowed: false, reason: \"The reviewed element wait timeout must be zero or a positive number of milliseconds with no code ceiling.\" };\n if (typeof reviewed.poll !== \"number\" || !Number.isFinite(reviewed.poll) || reviewed.poll < 0) return { allowed: false, reason: \"The reviewed element wait poll interval must be zero or a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"compute\") {\n const expression = expressionof(options.expression);\n if (!expression) return { allowed: false, reason: `The expression step needs a reviewed expression with operands, an operator of the reviewed set (${expressionoperators.join(\", \")}) and a result variable of a reviewed kind.` };\n const operatorcheck = validatexpressionoperators(expression);\n if (!operatorcheck.allowed) return operatorcheck;\n return { allowed: true };\n }\n if (kind === \"extractvars\") {\n const rule = regexruleof(options.rule);\n if (!rule) return { allowed: false, reason: \"The variable extraction needs a reviewed regex rule with its pattern, flags and named capture groups.\" };\n const shapecheck = validateregexrule(rule.pattern);\n if (!shapecheck.allowed) return shapecheck;\n if (typeof options.text !== \"string\") return { allowed: false, reason: \"The variable extraction needs the reviewed text the regex rule applies to.\" };\n return { allowed: true };\n }\n if (kind === \"condition\") {\n const condition = conditionof(options.condition);\n if (!condition) return { allowed: false, reason: \"The condition step needs a reviewed boolean expression in its options.\" };\n const operatorcheck = validatexpressionoperators(condition.expression);\n if (!operatorcheck.allowed) return operatorcheck;\n return { allowed: true };\n }\n if (kind === \"branch\") {\n const branch = branchof(options.branch);\n if (!branch) return { allowed: false, reason: \"The branch step needs reviewed unique paths with boolean match expressions and an else path in its options so every branch terminates.\" };\n for (const path of [...branch.paths, branch.else]) {\n if (path.when === undefined) continue;\n const operatorcheck = validatexpressionoperators(path.when);\n if (!operatorcheck.allowed) return operatorcheck;\n }\n return controlchildkinds(step);\n }\n if (kind === \"loop\") {\n const loop = loopof(options.loop);\n if (!loop) return { allowed: false, reason: \"The loop step needs a reviewed list variable, distinct item and index variables, an optional positive safety bound and a non-empty body in its options; an absent bound keeps the documented default.\" };\n return controlchildkinds(step);\n }\n if (kind === \"repeatuntil\") {\n const repeat = repeatuntilof(options.repeatuntil);\n if (!repeat) return { allowed: false, reason: \"The repeat until step needs a reviewed convergence expression, an optional positive safety bound and a non-empty body in its options.\" };\n const operatorcheck = validatexpressionoperators(repeat.until);\n if (!operatorcheck.allowed) return operatorcheck;\n return controlchildkinds(step);\n }\n if (kind === \"whileloop\") {\n const condition = whileof(options.while);\n if (!condition) return { allowed: false, reason: \"The while step needs a reviewed condition, a mandatory positive safety bound and a non-empty body in its options; a while loop without a safety bound is refused.\" };\n const operatorcheck = validatexpressionoperators(condition.while);\n if (!operatorcheck.allowed) return operatorcheck;\n return controlchildkinds(step);\n }\n if (kind === \"foreach\") {\n const foreach = foreachof(options.foreach);\n if (!foreach) return { allowed: false, reason: \"The foreach step needs a reviewed non-empty selector, distinct item and index variables and a non-empty body in its options.\" };\n return controlchildkinds(step);\n }\n if (kind === \"parallel\") {\n const parallel = parallelof(options.parallel);\n if (!parallel) return { allowed: false, reason: \"The parallel step needs uniquely identified branches with bodies and a join policy of the first, last or fail strategy with cancel or continue on branch failure in its options.\" };\n return controlchildkinds(step);\n }\n if (kind === \"trycatch\") {\n const fragile = tryof(options.try);\n if (!fragile) return { allowed: false, reason: \"The try step needs a fragile body, a catch handler and optional retry and timeout policies in its options: attempts stay user configured with no code ceiling, backoff is fixed or exponential and budgets are positive.\" };\n return controlchildkinds(step);\n }\n return { allowed: true };\n}\n\n/** Checks every child step of a control payload against the reviewed action vocabulary so no control construct hides an unreviewed kind behind its body. */\nfunction controlchildkinds(step: toolstep): policyevaluation {\n const children = controlsteps({ id: step.id, kind: step.kind, label: step.summary, ...(step.options !== undefined ? { options: step.options } : {}) });\n for (const child of children) {\n try { actionrisk(child.kind); } catch { return { allowed: false, reason: `The ${child.kind} step inside the control payload of the ${step.kind} step is not a reviewed action kind.` }; }\n }\n return { allowed: true };\n}\n\n/** Rejects unbounded backtracking shapes of reviewed regex patterns: a quantified group whose body itself ends with an unbounded quantifier can explode on adversarial text, so the shape is refused while bounded repetitions stay user choices. */\nexport function validateregexrule(pattern: string): policyevaluation {\n try { new RegExp(pattern); } catch { return { allowed: false, reason: \"The reviewed regex pattern does not compile.\" }; }\n const nestedquantifier = /\\((?:[^()\\\\]|\\\\.)*[+*}]\\)[+*{]/.test(pattern) || /\\(\\)[+*{]/.test(pattern);\n if (nestedquantifier) return { allowed: false, reason: \"The reviewed regex pattern nests an unbounded quantifier inside a quantified group and is refused because adversarial text could explode the backtracking.\" };\n const unboundedrepeat = /\\{\\d+,\\}/.test(pattern);\n if (unboundedrepeat && /\\([^)]*\\{\\d+,\\}[^)]*\\)[+*{]/.test(pattern)) return { allowed: false, reason: \"The reviewed regex pattern repeats an unbounded group and is refused because adversarial text could explode the backtracking.\" };\n return { allowed: true };\n}\n\n/** Validates the reviewed expression operators against the operand kinds and the result kind: arithmetic needs numbers and returns numbers, logic needs booleans and returns booleans, comparison needs numbers and returns booleans, text operators return strings or booleans and length returns a number. */\nfunction validatexpressionoperators(expression: import(\"./types.js\").expressiontype): policyevaluation {\n const numeric = new Set([\"add\", \"subtract\", \"multiply\", \"divide\", \"modulo\"]);\n const logic = new Set([\"and\", \"or\", \"not\"]);\n const comparison = new Set([\"less\", \"greater\", \"lessequal\", \"greaterequal\"]);\n const text = new Set([\"concat\", \"contains\"]);\n const operator = expression.operator;\n if (numeric.has(operator)) {\n for (const operand of [expression.left, expression.right]) {\n if (operand === undefined) continue;\n if (operand.literal !== undefined && typeof operand.literal === \"boolean\") return { allowed: false, reason: `The ${operator} operator needs numeric operands; boolean literals are refused.` };\n }\n if (expression.resultkind !== \"number\" && expression.resultkind !== \"string\") return { allowed: false, reason: `The ${operator} operator needs a number result kind.` };\n }\n if (logic.has(operator)) {\n for (const operand of [expression.left, expression.right]) {\n if (operand === undefined) continue;\n if (operand.literal !== undefined && typeof operand.literal !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs boolean operands; non boolean literals are refused.` };\n }\n if (expression.resultkind !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };\n if (operator === \"not\" && expression.right !== undefined) return { allowed: false, reason: \"The not operator takes one operand only.\" };\n }\n if (comparison.has(operator) && expression.resultkind !== \"boolean\") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };\n if (text.has(operator) && expression.resultkind !== \"boolean\" && expression.resultkind !== \"string\") return { allowed: false, reason: `The ${operator} operator needs a string or boolean result kind.` };\n if (operator === \"contains\" && expression.resultkind !== \"boolean\") return { allowed: false, reason: \"The contains operator needs a boolean result kind.\" };\n if (operator === \"length\") {\n if (expression.right !== undefined) return { allowed: false, reason: \"The length operator takes one operand only.\" };\n if (expression.resultkind !== \"number\") return { allowed: false, reason: \"The length operator needs a number result kind.\" };\n }\n if ((operator === \"equal\" || operator === \"notequal\") && !new Set([\"boolean\", \"string\", \"number\"]).has(expression.resultkind)) return { allowed: false, reason: \"The equality operator needs a primitive result kind.\" };\n return { allowed: true };\n}\n\n/** The workflow consent gate: a live session, an approved plan and the explicit run review of every real run; dry runs stay read only inside the same session and plan gates. */\nexport function workflowgate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"run the workflow step\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Workflow steps need the approved plan review before they run.\" };\n if (input.step.kind === \"runworkflow\") {\n let runoptions: Record<string, unknown> = {};\n try { runoptions = parseoptions(input.step); } catch { runoptions = {}; }\n if (runoptions.reviewed !== true) return { allowed: false, reason: \"Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes.\" };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed trigger parameter grammar of the 1.1.52 family: every kind arms exactly one rule behind the explicit arm review, the workflow reference must name a composed workflow, the match payloads follow their family grammar \u2014 visit origins and url list entries must be HTTPS urls, url patterns must parse as HTTPS globs, cron expressions must parse as five field schedules with named weekdays and months and a resolvable timezone, interval periods stay positive with zero or positive jitter, webhook secrets must clear the documented entropy floor with a non-empty payload schema, event names must come from the observed event catalog and context menu titles stay non-empty \u2014 while cooldown windows stay user configured positive values with the documented default of the webhook and event families winning only when the review configures none. */\nfunction validatetriggergrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const family = triggerfamilyof(step.kind);\n if (family === undefined) return { allowed: false, reason: \"The trigger step is not a reviewed trigger kind.\" };\n if (typeof options.workflowid !== \"string\" || !options.workflowid.trim()) return { allowed: false, reason: \"Every trigger rule needs the reviewed id of the composed workflow it launches.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Every trigger rule needs the explicit arm review with its match fields and bound workflow shown before it arms.\" };\n if (options.label !== undefined && (typeof options.label !== \"string\" || !options.label.trim())) return { allowed: false, reason: \"The reviewed trigger label must be a non-empty string.\" };\n if (options.cooldown !== undefined && (typeof options.cooldown !== \"number\" || !Number.isFinite(options.cooldown) || options.cooldown <= 0)) return { allowed: false, reason: \"The reviewed cooldown window must be a positive number of milliseconds with no code ceiling; the webhook and event families keep the documented default when the review configures none.\" };\n const payload = options.rule;\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return { allowed: false, reason: `The ${step.kind} step needs its reviewed rule payload in options.` };\n if (triggerpayloadof(family, payload) === undefined) {\n if (family === \"visit\") return { allowed: false, reason: \"The visit rule needs a non-empty reviewed list of HTTPS origins it fires on.\" };\n if (family === \"url\") return { allowed: false, reason: \"The url rule needs a reviewed HTTPS glob url pattern; `*` spans one path segment and `**` spans across segments.\" };\n if (family === \"menu\") return { allowed: false, reason: \"The menu rule needs a reviewed non-empty context menu entry title.\" };\n if (family === \"key\") return { allowed: false, reason: \"The keyboard shortcut rule needs a reviewed lowercase command name and an optional suggested key binding.\" };\n if (family === \"cron\") return { allowed: false, reason: \"The cron rule needs a reviewed five field cron expression of minutes, hours, days, months and weekdays with named weekdays and months and an optional resolvable timezone; unparseable schedules are refused.\" };\n if (family === \"interval\") return { allowed: false, reason: \"The interval rule needs a reviewed positive period in milliseconds with an optional zero or positive jitter window.\" };\n if (family === \"urllist\") return { allowed: false, reason: \"The url list rule needs a reviewed non-empty list of HTTPS urls its workflow runs across.\" };\n if (family === \"webhook\") return { allowed: false, reason: `The webhook rule needs a reviewed shared secret of at least twenty four characters mixing letters and digits and a non-empty payload schema of named string, number or boolean fields.` };\n if (family === \"event\") return { allowed: false, reason: `The page event rule needs a reviewed non-empty list of event names of the observed event catalog: ${triggereventcatalog.join(\", \")}.` };\n return { allowed: false, reason: \"The trigger rule payload does not follow its family grammar.\" };\n }\n if (family === \"cron\") {\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.cron === \"string\" && cronparse(candidate.cron) === undefined) return { allowed: false, reason: \"The cron expression does not parse as a five field schedule and is refused.\" };\n }\n if (family === \"webhook\") {\n const candidate = payload as Record<string, unknown>;\n if (typeof candidate.secret === \"string\" && !webhooksecretok(candidate.secret)) return { allowed: false, reason: \"The webhook shared secret must hold at least twenty four characters mixing letters and digits; the entropy floor is a floor, never a cap.\" };\n }\n const armed = armrule({ family, workflowid: options.workflowid, ...(typeof options.label === \"string\" && options.label.trim() ? { label: options.label } : {}), payload, ...(typeof options.cooldown === \"number\" ? { cooldown: options.cooldown } : {}), now: 0 });\n if (armed === undefined) return { allowed: false, reason: \"The trigger rule payload does not arm as a reviewed rule.\" };\n return { allowed: true };\n}\n\n/** The trigger consent gate: a live session, an approved plan and the explicit arm review of every rule; automatic launchers never arm outside the consent gates. */\nexport function triggergate(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: \"arm the trigger rule\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Trigger rules need the approved plan review before they arm.\" };\n let triggeroptions: Record<string, unknown> = {};\n try { triggeroptions = parseoptions(input.step); } catch { triggeroptions = {}; }\n if (triggeroptions.reviewed !== true) return { allowed: false, reason: \"Every trigger rule needs the explicit arm review with its match fields and bound workflow shown before it arms.\" };\n return { allowed: true };\n}\n\n/** Returns the match origins of one reviewed trigger rule so callers can keep every rule inside the workflow grant list; triggers on origins outside the grants are refused. */\nexport function triggerorigins(step: toolstep): string[] {\n let triggeroptions: Record<string, unknown> = {};\n try { triggeroptions = parseoptions(step); } catch { return []; }\n const family = triggerfamilyof(step.kind);\n if (family === undefined) return [];\n const armed = armrule({ family, workflowid: typeof triggeroptions.workflowid === \"string\" ? triggeroptions.workflowid : \"\", payload: triggeroptions.rule, ...(typeof triggeroptions.cooldown === \"number\" ? { cooldown: triggeroptions.cooldown } : {}), now: 0 });\n if (armed === undefined) return [];\n const origins: string[] = [];\n for (const origin of armed.origins ?? []) origins.push(origin);\n if (armed.pattern !== undefined) { try { origins.push(new URL(armed.pattern).origin); } catch { /* the pattern grammar already refused unparseable patterns */ } }\n for (const url of armed.urls ?? []) { try { origins.push(new URL(url).origin); } catch { /* the url list grammar already refused unparseable urls */ } }\n return [...new Set(origins)];\n}\n\n/** Returns the read only projection of one workflow step for dry runs: read class steps report their would be outcome while interaction and mutation steps carry no projection and the dry run refuses them; a control step projects only when every child step of its payload grades read. */\nexport function dryrunprojection(step: workflowstep): string | undefined {\n if (iscontrolflowkind(step.kind)) {\n for (const child of controlsteps(step)) {\n const childrisk = resolvedrisk({ id: child.id, kind: child.kind, summary: child.label, risk: \"read\", ...(child.target !== undefined ? { target: child.target } : {}), ...(child.value !== undefined ? { value: child.value } : {}), ...(child.options !== undefined ? { options: child.options } : {}) });\n if (childrisk !== \"read\") return undefined;\n }\n if (step.kind === \"condition\") return \"The condition step would evaluate its reviewed expression over the extracted values with no page side effect.\";\n if (step.kind === \"branch\") return \"The branch step would choose one reviewed path by page state and only the chosen path would run.\";\n if (step.kind === \"loop\") return \"The loop step would iterate its reviewed list binding the item and index variables per iteration inside the safety bound.\";\n if (step.kind === \"repeatuntil\") return \"The repeat until step would rerun its body until the convergence expression holds inside the safety bound.\";\n if (step.kind === \"whileloop\") return \"The while step would loop while its condition holds inside the reviewed safety bound.\";\n if (step.kind === \"foreach\") return \"The foreach step would iterate the elements of its reviewed selector binding the item and index variables per iteration.\";\n if (step.kind === \"parallel\") return \"The parallel step would run its branches concurrently and join their outcomes under the reviewed strategy.\";\n return \"The try step would run its fragile body and only the catch handler on failure.\";\n }\n const risk = resolvedrisk({ id: step.id, kind: step.kind, summary: step.label, risk: \"read\", ...(step.target !== undefined ? { target: step.target } : {}), ...(step.value !== undefined ? { value: step.value } : {}), ...(step.options !== undefined ? { options: step.options } : {}) });\n if (risk !== \"read\") return undefined;\n if (step.kind === \"delay\") return `The delay step would sleep its reviewed base inside the jitter window.`;\n if (step.kind === \"waitelement\") return `The element wait step would poll ${step.target ?? \"the reviewed selector\"} until appearance or the reviewed timeout.`;\n if (step.kind === \"compute\") return `The compute step would evaluate its reviewed expression into the result variable.`;\n if (step.kind === \"extractvars\") return `The variable extraction step would apply its reviewed regex rule and store the named captures.`;\n return `The ${step.kind} step would run read only and mutate nothing.`;\n}\n\n/** Validates one reviewed permission state of an override. */\nexport function permissionstatevalid(state: string): policyevaluation {\n if (!permissionstates.includes(state as permissionstate)) return { allowed: false, reason: `The reviewed permission state must be one of ${permissionstates.join(\", \")}.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed devtools parameter grammar of the 1.1.46 family: enabled domains bounded by the reviewed domain grammar, the required teardown plan of every attach, raw commands of the Domain.method form, domain event rules with match filters inside the reviewed watch window, breakpoints with conditions of the reviewed expression grammar, step modes, reviewed watch expressions, and script overrides with the explicit reviewed flag and a url pattern that names its origin. */\nfunction validatecdpgrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"attachcdp\") {\n if (!Array.isArray(options.domains) || options.domains.length === 0 || !options.domains.every((domain): domain is string => typeof domain === \"string\" && cdpdomains.includes(domain))) return { allowed: false, reason: `The attach needs a non-empty enabled domain list of the reviewed domain grammar: ${cdpdomains.join(\", \")}.` };\n if (teardownplanof(options.teardown) === undefined) return { allowed: false, reason: \"Every attach needs a reviewed teardown plan with its revert steps and resume policy before approval.\" };\n if (options.allowlist !== undefined) {\n const allowlist = cdpallowlistof(options.allowlist);\n if (!allowlist || !allowlist.domains.every(domain => (options.domains as string[]).includes(domain))) return { allowed: false, reason: \"The reviewed method allowlist must stay inside the enabled domains of the attach.\" };\n }\n const budgetcheck = debugwaitbudgetallowed(typeof options.wait === \"number\" ? options.wait : undefined, undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"detachcdp\") return { allowed: true };\n if (kind === \"cdpcmd\") {\n const command = options.command && typeof options.command === \"object\" && !Array.isArray(options.command) ? options.command as Record<string, unknown> : undefined;\n if (!command || typeof command.method !== \"string\" || methoddomain(command.method) === undefined) return { allowed: false, reason: \"The raw command needs a reviewed method of the Domain.method form.\" };\n if (command.params !== undefined && (typeof command.params !== \"object\" || Array.isArray(command.params))) return { allowed: false, reason: \"The raw command params must be a JSON object.\" };\n if (command.resultpath !== undefined && typeof command.resultpath !== \"string\") return { allowed: false, reason: \"The reviewed result path must be a dotted path string.\" };\n return { allowed: true };\n }\n if (kind === \"watchcdp\") {\n if (!Array.isArray(options.events) || options.events.length === 0 || !options.events.every(rule => cdpeventruleof(rule) !== undefined)) return { allowed: false, reason: \"The event watch needs a non-empty reviewed list of domain event rules of the reviewed domain grammar.\" };\n let watchwindow: number | undefined;\n if (options.watch !== undefined) {\n const watch = options.watch;\n if (!watch || typeof watch !== \"object\" || Array.isArray(watch)) return { allowed: false, reason: \"The reviewed event watch window must be an object.\" };\n const reviewed = watch as Record<string, unknown>;\n if (reviewed.window !== undefined) {\n if (typeof reviewed.window !== \"number\" || !Number.isFinite(reviewed.window) || reviewed.window < 0) return { allowed: false, reason: \"The reviewed event watch window must be zero or a positive number of milliseconds.\" };\n watchwindow = reviewed.window;\n }\n }\n if (watchwindow === undefined) return { allowed: false, reason: \"The event watch needs a reviewed lifetime window before any domain event is observed.\" };\n const budgetcheck = debugwaitbudgetallowed(watchwindow, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"setbreakpoint\") {\n const breakpoint = breakpointinputof(options.breakpoint);\n if (!breakpoint) return { allowed: false, reason: \"The breakpoint needs a reviewed script url and a zero based line.\" };\n if (!ishttpsurl(breakpoint.url)) return { allowed: false, reason: \"The breakpoint script url must be a reviewed HTTPS url.\" };\n if (breakpoint.condition !== undefined) {\n const conditioncheck = validatebreakpointcondition(breakpoint.condition);\n if (!conditioncheck.allowed) return conditioncheck;\n }\n return { allowed: true };\n }\n if (kind === \"stepcode\") {\n if (stepmodeof(options.mode) === undefined) return { allowed: false, reason: \"The step code mode must be one of stepover, stepinto, stepout or resume.\" };\n return { allowed: true };\n }\n if (kind === \"watchexpr\") {\n if (watchexpressionof(options.expression) === undefined) return { allowed: false, reason: \"The watch expression needs the reviewed expression text.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"Watch expressions must be reviewed before evaluation; set the explicit reviewed flag on the step.\" };\n return { allowed: true };\n }\n if (kind === \"overridescript\") {\n const override = overrideinputof(options.override);\n if (!override) return { allowed: false, reason: \"The script override needs a reviewed url pattern and its full fixture source.\" };\n if (patternorigin(override.urlpattern) === undefined) return { allowed: false, reason: \"Script overrides without a named https origin pattern are refused.\" };\n if (options.reviewed !== true) return { allowed: false, reason: \"The full fixture source must be reviewed before the script override runs; set the explicit reviewed flag on the step.\" };\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Validates the reviewed profiling parameter grammar of the 1.1.47 family: flow specs of the reviewed metric set inside a reviewed watch window, heap snapshots with the user chosen interval only, growth tracking with the reviewed slope, cpu profiles bounded by the reviewed wait budget, layout shift watches with the user chosen window only, trace records bounded by the reviewed category list and byte ceiling, trace annotations that carry step ids, offline replays of stored traces and source map capture scripts of explicit https urls. */\nfunction validateprofilegrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"measureflow\") {\n if (flowspecof(options.flow) === undefined) return { allowed: false, reason: `The flow measurement needs a reviewed flow spec with its mark prefix, step window and metric list of the reviewed metric set: navigation, paint, lcp, fid, interaction, blocking.` };\n const watch = options.watch && typeof options.watch === \"object\" && !Array.isArray(options.watch) ? options.watch as Record<string, unknown> : {};\n if (typeof watch.window !== \"number\" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: \"The flow measurement needs a reviewed watch window of zero or more milliseconds.\" };\n const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"heapshot\") {\n const heap = options.heap && typeof options.heap === \"object\" && !Array.isArray(options.heap) ? options.heap as Record<string, unknown> : {};\n if (heap.interval !== undefined && (typeof heap.interval !== \"number\" || !Number.isFinite(heap.interval) || heap.interval < 0)) return { allowed: false, reason: \"The reviewed heap snapshot interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"trackmemory\") {\n const growth = options.growth && typeof options.growth === \"object\" && !Array.isArray(options.growth) ? options.growth as Record<string, unknown> : undefined;\n if (!growth || typeof growth.slope !== \"number\" || !Number.isFinite(growth.slope) || growth.slope < 0) return { allowed: false, reason: \"Memory growth tracking needs the reviewed slope in bytes per millisecond before any sample is flagged.\" };\n if (growth.interval !== undefined && (typeof growth.interval !== \"number\" || !Number.isFinite(growth.interval) || growth.interval < 0)) return { allowed: false, reason: \"The reviewed sampling interval must be zero or a positive number of milliseconds and stays a user choice with no code ceiling.\" };\n return { allowed: true };\n }\n if (kind === \"profilecpu\") {\n const profile = options.profile && typeof options.profile === \"object\" && !Array.isArray(options.profile) ? options.profile as Record<string, unknown> : undefined;\n if (!profile || typeof profile.duration !== \"number\" || !Number.isFinite(profile.duration) || profile.duration < 0) return { allowed: false, reason: \"The cpu profile needs a reviewed duration of zero or more milliseconds.\" };\n const budgetcheck = debugwaitbudgetallowed(profile.duration, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"watchshifts\") {\n const watch = options.watch && typeof options.watch === \"object\" && !Array.isArray(options.watch) ? options.watch as Record<string, unknown> : {};\n if (typeof watch.window !== \"number\" || !Number.isFinite(watch.window) || watch.window < 0) return { allowed: false, reason: \"The layout shift watch needs a reviewed observation window of zero or more milliseconds; the window stays a user choice with no code ceiling.\" };\n if (options.threshold !== undefined && (typeof options.threshold !== \"number\" || !Number.isFinite(options.threshold) || options.threshold < 0)) return { allowed: false, reason: \"The reviewed shift score threshold must be zero or a positive number.\" };\n const budgetcheck = debugwaitbudgetallowed(watch.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"traceload\") {\n const trace = options.trace && typeof options.trace === \"object\" && !Array.isArray(options.trace) ? options.trace as Record<string, unknown> : undefined;\n if (!trace || !Array.isArray(trace.categories) || trace.categories.length === 0 || !trace.categories.every((category): category is string => typeof category === \"string\" && tracecategories.includes(category))) return { allowed: false, reason: `The trace record needs a non-empty reviewed category list of the reviewed category grammar: ${tracecategories.join(\", \")}.` };\n if (typeof trace.window !== \"number\" || !Number.isFinite(trace.window) || trace.window < 0) return { allowed: false, reason: \"The trace record needs a reviewed window of zero or more milliseconds and stops at the reviewed window end.\" };\n if (trace.exporttarget !== undefined && trace.exporttarget !== \"memory\" && trace.exporttarget !== \"download\") return { allowed: false, reason: \"The trace export target must be memory or download.\" };\n const budgetcheck = debugwaitbudgetallowed(trace.window, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budgetcheck.allowed) return budgetcheck;\n return { allowed: true };\n }\n if (kind === \"annotatetrace\" || kind === \"replaytrace\") {\n const trace = options.trace && typeof options.trace === \"object\" && !Array.isArray(options.trace) ? options.trace as Record<string, unknown> : undefined;\n if (!trace || typeof trace.traceid !== \"string\" || !trace.traceid.trim()) return { allowed: false, reason: `The ${kind === \"annotatetrace\" ? \"trace annotation\" : \"trace replay\"} needs the stored trace id of a recorded trace.` };\n if (kind === \"replaytrace\") return { allowed: true };\n if (!Array.isArray(options.annotations) || options.annotations.length === 0 || !options.annotations.every(annotation => annotationof(annotation) !== undefined)) return { allowed: false, reason: \"Exported traces carry their step annotations: every annotation needs a step id, a label and an optional offset from the trace start.\" };\n return { allowed: true };\n }\n if (kind === \"capturesourcemaps\") {\n if (options.scripts !== undefined) {\n if (!Array.isArray(options.scripts) || options.scripts.length === 0 || !options.scripts.every((url): url is string => typeof url === \"string\" && ishttpsurl(url))) return { allowed: false, reason: \"The source map capture scripts must be a non-empty list of reviewed HTTPS urls.\" };\n }\n return { allowed: true };\n }\n return { allowed: true };\n}\n\n/** Resolves the reviewed cdp allowlist of one plan: the enabled domains and method gates of its attachcdp step, the reviewable contract every later cdp kind of the plan must stay inside. */\nexport function planallowlist(steps: toolstep[]): cdpallowlist | undefined {\n const attach = steps.find(step => step.kind === \"attachcdp\");\n if (!attach) return undefined;\n let options: Record<string, unknown> = {};\n try { options = parseoptions(attach); } catch { options = {}; }\n const domains = Array.isArray(options.domains) ? options.domains.filter((domain): domain is string => typeof domain === \"string\" && cdpdomains.includes(domain)) : [];\n if (domains.length === 0) return undefined;\n const gated = cdpallowlistof(options.allowlist);\n return { domains, ...(gated?.methods !== undefined ? { methods: gated.methods } : {}) };\n}\n\n/** Resolves the reviewed outbound url of a network control step at review time: the form url of postform, the upload url of postfiles and the token url of authflow. */\nexport function controltarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n for (const key of [\"form\", \"upload\"] as const) {\n const value = options[key];\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const url = (value as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n }\n if (step.kind === \"authflow\") {\n const flow = oauthflowof(options.oauth);\n if (flow) return flow.tokenurl;\n }\n return undefined;\n}\n\n/** Resolves the reviewed channel url of a socket step at review time: the socket url of opensocket, the event stream url of subscribesse and the poll url of longpoll. */\nexport function sockettarget(step: toolstep): string | undefined {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n for (const key of [\"socket\", \"subscription\", \"poll\"] as const) {\n const value = options[key];\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const url = (value as Record<string, unknown>).url;\n if (typeof url === \"string\" && url.trim()) return url.trim();\n }\n }\n return undefined;\n}\n\n/** Requires the active tab grant of the live session for every media kind: the session tab and origin must match and the origin grant must cover the active origin. */\nexport function mediagate(session: agentsession | undefined, tabid: number, origin: string, now: number): policyevaluation {\n if (!session || session.stoppedat) return { allowed: false, reason: \"No active browser session exists for the media capture.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and cannot capture media.\" };\n if (session.pausedat) return { allowed: false, reason: \"The browser session is paused and cannot capture media.\" };\n if (session.tabid !== tabid) return { allowed: false, reason: `The media capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };\n if (!origingranted(session, origin)) return { allowed: false, reason: `The media capture of ${origin} needs the session origin grants first.` };\n return { allowed: true };\n}\n\n/** Requires an approved recording consent prompt before any recording of user activity starts; every start consumes its own prompt. */\nexport function recordingconsentgranted(step: toolstep): policyevaluation {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const consentref = options.consentref;\n if (typeof consentref !== \"string\" || !consentref.trim()) return { allowed: false, reason: \"A recording of user activity requires a reviewed consent ref in options before it starts.\" };\n return { allowed: true };\n}\n\n/** Exposes the recording duration window as a user configured choice in milliseconds; an absent window leaves the duration to the reviewed step options with no code ceiling. */\nexport function recordingwindow(settings: runsettings | undefined): number | undefined {\n const window = settings?.recordingwindow;\n return typeof window === \"number\" && Number.isFinite(window) && window > 0 ? window : undefined;\n}\n\n/** Keeps the reviewed lapse plan inside the reviewed wait budget: the whole lapse duration must fit the wait window with no code ceiling on either side. */\nexport function lapsebudgetallowed(interval: number, duration: number, wait: number | undefined): policyevaluation {\n if (!(interval > 0)) return { allowed: false, reason: \"The reviewed lapse interval must be a positive number of milliseconds.\" };\n if (!(duration > 0)) return { allowed: false, reason: \"The reviewed lapse duration must be a positive number of milliseconds.\" };\n if (wait !== undefined && !(wait >= 0)) return { allowed: false, reason: \"The reviewed wait budget must be zero or a positive number of milliseconds.\" };\n if (wait !== undefined && duration > wait) return { allowed: false, reason: `The lapse duration of ${duration} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter duration.` };\n return { allowed: true };\n}\n\n/** Validates the reviewed media capture parameter grammar of the 1.1.41 family: pdf paper sizes, recording scopes and windows, image filters, lapse plans, conversion targets and thumbnail directives stay user choices with no code ceilings. */\nfunction validatemediagrammar(step: toolstep, options: Record<string, unknown>): policyevaluation {\n const kind = step.kind;\n if (kind === \"capturepdf\") {\n const pdf = options.pdf;\n if (pdf !== undefined) {\n if (!pdf || typeof pdf !== \"object\" || Array.isArray(pdf)) return { allowed: false, reason: \"The reviewed pdf options must be an object in options.pdf.\" };\n const pdfoptions = pdf as Record<string, unknown>;\n if (pdfoptions.paperwidth !== undefined && (typeof pdfoptions.paperwidth !== \"number\" || !Number.isFinite(pdfoptions.paperwidth) || pdfoptions.paperwidth <= 0)) return { allowed: false, reason: \"The reviewed pdf paper width must be a positive number of inches with no code cap.\" };\n if (pdfoptions.paperheight !== undefined && (typeof pdfoptions.paperheight !== \"number\" || !Number.isFinite(pdfoptions.paperheight) || pdfoptions.paperheight <= 0)) return { allowed: false, reason: \"The reviewed pdf paper height must be a positive number of inches with no code cap.\" };\n if (pdfoptions.margins !== undefined) {\n const margins = pdfoptions.margins;\n if (!margins || typeof margins !== \"object\" || Array.isArray(margins)) return { allowed: false, reason: \"The reviewed pdf margins must be an object with top, right, bottom and left inches.\" };\n for (const side of [\"top\", \"right\", \"bottom\", \"left\"]) {\n const value = (margins as Record<string, unknown>)[side];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) return { allowed: false, reason: `The reviewed pdf ${side} margin must be zero or a positive number of inches; negative margins are refused.` };\n }\n }\n if (pdfoptions.scale !== undefined && (typeof pdfoptions.scale !== \"number\" || !Number.isFinite(pdfoptions.scale) || pdfoptions.scale <= 0)) return { allowed: false, reason: \"The reviewed pdf scale must be a positive number with no code cap.\" };\n if (pdfoptions.landscape !== undefined && typeof pdfoptions.landscape !== \"boolean\") return { allowed: false, reason: \"The reviewed pdf landscape flag must be a boolean.\" };\n if (pdfoptions.paginate !== undefined && typeof pdfoptions.paginate !== \"boolean\") return { allowed: false, reason: \"The reviewed pdf paginate flag must be a boolean.\" };\n }\n if (options.breakpoints !== undefined && (!Array.isArray(options.breakpoints) || options.breakpoints.length === 0 || !options.breakpoints.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed pdf break points must be a non-empty list of selectors when present.\" };\n if (options.exporttarget !== undefined && options.exporttarget !== \"memory\" && options.exporttarget !== \"download\") return { allowed: false, reason: \"The reviewed pdf export target must be memory or download; pdf documents do not route to the clipboard.\" };\n if (options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed pdf artifact name must be a non-empty string.\" };\n }\n if (kind === \"recordscreen\" || kind === \"captureaudio\") {\n const recording = options.recording;\n if (recording !== undefined) {\n if (!recording || typeof recording !== \"object\" || Array.isArray(recording)) return { allowed: false, reason: \"The reviewed recording options must be an object in options.recording.\" };\n const recordoptions = recording as Record<string, unknown>;\n if (recordoptions.scope !== undefined && recordoptions.scope !== \"tab\" && recordoptions.scope !== \"run\") return { allowed: false, reason: \"The reviewed recording scope must be tab or run.\" };\n if (recordoptions.fps !== undefined && (typeof recordoptions.fps !== \"number\" || !Number.isFinite(recordoptions.fps) || recordoptions.fps <= 0)) return { allowed: false, reason: \"The reviewed recording fps must be a positive number with no code ceiling.\" };\n if (recordoptions.bitrate !== undefined && (typeof recordoptions.bitrate !== \"number\" || !Number.isFinite(recordoptions.bitrate) || recordoptions.bitrate <= 0)) return { allowed: false, reason: \"The reviewed recording bitrate must be a positive number with no code ceiling.\" };\n if (recordoptions.audio !== undefined && typeof recordoptions.audio !== \"boolean\") return { allowed: false, reason: \"The reviewed recording audio flag must be a boolean.\" };\n }\n if (options.duration !== undefined && (typeof options.duration !== \"number\" || !Number.isFinite(options.duration) || options.duration <= 0)) return { allowed: false, reason: \"The reviewed recording duration must be a positive number of milliseconds with no code ceiling.\" };\n const consent = recordingconsentgranted(step);\n if (!consent.allowed) return consent;\n }\n if (kind === \"captureframe\") {\n if (options.timestamp !== undefined && (typeof options.timestamp !== \"number\" || !Number.isFinite(options.timestamp) || options.timestamp < 0)) return { allowed: false, reason: \"The reviewed frame timestamp must be zero or a positive number of seconds.\" };\n if (options.poster !== undefined && typeof options.poster !== \"boolean\") return { allowed: false, reason: \"The reviewed poster flag must be a boolean.\" };\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"downloadimages\") {\n const filter = options.imagefilter;\n if (!filter || typeof filter !== \"object\" || Array.isArray(filter)) return { allowed: false, reason: \"A reviewed imagefilter is required in options before any image downloads.\" };\n const imagefilter = filter as Record<string, unknown>;\n if (imagefilter.selector !== undefined && !isnonempty(imagefilter.selector)) return { allowed: false, reason: \"The reviewed imagefilter selector must be a non-empty selector from the reviewed selector grammar.\" };\n if (imagefilter.minwidth !== undefined && (typeof imagefilter.minwidth !== \"number\" || !Number.isFinite(imagefilter.minwidth) || imagefilter.minwidth < 0)) return { allowed: false, reason: \"The reviewed imagefilter minimum width must be zero or a positive number of pixels.\" };\n if (imagefilter.minheight !== undefined && (typeof imagefilter.minheight !== \"number\" || !Number.isFinite(imagefilter.minheight) || imagefilter.minheight < 0)) return { allowed: false, reason: \"The reviewed imagefilter minimum height must be zero or a positive number of pixels.\" };\n if (imagefilter.formats !== undefined && (!Array.isArray(imagefilter.formats) || imagefilter.formats.length === 0 || !imagefilter.formats.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed imagefilter format list must be a non-empty list of mime or extension patterns when present.\" };\n if (options.naming !== undefined) {\n const namingcheck = validatecapturenaming(options.naming);\n if (!namingcheck.allowed) return namingcheck;\n }\n }\n if (kind === \"shotcanvas\") {\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"probestream\" && options.selector !== undefined && !isnonempty(options.selector)) return { allowed: false, reason: \"The reviewed stream probe scope selector must be a non-empty string.\" };\n if (kind === \"timelapse\") {\n const lapse = options.lapse;\n if (!lapse || typeof lapse !== \"object\" || Array.isArray(lapse)) return { allowed: false, reason: \"A reviewed lapse plan with interval, duration and format is required in options.\" };\n const plan = lapse as Record<string, unknown>;\n if (typeof plan.interval !== \"number\" || !Number.isFinite(plan.interval) || plan.interval <= 0) return { allowed: false, reason: \"The reviewed lapse interval must be a positive number of milliseconds with no code ceiling.\" };\n if (typeof plan.duration !== \"number\" || !Number.isFinite(plan.duration) || plan.duration <= 0) return { allowed: false, reason: \"The reviewed lapse duration must be a positive number of milliseconds with no code ceiling.\" };\n if (plan.format !== undefined && plan.format !== \"png\" && plan.format !== \"jpeg\" && plan.format !== \"webp\") return { allowed: false, reason: \"The reviewed lapse format must be png, jpeg or webp.\" };\n const budget = lapsebudgetallowed(plan.interval as number, plan.duration as number, typeof options.wait === \"number\" ? options.wait : undefined);\n if (!budget.allowed) return budget;\n const capturecheck = validatecaptureoptions(options.capture);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (kind === \"convertimage\" || kind === \"makethumbs\") {\n const single = options.capture;\n const list = options.captures;\n const hasone = isnonempty(single);\n const haslist = Array.isArray(list) && list.length > 0 && list.every(item => isnonempty(item));\n if (!hasone && !haslist) return { allowed: false, reason: \"A reviewed capture id or a reviewed non-empty capture id list is required in options.\" };\n if (hasone && haslist) return { allowed: false, reason: \"The reviewed step needs one capture id or a capture id list, not both.\" };\n }\n if (kind === \"convertimage\") {\n const convert = options.convert;\n if (!convert || typeof convert !== \"object\" || Array.isArray(convert)) return { allowed: false, reason: \"A reviewed convert directive with a target format is required in options.\" };\n const directive = convert as Record<string, unknown>;\n if (directive.target !== \"png\" && directive.target !== \"jpeg\" && directive.target !== \"webp\") return { allowed: false, reason: \"The reviewed conversion target must be png, jpeg or webp.\" };\n if (directive.source !== undefined && directive.source !== \"png\" && directive.source !== \"jpeg\" && directive.source !== \"webp\") return { allowed: false, reason: \"The reviewed conversion source must be png, jpeg or webp.\" };\n if (directive.quality !== undefined && (typeof directive.quality !== \"number\" || !Number.isFinite(directive.quality) || directive.quality < 0 || directive.quality > 100)) return { allowed: false, reason: \"The reviewed conversion quality must stay between zero and one hundred with no code cap inside that range.\" };\n }\n if (kind === \"makethumbs\") {\n const thumb = options.thumb;\n if (!thumb || typeof thumb !== \"object\" || Array.isArray(thumb)) return { allowed: false, reason: \"A reviewed thumb directive with size, fit and suffix is required in options.\" };\n const directive = thumb as Record<string, unknown>;\n if (typeof directive.size !== \"number\" || !Number.isFinite(directive.size) || directive.size <= 0) return { allowed: false, reason: \"The reviewed thumbnail size must be a positive number of pixels with no fixed set.\" };\n if (directive.fit !== \"cover\" && directive.fit !== \"contain\") return { allowed: false, reason: \"The reviewed thumbnail fit must be cover or contain.\" };\n if (!isnonempty(directive.suffix)) return { allowed: false, reason: \"The reviewed thumbnail naming suffix must be a non-empty string.\" };\n }\n return { allowed: true };\n}\n\n/** Validates a single proposal against the active tab origin and local policy. */\nexport function validatestep(step: toolstep, origin: string): policyevaluation {\n if (!allowedactions.has(step.kind)) return { allowed: false, reason: \"Unsupported action kind.\" };\n if (!step.summary.trim()) return { allowed: false, reason: \"A human-readable action summary is required.\" };\n let options: Record<string, unknown>;\n try { options = parseoptions(step); } catch { return { allowed: false, reason: \"Step options must be a JSON object.\" }; }\n const hastargetref = options.targetref !== undefined;\n if (targetactions.has(step.kind) && !step.target?.trim() && !hastargetref) return { allowed: false, reason: \"A page target is required.\" };\n if (valueactions.has(step.kind) && !step.value?.trim()) return { allowed: false, reason: \"A reviewed value is required.\" };\n if (step.kind === \"select\" && !step.value?.trim()) return { allowed: false, reason: \"A reviewed option value is required.\" };\n if (step.kind === \"navigate\" && !step.value) return { allowed: false, reason: \"A navigation URL is required.\" };\n if (hastargetref) {\n const reference = validatetargetref(options.targetref);\n if (!reference.allowed) return reference;\n }\n if (step.kind === \"wait\") {\n try { waitduration(step); } catch { return { allowed: false, reason: \"Wait duration must be zero or a positive number of milliseconds.\" }; }\n }\n if (step.kind === \"navigate\") {\n try {\n if (new URL(step.value ?? \"\").origin !== origin) return { allowed: false, reason: \"Navigation must remain within the approved origin.\" };\n } catch {\n return { allowed: false, reason: \"Navigation URL is invalid.\" };\n }\n }\n if (step.kind === \"tabcreate\" || step.kind === \"windowcreate\" || step.kind === \"downloadfile\") {\n try {\n const url = new URL(step.value ?? \"\");\n if (url.protocol !== \"https:\") return { allowed: false, reason: \"The reviewed URL must use HTTPS.\" };\n } catch {\n return { allowed: false, reason: \"The reviewed URL is invalid.\" };\n }\n }\n if (step.kind === \"tabactivate\" || step.kind === \"tabclose\" || step.kind === \"tabreload\" || step.kind === \"windowclose\" || step.kind === \"windowresize\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser id is required.\" };\n }\n if (step.kind === \"zoomset\") {\n const zoom = Number(step.value);\n if (!Number.isFinite(zoom) || zoom <= 0) return { allowed: false, reason: \"The reviewed zoom must be a positive number.\" };\n }\n if (step.kind === \"setattribute\" || step.kind === \"writestorage\") {\n const keyname = step.kind === \"setattribute\" ? \"name\" : \"key\";\n if (typeof options[keyname] !== \"string\" || !(options[keyname] as string).trim()) return { allowed: false, reason: `A reviewed ${keyname} is required in options.` };\n if (typeof options.value !== \"string\") return { allowed: false, reason: \"A reviewed value is required in options.\" };\n }\n if (step.kind === \"windowresize\") {\n if (typeof options.width !== \"number\" || typeof options.height !== \"number\" || !Number.isFinite(options.width) || !Number.isFinite(options.height)) return { allowed: false, reason: \"Reviewed width and height numbers are required in options.\" };\n }\n if ((step.kind === \"scrollpage\" || step.kind === \"scrollby\") && (!numericoption(options, \"x\") || !numericoption(options, \"y\"))) return { allowed: false, reason: \"Scroll amounts must be numbers in options.\" };\n if (step.kind === \"waitfor\" && options.timeout !== undefined && (typeof options.timeout !== \"number\" || options.timeout < 0)) return { allowed: false, reason: \"The waitfor timeout must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"movepointer\") {\n const path = options.pointpath;\n if (!path || typeof path !== \"object\" || Array.isArray(path)) return { allowed: false, reason: \"A reviewed pointpath with start and end points is required in options.\" };\n const points = path as Record<string, unknown>;\n if (!ispoint(points.start) || !ispoint(points.end)) return { allowed: false, reason: \"The reviewed pointpath needs numeric start and end points.\" };\n if (points.waypoints !== undefined && (!Array.isArray(points.waypoints) || !points.waypoints.every(waypoint => ispoint(waypoint)))) return { allowed: false, reason: \"The reviewed pointpath waypoints must be numeric points.\" };\n if (!nonnegativeoption(points, \"duration\")) return { allowed: false, reason: \"The reviewed pointpath duration must be zero or a positive number of milliseconds.\" };\n const speed = options.speedprofile;\n if (speed !== undefined) {\n if (!speed || typeof speed !== \"object\" || Array.isArray(speed)) return { allowed: false, reason: \"The reviewed speed profile must be an object.\" };\n const profile = speed as Record<string, unknown>;\n if (profile.easing !== undefined && profile.easing !== \"linear\" && profile.easing !== \"easeinout\") return { allowed: false, reason: \"The reviewed easing must be linear or easeinout.\" };\n if (!nonnegativeoption(profile, \"peak\")) return { allowed: false, reason: \"The reviewed peak velocity must be zero or a positive number.\" };\n if (!nonnegativeoption(profile, \"jitter\")) return { allowed: false, reason: \"The reviewed jitter window must be zero or a positive number of milliseconds.\" };\n }\n }\n if (step.kind === \"clickpoint\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"point\")) return { allowed: false, reason: \"A reviewed point target reference is required in options.\" };\n if (step.kind === \"clicktext\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"text\")) return { allowed: false, reason: \"A reviewed text target reference is required in options.\" };\n if (step.kind === \"clickaria\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"aria\")) return { allowed: false, reason: \"A reviewed aria target reference is required in options.\" };\n if (step.kind === \"clickname\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"name\")) return { allowed: false, reason: \"A reviewed name target reference is required in options.\" };\n if (step.kind === \"resolvexpath\" && (!hastargetref || (options.targetref as Record<string, unknown>).mode !== \"xpath\")) return { allowed: false, reason: \"A reviewed xpath target reference is required in options.\" };\n if (step.kind === \"typetime\" && options.delay !== undefined && (typeof options.delay !== \"number\" || !Number.isFinite(options.delay) || options.delay < 0)) return { allowed: false, reason: \"The reviewed per keystroke delay must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"submitsearch\") {\n if (!isnonempty(options.results)) return { allowed: false, reason: \"A reviewed results region selector is required in options.\" };\n if (options.timeout !== undefined && (typeof options.timeout !== \"number\" || !Number.isFinite(options.timeout) || options.timeout < 0)) return { allowed: false, reason: \"The submitsearch timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"selectmulti\") {\n const values = options.values;\n if (!Array.isArray(values) || values.length === 0 || !values.every(value => isnonempty(value))) return { allowed: false, reason: \"A reviewed list of option values is required in options.\" };\n }\n if (step.kind === \"setslider\") {\n const slider = Number(step.value);\n if (!Number.isFinite(slider)) return { allowed: false, reason: \"The reviewed slider value must be a number.\" };\n }\n if (step.kind === \"setdate\" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed date must use the yyyy-mm-dd form.\" };\n if (step.kind === \"setcolor\" && !/^#[0-9a-fA-F]{6}$/.test(step.value ?? \"\")) return { allowed: false, reason: \"The reviewed color must use the #rrggbb form.\" };\n if (step.kind === \"keyhold\" && options.holdid !== undefined && !isnonempty(options.holdid)) return { allowed: false, reason: \"The reviewed hold id must be a non-empty string.\" };\n if (step.kind === \"dismissdialog\") {\n const accept = options.accept;\n const answer = options.answer;\n if (accept === undefined && !isnonempty(answer)) return { allowed: false, reason: \"A reviewed accept flag or prompt answer is required in options.\" };\n if (accept !== undefined && typeof accept !== \"boolean\") return { allowed: false, reason: \"The reviewed dialog accept flag must be a boolean.\" };\n if (answer !== undefined && !isnonempty(answer)) return { allowed: false, reason: \"The reviewed prompt answer must be a non-empty string.\" };\n }\n if (step.kind === \"pierceshadow\" && options.shadow !== undefined) {\n if (!Array.isArray(options.shadow) || !options.shadow.every(item => isnonempty(item))) return { allowed: false, reason: \"The reviewed shadow path must be a list of non-empty selectors.\" };\n }\n if (step.kind === \"enterframe\") {\n const path = options.framepath;\n if (!Array.isArray(path) || path.length === 0 || !path.every(item => typeof item === \"number\" && Number.isInteger(item) && item >= 0)) return { allowed: false, reason: \"A reviewed frame path of frame indexes is required in options.\" };\n return validateinnerstep(options, origin);\n }\n if (step.kind === \"retryaction\") {\n const inner = validateinnerstep(options, origin);\n if (!inner.allowed) return inner;\n const rule = options.retryrule;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule)) return { allowed: false, reason: \"A reviewed retry rule with attempts is required in options.\" };\n const retry = rule as Record<string, unknown>;\n if (typeof retry.attempts !== \"number\" || !Number.isInteger(retry.attempts) || retry.attempts < 1) return { allowed: false, reason: \"The reviewed retry attempts must be a positive integer with no code ceiling.\" };\n if (!nonnegativeoption(retry, \"settle\")) return { allowed: false, reason: \"The reviewed retry settle window must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(retry, \"tolerance\")) return { allowed: false, reason: \"The reviewed retry movement tolerance must be zero or a positive number of pixels.\" };\n }\n if (watchactions.has(step.kind)) {\n if (typeof options.lifetime !== \"number\" || !Number.isFinite(options.lifetime) || options.lifetime <= 0) return { allowed: false, reason: \"A reviewed watch lifetime window in milliseconds is required in options.\" };\n if (options.scopes !== undefined && (!Array.isArray(options.scopes) || !options.scopes.every(scope => isnonempty(scope)))) return { allowed: false, reason: \"The reviewed watch scopes must be a list of non-empty selectors.\" };\n if (options.events !== undefined && (!Array.isArray(options.events) || !options.events.every(event => isnonempty(event)))) return { allowed: false, reason: \"The reviewed watch event kinds must be a list of non-empty strings.\" };\n if (!nonnegativeoption(options, \"poll\")) return { allowed: false, reason: \"The reviewed watch poll interval must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"waitquiet\") {\n const rule = options.quietrule;\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule)) return { allowed: false, reason: \"A reviewed quietrule with an idle threshold is required in options.\" };\n const quiet = rule as Record<string, unknown>;\n if (typeof quiet.idle !== \"number\" || !Number.isFinite(quiet.idle) || quiet.idle <= 0) return { allowed: false, reason: \"The reviewed quiet idle threshold must be a positive number of milliseconds with no code ceiling.\" };\n if (!nonnegativeoption(quiet, \"poll\")) return { allowed: false, reason: \"The reviewed quiet poll interval must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(quiet, \"timeout\")) return { allowed: false, reason: \"The reviewed quiet timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"diffsnapshots\") {\n const versions = options.versions;\n if (!Array.isArray(versions) || versions.length !== 2 || !versions.every(version => typeof version === \"number\" && Number.isInteger(version) && version >= 1)) return { allowed: false, reason: \"Two reviewed observation version numbers are required in options.\" };\n }\n if (step.kind === \"openlink\" || step.kind === \"openprivate\" || step.kind === \"deeplink\") {\n const targetcheck = validatenavtarget(options.navtarget, step.kind);\n if (!targetcheck.allowed) return targetcheck;\n if (step.kind === \"deeplink\") {\n const app = options.app;\n if (!isnonempty(app)) return { allowed: false, reason: \"A reviewed deep link app pattern is required in options.\" };\n const params = options.params;\n if (params !== undefined && (!params || typeof params !== \"object\" || Array.isArray(params) || !Object.values(params).every(item => typeof item === \"string\"))) return { allowed: false, reason: \"The reviewed deep link params must be an object of string values.\" };\n }\n }\n if (step.kind === \"waitload\" && !nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The waitload timeout must be zero or a positive number of milliseconds.\" };\n if (step.kind === \"waiturl\" || step.kind === \"spawait\") {\n if (step.kind === \"waiturl\") {\n const patterncheck = validateurlpattern(options.urlpattern);\n if (!patterncheck.allowed) return patterncheck;\n }\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The wait timeout must be zero or a positive number of milliseconds.\" };\n if (!nonnegativeoption(options, \"poll\")) return { allowed: false, reason: \"The wait poll interval must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"followlink\") {\n if (options.fragment !== undefined && typeof options.fragment !== \"boolean\") return { allowed: false, reason: \"The reviewed followlink fragment flag must be a boolean.\" };\n }\n if (step.kind === \"spanav\") {\n if (options.routepattern !== undefined) {\n const routecheck = validateurlpattern(options.routepattern);\n if (!routecheck.allowed) return routecheck;\n }\n if (!nonnegativeoption(options, \"timeout\")) return { allowed: false, reason: \"The spanav route timeout must be zero or a positive number of milliseconds.\" };\n }\n if (step.kind === \"rewritequery\") {\n const set = options.set;\n const remove = options.remove;\n if (set === undefined && remove === undefined) return { allowed: false, reason: \"Reviewed query parameters to set or remove are required in options.\" };\n if (set !== undefined && (!set || typeof set !== \"object\" || Array.isArray(set) || !Object.values(set).every(item => typeof item === \"string\"))) return { allowed: false, reason: \"The reviewed query parameters to set must be an object of string values.\" };\n if (remove !== undefined && (!Array.isArray(remove) || !remove.every(item => isnonempty(item)))) return { allowed: false, reason: \"The reviewed query parameters to remove must be a list of non-empty names.\" };\n }\n if (step.kind === \"navlist\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (step.kind === \"navprofile\") {\n const profilecheck = validatewaitprofile(options.waitprofile);\n if (!profilecheck.allowed) return profilecheck;\n }\n if (step.kind === \"handleauth\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS origin or url is required as the auth target.\" };\n if (step.kind === \"printpdf\" && options.name !== undefined && !isnonempty(options.name)) return { allowed: false, reason: \"The reviewed artifact name must be a non-empty string.\" };\n if (step.kind === \"prefetch\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (step.kind === \"preconnect\") {\n const origins = options.origins;\n if (!Array.isArray(origins) || origins.length === 0 || !origins.every(originurl => ishttpsurl(originurl))) return { allowed: false, reason: \"A reviewed non-empty list of HTTPS origins is required in options.\" };\n }\n if (step.kind === \"reopentab\" && step.value !== undefined && !ishttpsurl(step.value)) return { allowed: false, reason: \"The reviewed reopen url must use HTTPS.\" };\n if (step.kind === \"navrate\") {\n const limitcheck = validateratelimit(options.ratelimit);\n if (!limitcheck.allowed) return limitcheck;\n }\n if (step.kind === \"checksafe\" && !ishttpsurl(step.value)) return { allowed: false, reason: \"A reviewed HTTPS url is required for the safety check.\" };\n if (step.kind === \"batchopen\") {\n const listcheck = validateurllist(options, \"urls\");\n if (!listcheck.allowed) return listcheck;\n }\n if (istabscommandkind(step.kind)) {\n const tabscheck = validatetabsgrammar(step, options);\n if (!tabscheck.allowed) return tabscheck;\n }\n if (isformkind(step.kind)) {\n const formcheck = validateformgrammar(step, options);\n if (!formcheck.allowed) return formcheck;\n }\n if (isdatasetkind(step.kind)) {\n const datacheck = validatedatagrammar(step, options, origin);\n if (!datacheck.allowed) return datacheck;\n }\n if (isfileskind(step.kind)) {\n const filescheck = validatefilesgrammar(step, options);\n if (!filescheck.allowed) return filescheck;\n }\n if (iscapturekind(step.kind)) {\n const capturecheck = validatecapturegrammar(step, options);\n if (!capturecheck.allowed) return capturecheck;\n }\n if (ismediakind(step.kind)) {\n const mediacheck = validatemediagrammar(step, options);\n if (!mediacheck.allowed) return mediacheck;\n }\n if (ishttpkind(step.kind)) {\n const httpcheck = validatehttpgrammar(step, options);\n if (!httpcheck.allowed) return httpcheck;\n }\n if (issocketkind(step.kind)) {\n const socketcheck = validatesocketgrammar(step, options);\n if (!socketcheck.allowed) return socketcheck;\n }\n if (isnetwatchkind(step.kind)) {\n const netwatchcheck = validatenetwatchgrammar(step, options);\n if (!netwatchcheck.allowed) return netwatchcheck;\n }\n if (iscontrolkind(step.kind)) {\n const controlcheck = validatecontrolgrammar(step, options);\n if (!controlcheck.allowed) return controlcheck;\n }\n if (isdebugkind(step.kind)) {\n const timelinecheck = validatetimelinegrammar(step, options);\n if (!timelinecheck.allowed) return timelinecheck;\n }\n if (iscdpkind(step.kind)) {\n const cdpcheck = validatecdpgrammar(step, options);\n if (!cdpcheck.allowed) return cdpcheck;\n }\n if (isprofilekind(step.kind)) {\n const profilecheck = validateprofilegrammar(step, options);\n if (!profilecheck.allowed) return profilecheck;\n }\n if (isemulationkind(step.kind)) {\n const emulationcheck = validateemulationgrammar(step, options);\n if (!emulationcheck.allowed) return emulationcheck;\n }\n if (issessionkind(step.kind)) {\n const sessioncheck = validatesessiongrammar(step, options);\n if (!sessioncheck.allowed) return sessioncheck;\n }\n if (isworkflowkind(step.kind)) {\n const workflowcheck = validateworkflowgrammar(step, options);\n if (!workflowcheck.allowed) return workflowcheck;\n }\n if (istriggeraction(step.kind)) {\n const triggercheck = validatetriggergrammar(step, options);\n if (!triggercheck.allowed) return triggercheck;\n }\n if (step.kind === \"tabcreate\") {\n if (options.background !== undefined && typeof options.background !== \"boolean\") return { allowed: false, reason: \"The reviewed background flag must be a boolean.\" };\n if (options.window !== undefined && (typeof options.window !== \"number\" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: \"The reviewed target window id must be a non-negative integer.\" };\n }\n if (step.kind === \"windowcreate\") {\n for (const field of [\"left\", \"top\", \"width\", \"height\"]) {\n if (options[field] !== undefined && (typeof options[field] !== \"number\" || !Number.isFinite(options[field]))) return { allowed: false, reason: `The reviewed window ${field} must be a number.` };\n }\n if (options.state !== undefined && ![\"normal\", \"maximized\", \"minimized\", \"fullscreen\"].includes(options.state as string)) return { allowed: false, reason: \"The reviewed window state must be normal, maximized, minimized or fullscreen.\" };\n }\n return { allowed: true };\n}\n\n/** Shared session gate: a live, unpaused session that still matches the active tab. */\nfunction sessiongate(input: { session: agentsession | undefined; tabid: number; origin: string; now: number; action: string }): policyevaluation {\n if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.pausedat) return { allowed: false, reason: `The browser session is paused and cannot ${input.action}.` };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: `The ${input.action} is outside the approved tab or origin.` };\n return { allowed: true };\n}\n\n/** Applies the consent gate immediately before an action reaches the page bridge. */\nexport function canexecute(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number; verdicts?: safetyverdict[]; settings?: runsettings }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"execute an action\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"The plan has not received explicit approval.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The approved plan has expired.\" };\n if ((input.step.kind === \"pierceshadow\" || input.step.kind === \"enterframe\") && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The shadow or frame step is outside the session origin grants.\" };\n if (input.step.kind === \"readjson\" && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The json state read is outside the session origin grants.\" };\n if (isexportkind(input.step.kind)) {\n const exportgate = exportgranted(input.session, input.origin);\n if (!exportgate.allowed) return exportgate;\n }\n if (input.step.kind === \"navlist\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n for (const url of Array.isArray(options.urls) ? options.urls : []) {\n if (typeof url !== \"string\") continue;\n const navigation = navigationgranted(input.session, url);\n if (!navigation.allowed) return navigation;\n }\n }\n if (islayoutkind(input.step.kind) && !layoutmutationgranted(input.session, now).allowed) return { allowed: false, reason: \"Group and layout mutations stay inside the active session.\" };\n if (input.step.kind === \"submitform\" || input.step.kind === \"retryform\") {\n if (!input.plan) return { allowed: false, reason: \"Form submission requires an asksubmit review step before it.\" };\n const reviewgate = submitreviewgranted(input.plan.steps, input.step.id);\n if (!reviewgate.allowed) return reviewgate;\n }\n if (input.step.kind === \"consentpassword\") {\n const consentgate = passwordconsentgranted(input.step);\n if (!consentgate.allowed) return consentgate;\n }\n if (input.step.kind === \"readclipboard\") {\n const clipgate = clipboardconsentgranted(input.step);\n if (!clipgate.allowed) return clipgate;\n }\n if (input.step.kind === \"interceptmime\" && !origingranted(input.session, input.origin)) return { allowed: false, reason: \"The download interception is outside the session origin grants.\" };\n if (iscapturekind(input.step.kind)) {\n const capturegatecheck = capturegate(input.session, input.tabid, input.origin, now);\n if (!capturegatecheck.allowed) return capturegatecheck;\n let captureoptions: Record<string, unknown> = {};\n try { captureoptions = parseoptions(input.step); } catch { captureoptions = {}; }\n const target = (captureoptions.capture as Record<string, unknown> | undefined)?.exporttarget;\n if (target !== undefined && target !== \"memory\" && target !== \"download\" && target !== \"clipboard\") return { allowed: false, reason: \"The capture export target must be memory, download or clipboard.\" };\n }\n if (ismediakind(input.step.kind)) {\n const mediagatecheck = mediagate(input.session, input.tabid, input.origin, now);\n if (!mediagatecheck.allowed) return mediagatecheck;\n }\n if (isrecordingkind(input.step.kind)) {\n const recordinggate = recordingconsentgranted(input.step);\n if (!recordinggate.allowed) return recordinggate;\n }\n if (ishttpkind(input.step.kind)) {\n const target = outboundtarget(input.step);\n if (target !== undefined) {\n const outboundgate = origincheck(input.session, target);\n if (!outboundgate.allowed) return outboundgate;\n }\n if (input.step.kind === \"fetchurl\" || input.step.kind === \"callrest\" || input.step.kind === \"callgraphql\") {\n const consentgate = fetchconsentrefgranted(input.step);\n if (!consentgate.allowed) return consentgate;\n }\n }\n if (issocketkind(input.step.kind)) {\n const channelurl = sockettarget(input.step);\n if (channelurl !== undefined) {\n const channelgate = socketgate(input.session, channelurl);\n if (!channelgate.allowed) return channelgate;\n }\n }\n if (input.step.kind === \"watchrequests\") {\n const watchgatecheck = watchgate(input.session, input.settings, now);\n if (!watchgatecheck.allowed) return watchgatecheck;\n }\n if (isdebugkind(input.step.kind)) {\n const timelinegatecheck = timelinegate(input.session, input.tabid, input.origin, now);\n if (!timelinegatecheck.allowed) return timelinegatecheck;\n }\n if (iscdpkind(input.step.kind)) {\n const debuggatecheck = debuggate(input.session, input.tabid, input.origin, now);\n if (!debuggatecheck.allowed) return debuggatecheck;\n if (!input.plan) return { allowed: false, reason: \"The devtools protocol steps need an approved plan.\" };\n const allowlist = planallowlist(input.plan.steps);\n if (input.step.kind !== \"attachcdp\") {\n if (allowlist === undefined) return { allowed: false, reason: \"The devtools protocol step needs the attachcdp step of the same plan with its enabled domains first.\" };\n if (input.step.kind === \"cdpcmd\") {\n let cdpoptions: Record<string, unknown> = {};\n try { cdpoptions = parseoptions(input.step); } catch { cdpoptions = {}; }\n const command = cdpoptions.command && typeof cdpoptions.command === \"object\" && !Array.isArray(cdpoptions.command) ? cdpoptions.command as Record<string, unknown> : undefined;\n const method = typeof command?.method === \"string\" ? command.method : \"\";\n if (methoddomain(method) === undefined || !allowlistcovers(allowlist, method)) return { allowed: false, reason: `The raw command ${method || \"\"} stays outside the enabled domain allowlist of the plan attach; review the attach domains or the method gates.` };\n }\n }\n let cdpoptions: Record<string, unknown> = {};\n try { cdpoptions = parseoptions(input.step); } catch { cdpoptions = {}; }\n if (input.step.kind === \"setbreakpoint\") {\n const breakpoint = breakpointinputof(cdpoptions.breakpoint);\n if (breakpoint) {\n const targetgate = origincheck(input.session, breakpoint.url);\n if (!targetgate.allowed) return targetgate;\n }\n }\n if (input.step.kind === \"overridescript\") {\n const override = overrideinputof(cdpoptions.override);\n if (override) {\n const targetgate = origincheck(input.session, override.urlpattern);\n if (!targetgate.allowed) return targetgate;\n }\n }\n }\n if (isprofilekind(input.step.kind)) {\n let profileoptions: Record<string, unknown> = {};\n try { profileoptions = parseoptions(input.step); } catch { profileoptions = {}; }\n const targets = [\n ...(attachtargetof(profileoptions.target) !== undefined ? [attachtargetof(profileoptions.target) as attachtarget] : []),\n ...(Array.isArray(profileoptions.attachtargets) ? profileoptions.attachtargets.flatMap(target => { const parsed = attachtargetof(target); return parsed !== undefined ? [parsed] : []; }) : []),\n ];\n const targetgatecheck = targetgate({ session: input.session, tabid: input.tabid, origin: input.origin, targets, grants: undefined, now });\n if (!targetgatecheck.allowed) return targetgatecheck;\n if (input.step.kind === \"capturesourcemaps\") {\n for (const url of Array.isArray(profileoptions.scripts) ? profileoptions.scripts : []) {\n if (typeof url !== \"string\") continue;\n const scriptgate = origincheck(input.session, url);\n if (!scriptgate.allowed) return scriptgate;\n }\n }\n }\n if (isemulationkind(input.step.kind)) {\n const emugatecheck = emugate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!emugatecheck.allowed) return emugatecheck;\n }\n if (issessionkind(input.step.kind)) {\n const sessiongatecheck = sessionrestoregate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!sessiongatecheck.allowed) return sessiongatecheck;\n if (input.step.kind === \"restoresession\") {\n let restoreoptions: Record<string, unknown> = {};\n try { restoreoptions = parseoptions(input.step); } catch { restoreoptions = {}; }\n for (const url of Array.isArray(restoreoptions.origins) ? restoreoptions.origins : []) {\n if (typeof url !== \"string\" || !url) continue;\n const origingate = origincheck(input.session, url);\n if (!origingate.allowed) return { allowed: false, reason: `The session restore reopens ${url} outside the session origin grants; review the restore record or grant the origin.` };\n }\n }\n }\n if (isworkflowkind(input.step.kind)) {\n const workflowgatecheck = workflowgate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!workflowgatecheck.allowed) return workflowgatecheck;\n }\n if (istriggeraction(input.step.kind)) {\n const triggergatecheck = triggergate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });\n if (!triggergatecheck.allowed) return triggergatecheck;\n }\n if (iscontrolkind(input.step.kind)) {\n const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"control the network\" });\n if (!controlgate.allowed) return controlgate;\n let controloptions: Record<string, unknown> = {};\n try { controloptions = parseoptions(input.step); } catch { controloptions = {}; }\n if (input.step.kind === \"blockrequest\") {\n const blockgatecheck = blockgate(input.session, input.step, now);\n if (!blockgatecheck.allowed) return blockgatecheck;\n const rule = blockruleof(controloptions.block);\n if (rule) {\n const blockorigin = origincheck(input.session, rule.urlpattern);\n if (!blockorigin.allowed) return blockorigin;\n }\n }\n if (input.step.kind === \"mockresponse\" || input.step.kind === \"rewriteheaders\") {\n const patterns = input.step.kind === \"mockresponse\" ? [mockspecof(controloptions.mock)?.urlpattern ?? \"\"] : (Array.isArray(controloptions.rules) ? controloptions.rules.map(item => item && typeof item === \"object\" && !Array.isArray(item) ? String((item as Record<string, unknown>).urlpattern ?? \"\") : \"\") : []);\n for (const pattern of patterns) {\n const patterngate = origincheck(input.session, pattern);\n if (!patterngate.allowed) return patterngate;\n }\n }\n if (input.step.kind === \"setcookies\" || input.step.kind === \"readcookies\" || input.step.kind === \"clearcookies\") {\n const domain = typeof controloptions.domain === \"string\" && controloptions.domain.trim() ? controloptions.domain : Array.isArray(controloptions.cookies) ? String((controloptions.cookies[0] as Record<string, unknown> | undefined)?.domain ?? \"\") : \"\";\n if (!domain) return { allowed: false, reason: \"A reviewed cookie domain is required before cookie control runs.\" };\n const cookiegatecheck = cookiegate(input.session, domain, now);\n if (!cookiegatecheck.allowed) return cookiegatecheck;\n }\n if (input.step.kind === \"authflow\") {\n const authconsent = authconsentgranted(input.step);\n if (!authconsent.allowed) return authconsent;\n }\n if (input.step.kind === \"saveapikey\") {\n const keyconsent = apikeyconsentgranted(input.step);\n if (!keyconsent.allowed) return keyconsent;\n }\n if (input.step.kind === \"routeproxy\") {\n const proxygatecheck = proxygate(input.session, input.step, now);\n if (!proxygatecheck.allowed) return proxygatecheck;\n }\n const target = controltarget(input.step);\n if (target !== undefined) {\n const targetgate = origincheck(input.session, target);\n if (!targetgate.allowed) return targetgate;\n }\n }\n if (input.step.kind === \"extractapi\") {\n let replayoptions: Record<string, unknown> = {};\n try { replayoptions = parseoptions(input.step); } catch { replayoptions = {}; }\n const replay = apireplayspecof(replayoptions.replay);\n if (replay !== undefined) {\n const replaygate = origincheck(input.session, replay.endpoint);\n if (!replaygate.allowed) return replaygate;\n }\n }\n if (input.step.kind === \"openlink\" || input.step.kind === \"openprivate\" || input.step.kind === \"batchopen\" || input.step.kind === \"prefetch\" || input.step.kind === \"deeplink\" || input.step.kind === \"reopentab\") {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n const grammar = validatestep(input.step, input.origin);\n if (!grammar.allowed) return grammar;\n const grants = input.session?.grants ?? [input.session?.origin ?? input.origin];\n const targets: unknown[] = input.step.kind === \"batchopen\" || input.step.kind === \"prefetch\" ? (Array.isArray(options.urls) ? options.urls : []) : input.step.kind === \"reopentab\" ? [input.step.value] : [(options.navtarget as Record<string, unknown> | undefined)?.url];\n for (const target of targets) {\n if (typeof target !== \"string\" || !target) continue;\n const verified = originverified(target, grants, input.verdicts ?? []);\n if (!verified.allowed) return verified;\n }\n }\n return validatestep(input.step, input.origin);\n}\n\n/** Allows a non-mutating, temporary target preview during plan review. */\nexport function canpreview(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"preview a target\" });\n if (!gate.allowed) return gate;\n if (!input.plan || ![\"pending\", \"approved\"].includes(input.plan.state)) return { allowed: false, reason: \"Only a reviewed pending or approved plan can be previewed.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The reviewed plan has expired.\" };\n let options: Record<string, unknown> = {};\n try { options = parseoptions(input.step); } catch { options = {}; }\n if (!targetactions.has(input.step.kind) && options.targetref === undefined) return { allowed: false, reason: \"Only a target-based action can be previewed.\" };\n return validatestep(input.step, input.origin);\n}\n\n/** Lists every reviewed action kind of the policy table so the step library of the editor browses the whole vocabulary. */\nexport function reviewedkinds(): string[] {\n return [...allowedactions].sort();\n}\n\n/** The editor save gate: the canvas model of a save needs a live session and an approved plan like every other reviewed artifact, its nodes must be steps or block invocations with unique ids, its edges must reference existing steps and run forward only so no cycle forms, and the composed record still passes the full workflow grammar through the composition the save triggers. */\nexport function editorsavegate(input: { session: agentsession | undefined; plan: agentplan | undefined; model: editormodel; now: number }): policyevaluation {\n const gate = sessiongate({ session: input.session, tabid: input.session?.tabid ?? 0, origin: input.session?.origin ?? \"https://example.com\", now: input.now, action: \"save the workflow editor canvas\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Editor saves need the approved plan review before a new workflow version composes.\" };\n const model = input.model;\n if (typeof model.name !== \"string\" || !model.name.trim()) return { allowed: false, reason: \"The workflow name of the canvas must be a non-empty string.\" };\n if (typeof model.version !== \"number\" || !Number.isInteger(model.version) || model.version < 1) return { allowed: false, reason: \"The workflow version of the canvas must be a positive integer.\" };\n if (!Array.isArray(model.origins) || model.origins.length === 0) return { allowed: false, reason: \"The canvas needs at least one granted HTTPS origin.\" };\n const ids = new Set<string>();\n for (const node of model.nodes) {\n if ((node.step === undefined) === (node.invocation === undefined)) return { allowed: false, reason: \"Every canvas node must be exactly one workflow step or one block invocation.\" };\n const id = node.id ?? (node.step !== undefined ? node.step.id : (node.invocation as { block: string }).block);\n if (!id || ids.has(id)) return { allowed: false, reason: `The canvas node id ${id || \"(empty)\"} must be unique.` };\n ids.add(id);\n }\n const reachable = new Set<string>();\n for (const node of model.nodes) {\n if (node.step !== undefined) { reachable.add(node.step.id); continue; }\n const walk = (entries: Array<{ id?: string; kind?: string; label?: string; block?: string }>): void => {\n for (const entry of entries) {\n if (typeof entry.id === \"string\" && typeof entry.kind === \"string\") { reachable.add(entry.id); continue; }\n if (typeof entry.block === \"string\") {\n const nested = model.blocks.find(candidate => candidate.name === entry.block);\n if (nested) walk(nested.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n }\n };\n const block = model.blocks.find(candidate => candidate.name === (node.invocation as { block: string }).block);\n if (!block) return { allowed: false, reason: `The block ${(node.invocation as { block: string }).block} of the canvas has no definition.` };\n walk(block.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n let order = 0;\n const positionof = new Map<string, number>();\n for (const node of model.nodes) {\n if (node.step !== undefined) { positionof.set(node.step.id, order); order += 1; continue; }\n const walk = (entries: Array<{ id?: string; kind?: string; label?: string; block?: string }>): void => {\n for (const entry of entries) {\n if (typeof entry.id === \"string\" && typeof entry.kind === \"string\") { positionof.set(entry.id, order); order += 1; continue; }\n if (typeof entry.block === \"string\") {\n const nested = model.blocks.find(candidate => candidate.name === entry.block);\n if (nested) walk(nested.steps as Array<{ id?: string; kind?: string; label?: string; block?: string }>);\n }\n }\n };\n walk((model.blocks.find(candidate => candidate.name === (node.invocation as { block: string }).block) as { steps: Array<{ id?: string; kind?: string; label?: string; block?: string }> }).steps);\n }\n for (const edge of model.edges) {\n if (!reachable.has(edge.from)) return { allowed: false, reason: `The canvas edge of ${edge.variable} references the unknown source step ${edge.from}.` };\n if (!reachable.has(edge.to)) return { allowed: false, reason: `The canvas edge of ${edge.variable} references the unknown target step ${edge.to}.` };\n if ((positionof.get(edge.from) ?? -1) >= (positionof.get(edge.to) ?? -1)) return { allowed: false, reason: `The canvas edge of ${edge.variable} runs backwards and would form a cycle.` };\n }\n return { allowed: true };\n}\n\n/** Refuses to run a workflow whose review state stays pending: an imported workflow or a version rollback stays unreviewed until the user approves its expanded step list through the import or rollback review. */\nexport function runreviewgranted(record: workflowrecord): policyevaluation {\n if (record.reviewstate === \"pending\") return { allowed: false, reason: \"The workflow stays unreviewed: the import or rollback review must approve its expanded step list before any run.\" };\n return { allowed: true };\n}\n\n/** The reviewed policy knobs a per site override may adjust: loop safety bounds, per step and per run timeout budgets, element wait timeouts and delay bases. */\nconst overrideknobs = [\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"];\n\n/** Validates one per site policy override so overrides only adjust reviewed knobs: the pattern must be an https origin or a `*` subdomain glob of one and every delta must name a reviewed knob with a positive user value and no code ceiling. */\nexport function validatesiteoverride(override: { pattern: string; deltas: Record<string, number> }): policyevaluation {\n if (typeof override.pattern !== \"string\" || !override.pattern.startsWith(\"https://\") || !/[a-z0-9.-]+/i.test(override.pattern.slice(8))) return { allowed: false, reason: \"The override pattern must be an https origin or a `*` subdomain glob of one.\" };\n if (!override.pattern.includes(\"*\")) {\n try {\n if (new URL(override.pattern).origin !== override.pattern) return { allowed: false, reason: \"The override pattern must be a bare https origin or a `*` subdomain glob, never a path.\" };\n } catch {\n return { allowed: false, reason: \"The override pattern must parse as an https origin or a `*` subdomain glob of one.\" };\n }\n }\n for (const [knob, delta] of Object.entries(override.deltas)) {\n if (!overrideknobs.includes(knob)) return { allowed: false, reason: `The override knob ${knob} is not one of the reviewed knobs: ${overrideknobs.join(\", \")}.` };\n if (typeof delta !== \"number\" || !Number.isFinite(delta) || delta <= 0) return { allowed: false, reason: `The override delta of ${knob} must be a positive user value with no code ceiling.` };\n }\n return { allowed: true };\n}\n\n/** Validates the export contents of a workflow file so secrets never leave the browser: every step options object of the workflow and of every packed template is parsed and any field that names a secret, token, api key, password or authorization header refuses the export. */\nexport function exportcontentreview(file: { workflow: workflowrecord; templates: steptemplate[] }): policyevaluation {\n const secretkeys = /(secret|token|apikey|api_key|password|authorization|credential)/i;\n const scan = (label: string, options: string | undefined): policyevaluation | undefined => {\n if (options === undefined) return undefined;\n let payload: unknown;\n try { payload = JSON.parse(options); } catch { return undefined; }\n const walk = (value: unknown, path: string): policyevaluation | undefined => {\n if (!value || typeof value !== \"object\") return undefined;\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (secretkeys.test(key)) return { allowed: false, reason: `The export of ${label} carries the secret field ${path}${key} and secrets never leave the browser.` };\n const nested = walk(entry, `${path}${key}.`);\n if (nested !== undefined) return nested;\n }\n return undefined;\n };\n return walk(payload, \"\");\n };\n for (const step of file.workflow.steps) {\n const refusal = scan(`the step ${step.id}`, step.options);\n if (refusal !== undefined) return refusal;\n }\n for (const template of file.templates) {\n const refusal = scan(`the template ${template.name}`, template.step.options);\n if (refusal !== undefined) return refusal;\n }\n return { allowed: true };\n}\n\n/** Validates one watchdog configuration: the stall threshold stays a positive user value with no code ceiling, the recovery action is one of retry, pause or cancel and the zombie window, when configured, stays positive with no ceiling. */\nexport function watchdogconfigvalid(config: watchdogconfig): policyevaluation {\n if (typeof config.enabled !== \"boolean\") return { allowed: false, reason: \"The watchdog enabled flag must be a boolean.\" };\n if (typeof config.stallthreshold !== \"number\" || !Number.isFinite(config.stallthreshold) || config.stallthreshold <= 0) return { allowed: false, reason: \"The watchdog stall threshold must be a positive number of milliseconds with no code ceiling.\" };\n if (![\"retry\", \"pause\", \"cancel\"].includes(config.action)) return { allowed: false, reason: \"The watchdog recovery action must be retry, pause or cancel.\" };\n if (config.zombiewindow !== undefined && (typeof config.zombiewindow !== \"number\" || !Number.isFinite(config.zombiewindow) || config.zombiewindow <= 0)) return { allowed: false, reason: \"The watchdog zombie window, when configured, must be a positive number of milliseconds with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Validates one mcp tool catalog against the action kind grammar: every tool name stays namespaced and unique, every wrapped kind belongs to the reviewed vocabulary, every namespace keeps its tools inside its domain kinds and every input schema carries typed properties with its required list. */\nexport function validatetoolcatalog(catalog: toolcatalog): policyevaluation {\n if (!Array.isArray(catalog.domains) || catalog.domains.length === 0) return { allowed: false, reason: \"The tool catalog needs its tool domains.\" };\n const seen = new Set<string>();\n for (const domain of catalog.domains) {\n if (!toolnamespaces.includes(domain.namespace)) return { allowed: false, reason: `The tool domain ${String(domain.namespace)} is not a reviewed namespace.` };\n if (!Array.isArray(domain.tools) || domain.tools.length === 0) return { allowed: false, reason: `The ${domain.namespace} domain exposes no tools.` };\n for (const tool of domain.tools) {\n if (typeof tool.name !== \"string\" || !tool.name.startsWith(`${domain.namespace}.`)) return { allowed: false, reason: `The tool ${String(tool.name)} does not carry its ${domain.namespace} namespace prefix.` };\n if (seen.has(tool.name)) return { allowed: false, reason: `The tool name ${tool.name} is not unique across the catalog.` };\n seen.add(tool.name);\n if (!allowedactions.has(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which is outside the reviewed action kind grammar.` };\n if (!domainkinds[domain.namespace].includes(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which does not belong to the ${domain.namespace} domain.` };\n if (typeof tool.description !== \"string\" || tool.description.trim() === \"\") return { allowed: false, reason: `The tool ${tool.name} needs its plain language description.` };\n const schema = tool.inputschema;\n if (!schema || schema.type !== \"object\" || schema.properties === undefined || schema.properties === null || typeof schema.properties !== \"object\" || Array.isArray(schema.properties) || Object.keys(schema.properties).length === 0) return { allowed: false, reason: `The tool ${tool.name} needs its json schema inputs of at least one typed property.` };\n for (const [name, property] of Object.entries(schema.properties)) {\n if (![\"string\", \"number\", \"boolean\", \"object\", \"array\"].includes(property.type)) return { allowed: false, reason: `The ${tool.name} input ${name} carries an untyped property.` };\n if (typeof property.description !== \"string\" || property.description.trim() === \"\") return { allowed: false, reason: `The ${tool.name} input ${name} needs its plain language description.` };\n }\n for (const name of schema.required) {\n if (!(name in schema.properties)) return { allowed: false, reason: `The tool ${tool.name} marks ${name} required outside its properties.` };\n }\n }\n }\n return { allowed: true };\n}\n\n/** Grades one tooldef with the risk class of its action kind and refuses a tool whose declared grade disagrees with the grammar. */\nexport function toolriskgrade(tool: tooldef): policyevaluation {\n const grade = actionrisk(tool.kind);\n if (grade !== tool.risk) return { allowed: false, reason: `The tool ${tool.name} declares the ${tool.risk} grade while its kind ${String(tool.kind)} grades ${grade}.` };\n return { allowed: true };\n}\n\n/** Requires consent metadata on every tool with side effects: read only tools stay free of the extra review while interaction and sensitive tools must declare their review requirement. */\nexport function toolconsentrequired(tool: tooldef): policyevaluation {\n if (tool.risk === \"read\") return { allowed: true };\n if (tool.consentmeta === undefined || typeof tool.consentmeta.review !== \"string\" || tool.consentmeta.review.trim() === \"\") return { allowed: false, reason: `The tool ${tool.name} has side effects and needs its consent metadata with the review requirement.` };\n return { allowed: true };\n}\n\n/** Grades one server bind configuration: the localhost bind stays the reviewed default while a bind outside localhost grades sensitive and needs the explicit remote review flag. */\nexport function serverbindgate(config: mcpserverconfig): policyevaluation {\n const bind = config.bind !== undefined && config.bind.trim() !== \"\" ? config.bind.trim() : \"127.0.0.1\";\n const local = bind === \"127.0.0.1\" || bind === \"localhost\" || bind === \"::1\";\n if (!local && config.remote !== true) return { allowed: false, reason: `The bind ${bind} leaves localhost and grades sensitive: the explicit remote review must approve it first.` };\n return { allowed: true };\n}\n\n/** Refuses one tool whose version stays below the negotiated compatibility floor so a client never receives a tool older than it can parse. */\nexport function toolversionfloor(tool: tooldef, floor: number): policyevaluation {\n if (typeof floor === \"number\" && Number.isFinite(floor) && tool.version < floor) return { allowed: false, reason: `The tool ${tool.name} of version ${tool.version} stays below the negotiated compatibility floor of ${floor}.` };\n return { allowed: true };\n}\n\n/** Requires the explicit user enablement before the mcp server ever starts; a disabled or unreviewed config never listens. */\nexport function serverenablementgate(config: mcpserverconfig): policyevaluation {\n if (config.enabled !== true) return { allowed: false, reason: \"The mcp server starts only after the user enables it; the protocol surface stays closed by default.\" };\n const bind = serverbindgate(config);\n if (!bind.allowed) return bind;\n if (!Array.isArray(config.transports) || config.transports.length === 0) return { allowed: false, reason: \"The mcp server needs at least one allowed transport of stdio or http.\" };\n if (!config.transports.every(transport => transport === \"stdio\" || transport === \"http\")) return { allowed: false, reason: \"The allowed transports of the mcp server are stdio and http.\" };\n if (typeof config.port !== \"number\" || !Number.isFinite(config.port) || config.port <= 0 || config.port > 65535) return { allowed: false, reason: \"The http listener port must be a valid port number.\" };\n if (config.framesize !== undefined && (typeof config.framesize !== \"number\" || !Number.isFinite(config.framesize) || config.framesize <= 0)) return { allowed: false, reason: \"The user configured frame size must stay a positive number with no code ceiling.\" };\n if (config.queuedepth !== undefined && (typeof config.queuedepth !== \"number\" || !Number.isFinite(config.queuedepth) || config.queuedepth <= 0)) return { allowed: false, reason: \"The user configured queue depth must stay a positive number with no code ceiling.\" };\n const remote = remoteenablementgate(config);\n if (!remote.allowed) return remote;\n return { allowed: true };\n}\n\n/** Validates the namespace membership of one tool: the name prefix must name the domain the tool lives in and the wrapped kind must belong to that domain so no tool drifts out of its namespace. */\nexport function toolnamespacegate(tool: tooldef): policyevaluation {\n const namespace = tool.name.split(\".\")[0];\n if (!toolnamespaces.includes(namespace as never)) return { allowed: false, reason: `The tool ${tool.name} carries no reviewed namespace prefix.` };\n if (!domainkinds[namespace as keyof typeof domainkinds].includes(tool.kind)) return { allowed: false, reason: `The tool ${tool.name} wraps ${String(tool.kind)} which does not belong to the ${namespace} domain.` };\n return { allowed: true };\n}\n\n/** The mcp tool dispatch gate: the client must be paired, the session live, the plan approved and the origin inside the session grants; read only tools pass under the dryrun risk class without extra approval while every tool with side effects must name the approved plan step of its own kind it executes. The full canexecute gates re-run at execution time. */\nexport function tooldispatchgate(input: { client: clientrecord; tool: tooldef; session: agentsession | undefined; plan: agentplan | undefined; origin: string; stepid?: string; now: number }): policyevaluation {\n if (input.client.disconnectedat !== undefined) return { allowed: false, reason: \"The mcp client is disconnected and its tool calls are refused.\" };\n if (!input.client.paired) return { allowed: false, reason: \"The mcp client waits for the user pairing approval; unpaired clients never dispatch tools.\" };\n if (!input.session || input.session.stoppedat || input.session.pausedat) return { allowed: false, reason: \"Tool dispatch needs the live browser session behind the consent gates.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired and tool dispatch is refused.\" };\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"Tool dispatch needs the approved plan review before any tool runs.\" };\n if (!origingranted(input.session, input.origin)) return { allowed: false, reason: `The tool call origin ${input.origin} stays outside the session grants and is refused.` };\n if (input.tool.risk === \"read\") return { allowed: true };\n if (input.stepid === undefined || input.stepid.trim() === \"\") return { allowed: false, reason: `The ${input.tool.name} tool has side effects and needs the id of the approved plan step it executes.` };\n const step = input.plan.steps.find(candidate => candidate.id === input.stepid);\n if (step === undefined) return { allowed: false, reason: `The tool call names the step ${input.stepid} which the approved plan does not carry.` };\n if (step.kind !== input.tool.kind) return { allowed: false, reason: `The tool call names the step ${input.stepid} whose kind ${String(step.kind)} does not match the ${input.tool.name} tool.` };\n return { allowed: true };\n}\n\n/** Grades the consent metadata of every sensitive tool: the risk class must match the policy grading of the wrapped kind, the approval gate requirement must be explicit and the origin scope must stay the session grants. */\nexport function consentmetagrade(tool: tooldef): policyevaluation {\n if (tool.risk === \"read\") return { allowed: true };\n if (tool.consentmeta === undefined) return { allowed: false, reason: `The tool ${tool.name} has side effects and needs its consent metadata.` };\n if (tool.consentmeta.riskclass !== actionrisk(tool.kind)) return { allowed: false, reason: `The consent metadata of ${tool.name} declares the ${String(tool.consentmeta.riskclass)} risk class while policy grades its kind ${String(tool.kind)} as ${actionrisk(tool.kind)}.` };\n if (tool.consentmeta.approvalrequired !== true) return { allowed: false, reason: `The tool ${tool.name} has side effects and its consent metadata must require the explicit approval gate.` };\n if (tool.consentmeta.originscope !== \"session\") return { allowed: false, reason: `The tool ${tool.name} must scope its calls to the session grants.` };\n return { allowed: true };\n}\n\n/** Validates one allowlist entry against the known client identities: the fingerprint must belong to a stored identity, the display name must be non empty and every granted namespace must be a reviewed namespace. */\nexport function allowlistentryvalid(entry: allowlistentry, identities: clientidentity[]): policyevaluation {\n if (typeof entry.fingerprint !== \"string\" || entry.fingerprint.trim() === \"\") return { allowed: false, reason: \"The allowlist entry needs the client fingerprint it grants.\" };\n if (!identities.some(identity => identity.fingerprint === entry.fingerprint)) return { allowed: false, reason: `The allowlist entry ${entry.fingerprint} matches no known client identity.` };\n if (typeof entry.displayname !== \"string\" || entry.displayname.trim() === \"\") return { allowed: false, reason: `The allowlist entry ${entry.fingerprint} needs its display name.` };\n if (!Array.isArray(entry.namespaces) || entry.namespaces.length === 0) return { allowed: false, reason: `The allowlist entry ${entry.displayname} grants no tool namespace.` };\n if (!entry.namespaces.every(namespace => toolnamespaces.includes(namespace))) return { allowed: false, reason: `The allowlist entry ${entry.displayname} grants an unreviewed namespace.` };\n return { allowed: true };\n}\n\n/** Validates one session token lifetime as a user configured value: an absent lifetime keeps the documented default while a configured window must stay positive with no code ceiling. */\nexport function tokenlifetimevalid(lifetime: number | undefined): policyevaluation {\n if (lifetime === undefined) return { allowed: true };\n if (typeof lifetime !== \"number\" || !Number.isFinite(lifetime) || lifetime <= 0) return { allowed: false, reason: \"The token lifetime must stay a positive user value with no code ceiling.\" };\n return { allowed: true };\n}\n\n/** Requires tls for any non localhost transport: a configured remote access policy or a bind outside localhost must carry the on or required tls mode before any remote traffic passes. */\nexport function remotetransporttls(config: mcpserverconfig): policyevaluation {\n const bind = config.bind !== undefined && config.bind.trim() !== \"\" ? config.bind.trim() : \"127.0.0.1\";\n const local = bind === \"127.0.0.1\" || bind === \"localhost\" || bind === \"::1\";\n const tls = config.remoteaccess?.tls ?? config.httpstream?.tls;\n if ((config.remoteaccess !== undefined || !local) && (tls === undefined || tls.mode === \"off\")) return { allowed: false, reason: `The ${config.remoteaccess !== undefined ? \"remote transport\" : `bind ${bind}`} leaves localhost and every non localhost transport requires tls before any remote traffic.` };\n return { allowed: true };\n}\n\n/** Refuses the pairing flow when no session is active: pairing codes issue only while the live browser session exists, so no remote client pairs against a closed surface. */\nexport function pairingreadinessgate(session: agentsession | undefined, now: number): policyevaluation {\n if (!session || session.stoppedat || session.pausedat) return { allowed: false, reason: \"The pairing flow needs the live browser session before any code issues.\" };\n if (session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired and the pairing flow is refused.\" };\n return { allowed: true };\n}\n\n/** Grades the remote transport enablement as a sensitive user choice: a configured remote access policy requires the explicit remote review and tls before the remote surface opens. */\nexport function remoteenablementgate(config: mcpserverconfig): policyevaluation {\n if (config.remoteaccess === undefined) return { allowed: true };\n if (config.remote !== true) return { allowed: false, reason: \"The remote transport enablement is a sensitive user choice and needs the explicit remote review.\" };\n const tls = remotetransporttls(config);\n if (!tls.allowed) return tls;\n if (typeof config.remoteaccess.endpoint !== \"string\" || config.remoteaccess.endpoint.trim() === \"\") return { allowed: false, reason: \"The remote access policy needs its user configured endpoint.\" };\n if (config.remoteaccess.maxclients !== undefined && (typeof config.remoteaccess.maxclients !== \"number\" || !Number.isFinite(config.remoteaccess.maxclients) || config.remoteaccess.maxclients <= 0)) return { allowed: false, reason: \"The user configured client ceiling must stay a positive value with no code ceiling.\" };\n const lifetime = tokenlifetimevalid(config.remoteaccess.tokenlifetimems);\n if (!lifetime.allowed) return lifetime;\n const timeout = approvaltimeoutvalid(config.remoteaccess.approvaltimeout);\n if (!timeout.allowed) return timeout;\n return { allowed: true };\n}\n\n/** Limits the token scopes to the namespaces the user granted: every scope must be a reviewed namespace the grant list carries, so a token never widens beyond the allowlist. */\nexport function tokenscopevalid(scopes: toolnamespace[], granted: toolnamespace[]): policyevaluation {\n if (!Array.isArray(scopes) || scopes.length === 0) return { allowed: false, reason: \"A session token needs at least one granted tool namespace.\" };\n for (const scope of scopes) {\n if (!toolnamespaces.includes(scope)) return { allowed: false, reason: `The scope ${String(scope)} is not a reviewed tool namespace.` };\n if (!granted.includes(scope)) return { allowed: false, reason: `The scope ${scope} stays outside the namespaces the user granted.` };\n }\n return { allowed: true };\n}\n\n/** Validates one approval timeout as a user configured positive window with the documented refusal default; an absent timeout keeps the documented default. */\nexport function approvaltimeoutvalid(timeout: approvaltimeout | undefined): policyevaluation {\n if (timeout === undefined) return { allowed: true };\n if (typeof timeout.windowms !== \"number\" || !Number.isFinite(timeout.windowms) || timeout.windowms <= 0) return { allowed: false, reason: \"The approval timeout must stay a positive user window with no code ceiling.\" };\n if (timeout.ontimeout !== \"refuse\") return { allowed: false, reason: \"The documented disposition of an unanswered approval gate is refusal.\" };\n return { allowed: true };\n}\n\n/** Grades the token revocation as an always available user action: no gate, review or state ever blocks the user from revoking a paired client. */\nexport function revocationgate(): policyevaluation {\n return { allowed: true };\n}\n", "import type { actionrisk, blockinvocation, editoredge, editormodel, editornode, editorlayout, exportformat, minimapstate, nestedparam, palettecategory, palettenode, siteoverride, steplibraryentry, steptemplate, variablebinding, versiondiff, workflowfile, workflowrecord, workflowstep } from \"./types.js\";\nimport { composeworkflow, steptemplateof, validateworkflow, workflowstepof } from \"./workflow.js\";\nimport { controlflowkinds } from \"./controlflow.js\";\nimport { triggerkinds } from \"./trigger.js\";\nimport { workflowfileversion } from \"./protocol.js\";\n\n/**\n * Workflow editor of the 1.1.53 family.\n * Every pure rule of the visual builder lives in this file: the canvas model with nodes, typed binding edges and layout state, the load and save round trips against the composed workflow grammar, the drag and drop snapping to block boundaries, the reorder persistence, the grouping of a selection into a new block, the template insertion with nested parameters, the mini map projection and viewport math, the zoom that keeps step labels readable, the step search, the breakpoint markers with the debug run segmentation, the version diffing, the json and yaml file format for import, export and template sharing, the per site override application and the undo and redo stacks.\n * The module stays pure: the sidepanel renders the model and the background validates saves through the same composeworkflow grammar every other path uses, so no editor artifact bypasses review.\n */\n\n/** The five categories of the block palette: actions, control flow, waits, variables and triggers. */\nexport const palettecategories: palettecategory[] = [\"actions\", \"controlflow\", \"waits\", \"variables\", \"triggers\"];\n\n/** The curated drop blocks of the palette: one descriptor per canonical block of every category. */\nexport const palettenodes: palettenode[] = [\n { kind: \"click\", label: \"Click an element\", category: \"actions\", description: \"Clicks the reviewed selector target.\" },\n { kind: \"type\", label: \"Type text\", category: \"actions\", description: \"Types the reviewed text into the target field.\" },\n { kind: \"navigate\", label: \"Navigate\", category: \"actions\", description: \"Navigates the tab to the reviewed url.\" },\n { kind: \"readtext\", label: \"Read text\", category: \"actions\", description: \"Reads the text of the target element.\" },\n { kind: \"scrapetable\", label: \"Scrape a table\", category: \"actions\", description: \"Extracts the reviewed table into a dataset.\" },\n { kind: \"fillform\", label: \"Fill a form\", category: \"actions\", description: \"Fills the reviewed form fields from a saved profile.\" },\n { kind: \"querytabs\", label: \"Query tabs\", category: \"actions\", description: \"Lists the tabs matching the reviewed query.\" },\n { kind: \"fetchurl\", label: \"Fetch a url\", category: \"actions\", description: \"Fetches the reviewed endpoint behind the call consent.\" },\n { kind: \"condition\", label: \"Condition\", category: \"controlflow\", description: \"Evaluates one reviewed boolean expression with no page side effect.\" },\n { kind: \"branch\", label: \"Branch\", category: \"controlflow\", description: \"Chooses one reviewed path by page state with a mandatory else path.\" },\n { kind: \"loop\", label: \"Loop a list\", category: \"controlflow\", description: \"Iterates a list variable binding the item and index per pass.\" },\n { kind: \"repeatuntil\", label: \"Repeat until\", category: \"controlflow\", description: \"Reruns the body until the convergence expression holds.\" },\n { kind: \"whileloop\", label: \"While loop\", category: \"controlflow\", description: \"Loops while the condition holds inside the reviewed bound.\" },\n { kind: \"foreach\", label: \"For each element\", category: \"controlflow\", description: \"Iterates the elements of the reviewed selector.\" },\n { kind: \"parallel\", label: \"Parallel branches\", category: \"controlflow\", description: \"Runs branches concurrently and joins them under the reviewed strategy.\" },\n { kind: \"trycatch\", label: \"Try catch\", category: \"controlflow\", description: \"Wraps fragile steps with a catch handler, retries and timeouts.\" },\n { kind: \"delay\", label: \"Delay\", category: \"waits\", description: \"Sleeps the reviewed base inside the jitter window.\" },\n { kind: \"waitelement\", label: \"Wait for element\", category: \"waits\", description: \"Polls the reviewed selector until appearance or timeout.\" },\n { kind: \"wait\", label: \"Wait\", category: \"waits\", description: \"Waits the reviewed duration.\" },\n { kind: \"waitfor\", label: \"Wait for target\", category: \"waits\", description: \"Waits until the reviewed target exists.\" },\n { kind: \"waittext\", label: \"Wait for text\", category: \"waits\", description: \"Waits until the reviewed text appears.\" },\n { kind: \"waitquiet\", label: \"Wait for quiet\", category: \"waits\", description: \"Waits until the page stops mutating.\" },\n { kind: \"waitload\", label: \"Wait for load\", category: \"waits\", description: \"Waits until the navigation settles.\" },\n { kind: \"compute\", label: \"Compute\", category: \"variables\", description: \"Evaluates one reviewed expression into the result variable.\" },\n { kind: \"extractvars\", label: \"Extract variables\", category: \"variables\", description: \"Applies the reviewed regex and stores the named captures.\" },\n { kind: \"savetemplate\", label: \"Save template\", category: \"variables\", description: \"Shares the reviewed step as a reusable template.\" },\n { kind: \"visitrule\", label: \"Visit rule\", category: \"triggers\", description: \"Fires on navigations to the reviewed origins.\" },\n { kind: \"urlrule\", label: \"Url rule\", category: \"triggers\", description: \"Fires when the url matches the reviewed glob pattern.\" },\n { kind: \"cronrule\", label: \"Cron rule\", category: \"triggers\", description: \"Fires on the reviewed five field cron schedule.\" },\n { kind: \"intervalrule\", label: \"Interval rule\", category: \"triggers\", description: \"Fires every reviewed period with the jitter spread.\" },\n { kind: \"webhookrule\", label: \"Webhook rule\", category: \"triggers\", description: \"Fires on a secret verified webhook delivery.\" },\n { kind: \"eventrule\", label: \"Event rule\", category: \"triggers\", description: \"Fires on the observed page events of the catalog.\" },\n];\n\n/** The reviewed option schemas the step library documents per kind; kinds without an entry document no reviewed options of their own. */\nconst optionschemas: Record<string, Array<{ name: string; kind: \"string\" | \"number\" | \"boolean\"; required?: boolean }>> = {\n delay: [{ name: \"base\", kind: \"number\", required: true }, { name: \"jitter\", kind: \"number\" }],\n waitelement: [{ name: \"timeout\", kind: \"number\" }, { name: \"poll\", kind: \"number\" }],\n compute: [{ name: \"expression\", kind: \"string\", required: true }],\n extractvars: [{ name: \"rule\", kind: \"string\", required: true }],\n composeworkflow: [{ name: \"name\", kind: \"string\", required: true }, { name: \"version\", kind: \"number\" }],\n runworkflow: [{ name: \"workflowid\", kind: \"string\", required: true }, { name: \"reviewed\", kind: \"boolean\", required: true }, { name: \"variables\", kind: \"string\" }, { name: \"background\", kind: \"boolean\" }],\n dryrun: [{ name: \"workflowid\", kind: \"string\", required: true }],\n loop: [{ name: \"loop\", kind: \"string\", required: true }],\n repeatuntil: [{ name: \"repeatuntil\", kind: \"string\", required: true }],\n whileloop: [{ name: \"whileloop\", kind: \"string\", required: true }],\n foreach: [{ name: \"foreach\", kind: \"string\", required: true }],\n parallel: [{ name: \"parallel\", kind: \"string\", required: true }],\n trycatch: [{ name: \"trycatch\", kind: \"string\", required: true }],\n};\n\n/** Classifies one action kind into its palette category: the ten trigger kinds, the eight control flow kinds, the wait family, the variable family and everything else an action. */\nfunction stepcategory(kind: string): palettecategory {\n if (triggerkinds.includes(kind)) return \"triggers\";\n if (controlflowkinds.includes(kind)) return \"controlflow\";\n if (kind.startsWith(\"wait\") || kind === \"spawait\" || kind === \"delay\") return \"waits\";\n if (kind === \"compute\" || kind === \"extractvars\" || kind === \"savetemplate\") return \"variables\";\n return \"actions\";\n}\n\n/** Builds the step library over every reviewed action kind the policy table knows, grouped by category with the documented option schema of the kinds that carry one. */\nexport function buildsteplibrary(kinds: string[]): steplibraryentry[] {\n return [...new Set(kinds)].sort().map(kind => ({ kind, category: stepcategory(kind), optionschema: optionschemas[kind] ?? [] }));\n}\n\n/** The row height every canvas node occupies; the layout stacks steps top to bottom and block columns side by side. */\nconst noderowheight = 96;\n\n/** The column width of one block container on the canvas. */\nconst blockcolumnwidth = 280;\n\n/** The x origin of the main column of the canvas. */\nconst canvasoriginx = 40;\n\n/** Strips the undo and redo stacks of one model so a snapshot never carries nested history. */\nfunction snapshotof(model: editormodel): editormodel {\n const { undo, redo, dirty, ...rest } = model;\n void undo; void redo; void dirty;\n return { ...rest, dirty: true };\n}\n\n/** Pushes one edit onto the undo stack and clears the redo stack; every canvas edit routes through here. */\nfunction withundo(model: editormodel, next: editormodel): editormodel {\n const undo = [...(model.undo ?? []), snapshotof(model)];\n const { redo, ...rest } = next;\n void redo;\n return { ...rest, dirty: true, undo };\n}\n\n/** Returns the id of one canvas node: the explicit node id, the step id or the invoked block name. */\nfunction nodeidof(node: editornode): string {\n return node.id ?? (node.step !== undefined ? node.step.id : node.invocation !== undefined ? node.invocation.block : \"\");\n}\n\n/** Computes the layout width and height the nodes of one model occupy. */\nfunction layoutsizeof(nodes: editornode[]): { width: number; height: number } {\n const width = Math.max(640, ...nodes.map(node => node.x + blockcolumnwidth)) + 40;\n const height = Math.max(480, ...nodes.map(node => node.y + noderowheight)) + 40;\n return { width, height };\n}\n\n/** Converts one composed workflow record into the canvas model: one node per top level step, one invocation node per contiguous block region of the expanded step list with a unique id even when one block is invoked many times, the bindings of every step lifted into typed edges and the layout stacked top to bottom with the block columns side by side. */\nexport function loadworkflow(record: workflowrecord, layout?: editorlayout): editormodel {\n const blocks = record.blocks.map(block => ({ ...block, steps: block.steps.map(entry => ({ ...entry })) }));\n const blockcolumn = (blockname: string): number => {\n const index = blocks.findIndex(block => block.name === blockname);\n return index < 0 ? canvasoriginx : canvasoriginx + (index + 1) * blockcolumnwidth;\n };\n const invocationcount = new Map<string, number>();\n const nodes: editornode[] = [];\n const edges: editoredge[] = [];\n let index = 0;\n while (index < record.steps.length) {\n const step = record.steps[index] as workflowstep;\n for (const binding of step.bindings ?? []) edges.push({ from: binding.stepid, to: step.id, variable: binding.variable, kind: binding.kind, ...(binding.path !== undefined ? { path: binding.path } : {}) });\n if (step.block === undefined) {\n const { bindings, block, params, ...rest } = step;\n void bindings; void block; void params;\n nodes.push({ step: { ...rest }, x: canvasoriginx, y: 60 + nodes.length * noderowheight });\n index += 1;\n continue;\n }\n const blockname = step.block;\n let end = index;\n while (end < record.steps.length && (record.steps[end] as workflowstep).block === blockname) end += 1;\n const region = record.steps.slice(index, end) as workflowstep[];\n const count = (invocationcount.get(blockname) ?? 0) + 1;\n invocationcount.set(blockname, count);\n const params = region.flatMap(entry => entry.params ?? []);\n nodes.push({ id: count === 1 ? blockname : `${blockname}${count}`, invocation: { block: blockname, label: blockname, ...(params.length > 0 ? { params: params.map(param => ({ ...param })) } : {}) }, x: blockcolumn(blockname), y: 60 + nodes.length * noderowheight });\n index = end;\n }\n const size = layouttypeof(nodes, layout);\n const model: editormodel = { workflowid: record.id, name: record.name, version: record.version, origins: [...record.origins], nodes, edges, blocks, layout: size, minimap: emptyminimap(), dirty: false };\n return { ...model, minimap: renderminimap(model).minimap };\n}\n\n/** Merges one explicit layout with the computed node bounds so a reopened canvas keeps its size while new nodes stay visible. */\nfunction layouttypeof(nodes: editornode[], layout?: editorlayout): editorlayout {\n const size = layoutsizeof(nodes);\n if (!layout) return { width: size.width, height: size.height, viewportx: 0, viewporty: 0, zoom: 1 };\n return { width: Math.max(size.width, layout.width), height: Math.max(size.height, layout.height), viewportx: layout.viewportx, viewporty: layout.viewporty, zoom: layout.zoom };\n}\n\n/** Builds the empty mini map of a model before the first projection. */\nfunction emptyminimap(): minimapstate {\n return { width: 160, height: 100, scale: 0, zoom: 1, viewport: { x: 0, y: 0, width: 0, height: 0 } };\n}\n\n/** Validates the canvas model and converts it back into one composed workflow record: every node is a step or a block invocation, every edge links the output of an earlier node into a later node so no cycle forms, block child bindings stay inside their block and the composed record passes the full workflow grammar. */\nexport function saveworkflow(model: editormodel, input: { now: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): workflowrecord {\n if (typeof model.name !== \"string\" || !model.name.trim()) throw new Error(\"The workflow name must be a non-empty string.\");\n if (typeof model.version !== \"number\" || !Number.isInteger(model.version) || model.version < 1) throw new Error(\"The workflow version must be a positive integer.\");\n if (!Array.isArray(model.origins) || model.origins.length === 0) throw new Error(\"A workflow needs at least one granted HTTPS origin.\");\n const ids = new Set<string>();\n for (const node of model.nodes) {\n if ((node.step === undefined) === (node.invocation === undefined)) throw new Error(\"Every canvas node must be exactly one workflow step or one block invocation.\");\n const id = nodeidof(node);\n if (!id || ids.has(id)) throw new Error(`The canvas node id ${id || \"(empty)\"} must be unique.`);\n ids.add(id);\n }\n /** Walks the top level entries in execution order and maps every reachable step id onto its position so the edge check answers cycles. */\n const positionof = new Map<string, number>();\n let position = 0;\n for (const node of model.nodes) {\n if (node.step !== undefined) { positionof.set(node.step.id, position); position += 1; continue; }\n const block = model.blocks.find(entry => entry.name === node.invocation?.block);\n if (!block) throw new Error(`The block ${node.invocation?.block ?? \"\"} of the canvas has no definition.`);\n const walk = (entries: Array<workflowstep | blockinvocation>): void => {\n for (const entry of entries) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry)) { positionof.set(entry.id, position); position += 1; continue; }\n const nested = model.blocks.find(candidate => candidate.name === (entry as blockinvocation).block);\n if (!nested) throw new Error(`The block ${(entry as blockinvocation).block} of the canvas has no definition.`);\n walk(nested.steps);\n }\n };\n walk(block.steps);\n }\n for (const edge of model.edges) {\n if (!positionof.has(edge.from)) throw new Error(`The edge of ${edge.variable} references the unknown source step ${edge.from}.`);\n if (!positionof.has(edge.to)) throw new Error(`The edge of ${edge.variable} references the unknown target step ${edge.to}.`);\n if ((positionof.get(edge.from) as number) >= (positionof.get(edge.to) as number)) throw new Error(`The edge of ${edge.variable} runs backwards from ${edge.from} into ${edge.to} and would form a cycle.`);\n }\n /** Collects the bindings one step id receives from the canvas edges. */\n const bindingsof = (stepid: string): variablebinding[] => model.edges.filter(edge => edge.to === stepid).map(edge => ({ variable: edge.variable, kind: edge.kind, stepid: edge.from, ...(edge.path !== undefined ? { path: edge.path } : {}) }));\n const entries: Array<workflowstep | blockinvocation> = [];\n const attached = new Map<string, workflowstep[]>();\n for (const node of model.nodes) {\n if (node.invocation !== undefined) { entries.push({ ...node.invocation }); continue; }\n const step = node.step as workflowstep;\n const bindings = bindingsof(step.id);\n const { block, params, ...rest } = { ...step, ...(bindings.length > 0 ? { bindings } : {}) };\n void params;\n const carried: workflowstep = rest;\n if (block !== undefined) {\n if (!model.blocks.some(candidate => candidate.name === block)) throw new Error(`The step ${step.id} attaches to the unknown block ${block}.`);\n const list = attached.get(block) ?? [];\n list.push(carried);\n attached.set(block, list);\n continue;\n }\n entries.push(carried);\n }\n const blocks = model.blocks.map(block => {\n const snapped = attached.get(block.name) ?? [];\n const snappedids = new Set(snapped.map(step => step.id));\n const carried: Array<workflowstep | blockinvocation> = [];\n for (const entry of block.steps) {\n if (\"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && snappedids.has((entry as workflowstep).id)) continue;\n carried.push(entry);\n }\n const steps: Array<workflowstep | blockinvocation> = [...carried, ...snapped];\n const withbindings: Array<workflowstep | blockinvocation> = [];\n for (const entry of steps) {\n if (!(\"kind\" in entry && \"label\" in entry && !(\"block\" in entry))) { withbindings.push(entry); continue; }\n const bindings = bindingsof((entry as workflowstep).id);\n const { block: inner, params, ...rest } = { ...(entry as workflowstep), ...(bindings.length > 0 ? { bindings } : {}) };\n void inner; void params;\n withbindings.push(rest as workflowstep);\n }\n return { ...block, steps: withbindings };\n });\n const composed = composeworkflow({ id: model.workflowid, name: model.name, version: model.version, origins: [...model.origins], steps: entries, blocks: blocks.map(block => ({ ...block })), now: input.now, ...(input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {}), ...(input.riskof !== undefined ? { riskof: input.riskof } : {}) });\n const checked = validateworkflow(composed, input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {});\n if (!checked.allowed) throw new Error(checked.reason ?? \"The canvas model failed the workflow grammar.\");\n return composed;\n}\n\n/** Attaches one step to a block boundary: the dragged position snaps onto the reviewed grid and the nearest block column attaches the step into that block while the main column detaches it. */\nexport function snapnode(model: editormodel, nodeid: string, x: number, y: number, grid = 20): editormodel {\n if (!Number.isFinite(grid) || grid <= 0) throw new Error(\"The snap grid must be a positive number.\");\n const index = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (index < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n const node = model.nodes[index] as editornode;\n if (node.step === undefined) throw new Error(\"A block invocation node attaches through its own definition, not through snapping.\");\n const snappedx = Math.round(x / grid) * grid;\n const snappedy = Math.round(y / grid) * grid;\n let attached: string | undefined;\n for (const [blockindex, block] of model.blocks.entries()) {\n const columnx = canvasoriginx + (blockindex + 1) * blockcolumnwidth;\n if (Math.abs(snappedx - columnx) <= blockcolumnwidth / 2) attached = block.name;\n }\n const { block: priorblock, ...rest } = node.step;\n void priorblock;\n const step: workflowstep = { ...rest, ...(attached !== undefined ? { block: attached } : {}) };\n const nodes = model.nodes.map((candidate, position) => position === index ? { step, x: snappedx, y: snappedy } : candidate);\n const size = layouttypeof(nodes, model.layout);\n const next: editormodel = { ...model, nodes, layout: size };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Persists one drag and drop ordering: the node moves to the reviewed index of the top level list while the edges stay attached to their step ids. */\nexport function reordersteps(model: editormodel, nodeid: string, index: number): editormodel {\n const current = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (current < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n if (!Number.isInteger(index) || index < 0 || index > model.nodes.length - 1) throw new Error(\"The reorder index must address an existing position of the canvas list.\");\n const nodes = [...model.nodes];\n const [moved] = nodes.splice(current, 1);\n if (!moved) throw new Error(\"The reordered canvas node vanished.\");\n nodes.splice(index, 0, moved);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Moves many selected steps into a new block: the definition collects the selected steps in their current order and one invocation node replaces the first selected position. */\nexport function groupselect(model: editormodel, nodeids: string[], blockname: string): editormodel {\n if (!/^[a-z][a-z0-9]*$/.test(blockname)) throw new Error(\"The block name must be a unique lowercase word.\");\n if (model.blocks.some(block => block.name === blockname)) throw new Error(`The block name ${blockname} already exists on the canvas.`);\n const selected = nodeids.map(id => {\n const node = model.nodes.find(candidate => nodeidof(candidate) === id);\n if (!node || node.step === undefined) throw new Error(`The grouping selection must address step nodes; ${id} is not one.`);\n return node;\n });\n if (selected.length === 0) throw new Error(\"The grouping selection needs at least one step node.\");\n const steps = selected.map(node => node.step as workflowstep);\n const blocks = [...model.blocks, { name: blockname, label: blockname, steps: steps.map(step => ({ ...step })) }];\n const firstindex = model.nodes.findIndex(node => nodeidof(node) === nodeids[0] as string);\n const invocationnode: editornode = { id: blockname, invocation: { block: blockname, label: blockname }, x: (selected[0] as editornode).x, y: (selected[0] as editornode).y };\n const nodes: editornode[] = [];\n model.nodes.forEach((node, index) => {\n if (nodeids.includes(nodeidof(node))) {\n if (index === firstindex) nodes.push(invocationnode);\n return;\n }\n nodes.push(node);\n });\n const next: editormodel = { ...model, nodes, blocks };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Inserts one shared step template with its nested parameters: the template step becomes a canvas node at the reviewed index and the parameters ride with the step into its block scope. */\nexport function expandtemplate(model: editormodel, template: steptemplate, params: nestedparam[] = [], index?: number): editormodel {\n const parsed = steptemplateof(template);\n if (!parsed) throw new Error(\"The template does not carry one reviewed workflow step.\");\n let id = parsed.step.id;\n let suffix = 2;\n const taken = new Set(model.nodes.map(node => nodeidof(node)));\n while (taken.has(id)) { id = `${parsed.step.id}${suffix}`; suffix += 1; }\n const step: workflowstep = { ...parsed.step, id, ...(params.length > 0 ? { params: params.map(param => ({ ...param })) } : {}) };\n const position = index !== undefined && Number.isInteger(index) && index >= 0 && index <= model.nodes.length ? index : model.nodes.length;\n const nodes = [...model.nodes.slice(0, position), { step, x: canvasoriginx, y: 60 + position * noderowheight }, ...model.nodes.slice(position)];\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Inserts one new step node onto the canvas at the reviewed index: the palette and the step library drop their kinds through here so every insertion rides the undo stack. */\nexport function addnode(model: editormodel, step: workflowstep, index?: number): editormodel {\n const normalized = workflowstepof(step);\n if (!normalized) throw new Error(\"The canvas insertion needs one reviewed workflow step.\");\n let id = normalized.id;\n let suffix = 2;\n const taken = new Set(model.nodes.map(node => nodeidof(node)));\n while (taken.has(id)) { id = `${normalized.id}${suffix}`; suffix += 1; }\n const position = index !== undefined && Number.isInteger(index) && index >= 0 && index <= model.nodes.length ? index : model.nodes.length;\n const nodes = [...model.nodes.slice(0, position), { step: { ...normalized, id }, x: canvasoriginx, y: 60 + position * noderowheight }, ...model.nodes.slice(position)];\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Replaces the payload of one step node of the canvas: the step inspector edits its target, value, options, expression and extract fields through here so every edit rides the undo stack. */\nexport function editstep(model: editormodel, step: workflowstep): editormodel {\n const normalized = workflowstepof(step);\n if (!normalized) throw new Error(\"The step inspector edit needs one reviewed workflow step.\");\n const index = model.nodes.findIndex(node => node.step?.id === normalized.id);\n if (index < 0) throw new Error(`No canvas step matches ${normalized.id}.`);\n const node = model.nodes[index] as editornode;\n const nodes = model.nodes.map((candidate, position) => position === index ? { step: { ...normalized, ...(node.step?.block !== undefined ? { block: node.step.block } : {}), ...(node.step?.breakpoint === true ? { breakpoint: true } : {}) }, x: node.x, y: node.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Projects the full canvas into the mini map: the projection scale fits every node into the mini size and the viewport rectangle follows the layout viewport and zoom. */\nexport function renderminimap(model: editormodel, width = 160, height = 100): { minimap: minimapstate; nodes: Array<{ id: string; x: number; y: number }> } {\n if (!Number.isFinite(width) || width <= 0 || !Number.isFinite(height) || height <= 0) throw new Error(\"The mini map size must be positive.\");\n const canvaswidth = Math.max(1, model.layout.width);\n const canvasheight = Math.max(1, model.layout.height);\n const scale = Math.min(width / canvaswidth, height / canvasheight);\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n const visiblewidth = canvaswidth / zoom;\n const visibleheight = canvasheight / zoom;\n const viewport = {\n x: Math.max(0, Math.min(model.layout.viewportx, canvaswidth)) * scale,\n y: Math.max(0, Math.min(model.layout.viewporty, canvasheight)) * scale,\n width: visiblewidth * scale,\n height: visibleheight * scale,\n };\n const nodes = model.nodes.map(node => ({ id: nodeidof(node), x: node.x * scale, y: node.y * scale }));\n return { minimap: { width, height, scale, zoom, viewport }, nodes };\n}\n\n/** Jumps the canvas to a clicked mini map region: the click converts back into canvas coordinates and the viewport centers on it inside the canvas bounds. */\nexport function minimapfocus(model: editormodel, x: number, y: number, width = 160, height = 100): editormodel {\n const projection = renderminimap(model, width, height);\n if (projection.minimap.scale <= 0) return model;\n const canvasx = x / projection.minimap.scale;\n const canvasy = y / projection.minimap.scale;\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n const visiblewidth = model.layout.width / zoom;\n const visibleheight = model.layout.height / zoom;\n const viewportx = Math.max(0, Math.min(canvasx - visiblewidth / 2, Math.max(0, model.layout.width - visiblewidth)));\n const viewporty = Math.max(0, Math.min(canvasy - visibleheight / 2, Math.max(0, model.layout.height - visibleheight)));\n const next: editormodel = { ...model, layout: { ...model.layout, viewportx, viewporty } };\n return { ...next, minimap: renderminimap(next).minimap };\n}\n\n/** Sets the canvas zoom to any positive user value with no ceiling while the step labels compensate so they stay readable at every zoom level: the returned label scale grows the labels relative to the canvas once the zoom shrinks below the readable floor. */\nexport function zoomcanvas(model: editormodel, zoom: number): { model: editormodel; labelscale: number } {\n if (!Number.isFinite(zoom) || zoom <= 0) throw new Error(\"The canvas zoom must be a positive number with no code ceiling.\");\n const next: editormodel = { ...model, layout: { ...model.layout, zoom } };\n const labelscale = zoom < 1 ? 1 / zoom : 1;\n return { model: { ...next, minimap: renderminimap(next).minimap }, labelscale };\n}\n\n/** Finds steps by label, kind or variable name: the search answers the matching nodes with the reasons they matched, case insensitive. */\nexport function searchsteps(model: editormodel, query: string): Array<{ id: string; label: string; kind: string; matched: string[] }> {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n const results: Array<{ id: string; label: string; kind: string; matched: string[] }> = [];\n for (const node of model.nodes) {\n if (node.step === undefined) continue;\n const matched: string[] = [];\n if (node.step.label.toLowerCase().includes(needle)) matched.push(\"label\");\n if (node.step.kind.toLowerCase().includes(needle)) matched.push(\"kind\");\n const variables = [\n ...model.edges.filter(edge => edge.to === node.step?.id || edge.from === node.step?.id).map(edge => edge.variable),\n ...(node.step.expression !== undefined ? [node.step.expression.result] : []),\n ...(node.step.extract !== undefined ? node.step.extract.groups : []),\n ];\n if (variables.some(name => name.toLowerCase().includes(needle))) matched.push(\"variable\");\n if (matched.length > 0) results.push({ id: node.step.id, label: node.step.label, kind: node.step.kind, matched });\n }\n return results;\n}\n\n/** Toggles the breakpoint marker of one step for editor debugging; a debug run pauses right before a marked step, and the marker rides the steps inside block definitions too. */\nexport function markbreakpoint(model: editormodel, stepid: string): editormodel {\n const toggle = (step: workflowstep): workflowstep => {\n const { breakpoint, ...rest } = step;\n void breakpoint;\n return breakpoint === true ? rest : { ...rest, breakpoint: true };\n };\n const index = model.nodes.findIndex(node => node.step?.id === stepid);\n if (index >= 0) {\n const node = model.nodes[index] as editornode;\n const step = node.step as workflowstep;\n const nodes = model.nodes.map((candidate, position) => position === index ? { step: toggle(step), x: candidate.x, y: candidate.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n }\n const blocks = model.blocks.map(block => {\n const stepindex = block.steps.findIndex(entry => \"kind\" in entry && \"label\" in entry && !(\"block\" in entry) && (entry as workflowstep).id === stepid);\n if (stepindex < 0) return block;\n const steps = block.steps.map((entry, position) => position === stepindex ? toggle(entry as workflowstep) : entry);\n return { ...block, steps };\n });\n if (blocks.every((block, position) => block === model.blocks[position])) throw new Error(`No canvas step matches ${stepid}.`);\n const next: editormodel = { ...model, blocks };\n return withundo(model, next);\n}\n\n/** Plans one debug run segment: the run executes the steps from the cursor up to the step before the next breakpoint, pauses at the breakpoint step id and reports the steps remaining after it; a run without breakpoints runs to the end. */\nexport function runtobreakpoint(input: { record: workflowrecord; cursor?: number; breakpoints: string[] }): { until: number; pausat: string | undefined; remaining: number } {\n const cursor = input.cursor !== undefined && Number.isInteger(input.cursor) && input.cursor >= 0 ? input.cursor : 0;\n const marked = new Set(input.breakpoints);\n for (let index = cursor; index < input.record.steps.length; index += 1) {\n const step = input.record.steps[index] as workflowstep;\n if (step.breakpoint === true || marked.has(step.id)) {\n return { until: index, pausat: step.id, remaining: input.record.steps.length - index };\n }\n }\n return { until: input.record.steps.length, pausat: undefined, remaining: 0 };\n}\n\n/** Compares two workflow versions: the steps the newer version added, removed and changed with the field names that changed. */\nexport function diffversions(from: workflowrecord, to: workflowrecord, now: number): versiondiff {\n const fromsteps = new Map(from.steps.map(step => [step.id, step]));\n const tosteps = new Map(to.steps.map(step => [step.id, step]));\n const added: versiondiff[\"added\"] = [];\n const removed: versiondiff[\"removed\"] = [];\n const changed: versiondiff[\"changed\"] = [];\n for (const step of to.steps) {\n const prior = fromsteps.get(step.id);\n if (!prior) { added.push({ stepid: step.id, kind: step.kind, label: step.label }); continue; }\n const changes: string[] = [];\n if (prior.label !== step.label) changes.push(\"label\");\n if (prior.kind !== step.kind) changes.push(\"kind\");\n if (prior.target !== step.target) changes.push(\"target\");\n if (prior.value !== step.value) changes.push(\"value\");\n if (prior.options !== step.options) changes.push(\"options\");\n if (JSON.stringify(prior.expression) !== JSON.stringify(step.expression)) changes.push(\"expression\");\n if (JSON.stringify(prior.extract) !== JSON.stringify(step.extract)) changes.push(\"extract\");\n if (JSON.stringify(prior.bindings) !== JSON.stringify(step.bindings)) changes.push(\"bindings\");\n if (changes.length > 0) changed.push({ stepid: step.id, kind: step.kind, label: step.label, changes });\n }\n for (const step of from.steps) {\n if (!tosteps.has(step.id)) removed.push({ stepid: step.id, kind: step.kind, label: step.label });\n }\n return { workflowid: to.id, from: from.version, to: to.version, added, removed, changed, at: now };\n}\n\n/** Serializes one workflow record with its version metadata into a workflow file of the reviewed json or yaml format. */\nexport function exportworkflow(record: workflowrecord, format: exportformat, note?: string, now?: number): { format: exportformat; contents: string; file: workflowfile } {\n const file: workflowfile = { format: workflowfileversion, exportedat: now ?? Date.now(), workflow: record, ...(note !== undefined && note.trim() !== \"\" ? { note } : {}), templates: [] };\n return { format, contents: serializefile(file, format), file };\n}\n\n/** Packs one workflow with its shared step templates into a single shareable file so a whole library travels together. */\nexport function shareworkflow(record: workflowrecord, templates: steptemplate[], format: exportformat, note?: string, now?: number): { format: exportformat; contents: string; file: workflowfile } {\n const file: workflowfile = { format: workflowfileversion, exportedat: now ?? Date.now(), workflow: record, ...(note !== undefined && note.trim() !== \"\" ? { note } : {}), templates: templates.map(template => ({ ...template })) };\n return { format, contents: serializefile(file, format), file };\n}\n\n/** Validates and loads one workflow file: the format version must match, the workflow must compose through the full grammar and every packed template must normalize; the loaded record grades unreviewed until the user approves it. */\nexport function importworkflow(input: { contents: string; format?: exportformat; now?: number; kindallowed?: (kind: string) => boolean; riskof?: (kind: string) => actionrisk }): { record: workflowrecord; templates: steptemplate[]; file: workflowfile } {\n const format = input.format ?? (input.contents.trimStart().startsWith(\"{\") ? \"json\" : \"yaml\");\n const parsed = parsefile(input.contents, format);\n if (parsed.format !== workflowfileversion) throw new Error(`The workflow file format ${String(parsed.format)} is not the reviewed format ${workflowfileversion}.`);\n const candidate = parsed.workflow;\n if (!candidate || typeof candidate !== \"object\" || Array.isArray(candidate)) throw new Error(\"The workflow file carries no workflow record.\");\n const fields = candidate as unknown as Record<string, unknown>;\n const stepsvalue = fields.steps;\n if (!Array.isArray(stepsvalue) || stepsvalue.length === 0) throw new Error(\"An imported workflow needs at least one step.\");\n const steps: Array<workflowstep | blockinvocation> = [];\n for (const entry of stepsvalue) {\n const step = workflowstepof(entry);\n if (step) { steps.push(step); continue; }\n throw new Error(\"Every imported workflow entry must be a reviewed step.\");\n }\n const composed = composeworkflow({\n id: typeof fields.id === \"string\" && fields.id.trim() !== \"\" ? fields.id : crypto.randomUUID(),\n name: typeof fields.name === \"string\" ? fields.name : \"\",\n version: typeof fields.version === \"number\" ? fields.version : 1,\n origins: Array.isArray(fields.origins) ? fields.origins.filter((origin): origin is string => typeof origin === \"string\") : [],\n steps,\n now: input.now ?? Date.now(),\n ...(input.kindallowed !== undefined ? { kindallowed: input.kindallowed } : {}),\n ...(input.riskof !== undefined ? { riskof: input.riskof } : {}),\n });\n const templatesvalue = parsed.templates;\n if (templatesvalue !== undefined && !Array.isArray(templatesvalue)) throw new Error(\"The packed templates of the workflow file must be a list.\");\n const templates: steptemplate[] = [];\n for (const entry of templatesvalue ?? []) {\n const template = steptemplateof(entry);\n if (!template) throw new Error(\"A packed template of the workflow file does not carry one reviewed step.\");\n templates.push(template);\n }\n const record: workflowrecord = { ...composed, reviewstate: \"pending\" };\n return { record, templates, file: { ...parsed, workflow: record } };\n}\n\n/** Wires one nested parameter into a block invocation of the canvas: the parameter replaces a same named one and the default binds into the block scope once the run opens it. */\nexport function bindparam(model: editormodel, blockname: string, param: nestedparam): editormodel {\n if (!/^[a-z][a-z0-9]*$/.test(param.name)) throw new Error(\"The nested parameter name must be a lowercase word.\");\n const index = model.nodes.findIndex(node => node.invocation?.block === blockname);\n if (index < 0) throw new Error(`No block invocation of ${blockname} sits on the canvas.`);\n const node = model.nodes[index] as editornode;\n const invocation = node.invocation as blockinvocation;\n const params = [...(invocation.params ?? []).filter(existing => existing.name !== param.name), { ...param }];\n const nodes = model.nodes.map((candidate, position) => position === index ? { invocation: { ...invocation, params }, x: candidate.x, y: candidate.y } : candidate);\n const next: editormodel = { ...model, nodes };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Answers whether one origin matches a reviewed override pattern: an exact origin or a `*` subdomain glob of an https origin. */\nfunction originmatches(pattern: string, origin: string): boolean {\n if (pattern === origin) return true;\n const glob = pattern.replace(/\\./g, \"\\\\.\").replace(/\\*/g, \"[^.]+\");\n if (!glob.startsWith(\"https://\")) return false;\n return new RegExp(`^${glob}$`).test(origin);\n}\n\n/** Applies one per site policy override to a workflow: the deltas adjust only the reviewed knobs \u2014 loop bounds, step and run timeouts, element wait timeouts and delay bases \u2014 of the steps whose workflow origins match the override pattern. */\nexport function applyoverride(record: workflowrecord, override: siteoverride): workflowrecord {\n const matching = record.origins.filter(origin => originmatches(override.pattern, origin));\n if (matching.length === 0) throw new Error(`The override pattern ${override.pattern} matches none of the workflow origins ${record.origins.join(\", \")}.`);\n const knobs = new Set([\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"]);\n for (const knob of Object.keys(override.deltas)) {\n if (!knobs.has(knob)) throw new Error(`The override knob ${knob} is not one of the reviewed knobs: ${[...knobs].join(\", \")}.`);\n if (typeof override.deltas[knob] !== \"number\" || !Number.isFinite(override.deltas[knob]) || override.deltas[knob] as number <= 0) throw new Error(`The override delta of ${knob} must be a positive number with no code ceiling.`);\n }\n const apply = (step: workflowstep): workflowstep => {\n if (Object.keys(override.deltas).length === 0) return step;\n let payload: Record<string, unknown> = {};\n try { payload = step.options !== undefined ? JSON.parse(step.options) as Record<string, unknown> : {}; } catch { payload = {}; }\n const bodyof = (key: string): Record<string, unknown> => payload[key] !== undefined && typeof payload[key] === \"object\" && !Array.isArray(payload[key]) ? payload[key] as Record<string, unknown> : {};\n if (override.deltas.loopbound !== undefined && [\"loop\", \"repeatuntil\", \"whileloop\"].includes(step.kind)) {\n const body = bodyof(step.kind);\n body.bound = override.deltas.loopbound;\n payload[step.kind] = body;\n }\n if ((override.deltas.stepms !== undefined || override.deltas.runms !== undefined) && step.kind === \"trycatch\") {\n const body = bodyof(\"trycatch\");\n const timeout = body.timeout !== undefined && typeof body.timeout === \"object\" && !Array.isArray(body.timeout) ? body.timeout as Record<string, unknown> : {};\n if (override.deltas.stepms !== undefined) timeout.stepms = override.deltas.stepms;\n if (override.deltas.runms !== undefined) timeout.runms = override.deltas.runms;\n body.timeout = timeout;\n payload.trycatch = body;\n }\n if (override.deltas.waitms !== undefined && step.kind === \"waitelement\") {\n payload.timeout = override.deltas.waitms;\n }\n if (override.deltas.delaybase !== undefined && step.kind === \"delay\") {\n payload.base = override.deltas.delaybase;\n }\n const changed = Object.keys(payload).length > 0;\n return changed ? { ...step, options: JSON.stringify(payload) } : step;\n };\n return { ...record, steps: record.steps.map(apply) };\n}\n\n/** Wires one typed binding edge from the output socket of an earlier step into the input socket of a later step; a backwards edge refuses so no cycle forms. */\nexport function addedge(model: editormodel, edge: editoredge): editormodel {\n const from = model.nodes.findIndex(node => nodeidof(node) === edge.from);\n const to = model.nodes.findIndex(node => nodeidof(node) === edge.to);\n if (from < 0) throw new Error(`The canvas edge references the unknown source step ${edge.from}.`);\n if (to < 0) throw new Error(`The canvas edge references the unknown target step ${edge.to}.`);\n if (from >= to) throw new Error(`The canvas edge of ${edge.variable} would run backwards from ${edge.from} into ${edge.to} and form a cycle.`);\n if (!/^[a-z][a-z0-9]*$/.test(edge.variable)) throw new Error(\"The bound variable name must be a lowercase word.\");\n const edges = [...model.edges.filter(candidate => !(candidate.from === edge.from && candidate.to === edge.to && candidate.variable === edge.variable)), { ...edge, ...(edge.path !== undefined ? { path: edge.path } : {}) }];\n const next: editormodel = { ...model, edges };\n return withundo(model, next);\n}\n\n/** Removes one typed binding edge of the canvas by its source, target and variable. */\nexport function removeedge(model: editormodel, from: string, to: string, variable: string): editormodel {\n const edges = model.edges.filter(candidate => !(candidate.from === from && candidate.to === to && candidate.variable === variable));\n if (edges.length === model.edges.length) throw new Error(`No canvas edge of ${variable} links ${from} into ${to}.`);\n const next: editormodel = { ...model, edges };\n return withundo(model, next);\n}\n\n/** Removes one canvas node with every edge attached to it; the undo stack keeps the removal reversible. */\nexport function removenode(model: editormodel, nodeid: string): editormodel {\n const index = model.nodes.findIndex(node => nodeidof(node) === nodeid);\n if (index < 0) throw new Error(`No canvas node matches ${nodeid}.`);\n const nodes = model.nodes.filter((_, position) => position !== index);\n const edges = model.edges.filter(edge => edge.from !== nodeid && edge.to !== nodeid);\n const next: editormodel = { ...model, nodes, edges };\n return withundo(model, { ...next, minimap: renderminimap(next).minimap });\n}\n\n/** Steps one canvas edit back: the last undo snapshot becomes the current model and the edited model waits on the redo stack. */\nexport function undoedit(model: editormodel): editormodel {\n const undo = model.undo ?? [];\n if (undo.length === 0) return model;\n const previous = undo[undo.length - 1] as editormodel;\n const current = snapshotof(model);\n return { ...previous, undo: undo.slice(0, -1), redo: [...(model.redo ?? []), current] };\n}\n\n/** Steps one canvas edit forward again after an undo: the newest redo snapshot returns as the current model. */\nexport function redoedit(model: editormodel): editormodel {\n const redo = model.redo ?? [];\n if (redo.length === 0) return model;\n const next = redo[redo.length - 1] as editormodel;\n const current = snapshotof(model);\n return { ...next, redo: redo.slice(0, -1), undo: [...(model.undo ?? []), current] };\n}\n\n/** Serializes one workflow file into the reviewed json or yaml format; the yaml writer emits the documented subset of quoted scalars, mappings and block sequences the reader parses back. */\nfunction serializefile(file: workflowfile, format: exportformat): string {\n if (format === \"json\") return JSON.stringify(file, null, 2);\n return yamlvalue(file, 0).join(\"\\n\") + \"\\n\";\n}\n\n/** Parses one workflow file from json or the documented yaml subset; every structural violation refuses the import. */\nfunction parsefile(contents: string, format: exportformat): workflowfile {\n if (format === \"json\") {\n const parsed: unknown = JSON.parse(contents);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"The workflow file is not a json object.\");\n return parsed as workflowfile;\n }\n const lines = contents.split(/\\r?\\n/).map(line => line.replace(/\\t/g, \" \")).filter(line => line.trim() !== \"\" && !line.trim().startsWith(\"#\"));\n if (lines.length === 0) throw new Error(\"The yaml workflow file is empty.\");\n const { value, next } = yamlblock(lines, 0, indentof(lines[0] as string));\n if (next < lines.length) throw new Error(\"The yaml workflow file carries content outside the documented subset.\");\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"The yaml workflow file is not a mapping.\");\n return value as workflowfile;\n}\n\n/** Measures the leading spaces of one line. */\nfunction indentof(line: string): number {\n const match = /^ */.exec(line);\n return match ? match[0].length : 0;\n}\n\n/** Renders one scalar of the yaml subset: strings quote with json escaping so no scalar ever confuses the reader. */\nfunction yamlscalar(value: unknown): string {\n if (value === null || value === undefined) return \"null\";\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n return JSON.stringify(String(value));\n}\n\n/** Renders any value of a workflow file into yaml lines of the documented subset. */\nfunction yamlvalue(value: unknown, indent: number): string[] {\n const pad = \" \".repeat(indent);\n if (value === null || value === undefined || typeof value !== \"object\") return [`${pad}${yamlscalar(value)}`];\n if (Array.isArray(value)) {\n if (value.length === 0) return [`${pad}[]`];\n const lines: string[] = [];\n for (const item of value) {\n if (item !== null && typeof item === \"object\") {\n lines.push(`${pad}-`);\n lines.push(...yamlvalue(item, indent + 2));\n } else {\n lines.push(`${pad}- ${yamlscalar(item)}`);\n }\n }\n return lines;\n }\n const entries = Object.entries(value as Record<string, unknown>);\n if (entries.length === 0) return [`${pad}{}`];\n const lines: string[] = [];\n for (const [key, entry] of entries) {\n if (entry !== null && typeof entry === \"object\") {\n if (Array.isArray(entry) && entry.length === 0) { lines.push(`${pad}${key}: []`); continue; }\n if (!Array.isArray(entry) && Object.keys(entry as Record<string, unknown>).length === 0) { lines.push(`${pad}${key}: {}`); continue; }\n lines.push(`${pad}${key}:`);\n lines.push(...yamlvalue(entry, indent + 2));\n } else {\n lines.push(`${pad}${key}: ${yamlscalar(entry)}`);\n }\n }\n return lines;\n}\n\n/** Parses one yaml block of the documented subset into its value starting at the reviewed line index and indentation. */\nfunction yamlblock(lines: string[], start: number, indent: number): { value: unknown; next: number } {\n const first = lines[start] as string;\n if (/^\\s*-\\s/.test(first) || /^\\s*-$/.test(first)) {\n const items: unknown[] = [];\n let index = start;\n while (index < lines.length) {\n const line = lines[index] as string;\n if (indentof(line) !== indent || !/^\\s*-\\s?/.test(line)) break;\n const rest = line.slice(indent + 1).trim();\n if (rest !== \"\") {\n items.push(yamlscalarvalue(rest));\n index += 1;\n continue;\n }\n const nested = yamlblock(lines, index + 1, indent + 2);\n items.push(nested.value);\n index = nested.next;\n }\n return { value: items, next: index };\n }\n const mapping: Record<string, unknown> = {};\n let index = start;\n while (index < lines.length) {\n const line = lines[index] as string;\n if (indentof(line) !== indent) break;\n const match = /^([A-Za-z][A-Za-z0-9]*):(?:\\s(.*))?$/.exec(line.slice(indent));\n if (!match) break;\n const key = match[1] as string;\n const rest = match[2];\n if (rest !== undefined && rest !== \"\") {\n if (rest === \"[]\" ) { mapping[key] = []; index += 1; continue; }\n if (rest === \"{}\") { mapping[key] = {}; index += 1; continue; }\n mapping[key] = yamlscalarvalue(rest);\n index += 1;\n continue;\n }\n const nested = yamlblock(lines, index + 1, indent + 2);\n mapping[key] = nested.value;\n index = nested.next;\n }\n if (index === start) throw new Error(\"The yaml workflow file left the documented subset.\");\n return { value: mapping, next: index };\n}\n\n/** Parses one quoted, numeric, boolean or null scalar of the yaml subset. */\nfunction yamlscalarvalue(text: string): unknown {\n if (text.startsWith(\"\\\"\")) {\n const parsed: unknown = JSON.parse(text);\n return typeof parsed === \"string\" ? parsed : text;\n }\n if (text === \"true\") return true;\n if (text === \"false\") return false;\n if (text === \"null\") return null;\n if (/^-?\\d+(?:\\.\\d+)?$/.test(text)) return Number(text);\n return text;\n}\n", "import type { tabgrouprecord, tablayout, tabquery, tabwatchevent, toolstep } from \"../types.js\";\nimport { parseoptions } from \"../policy.js\";\nimport { assigntasktab, tasktabs } from \"../progress.js\";\nimport type { planprogress } from \"../types.js\";\n\n/**\n * Tabs and windows command logics for reviewed steps.\n * Every correlated rule for tab queries, clone detection, group membership, layouts, snapshots, watchers, badges, discard candidates, switcher order, zoom steps and the task tab budget lives in this file.\n */\n\n/** One serializable live tab shape resolved against the browser tab set. */\nexport interface tabshape {\n tabid: number;\n url: string;\n title: string;\n index: number;\n windowid: number;\n active: boolean;\n pinned: boolean;\n audible: boolean;\n muted: boolean;\n discarded: boolean;\n}\n\n/** One serializable live window shape with bounds, state and profile kind. */\nexport interface windowshape {\n windowid: number;\n left: number;\n top: number;\n width: number;\n height: number;\n state: \"normal\" | \"maximized\" | \"minimized\" | \"fullscreen\";\n incognito: boolean;\n focused: boolean;\n}\n\n/** Reads the reviewed tabquery of a tabs and windows command step; null when the step reviews none. */\nexport function parsetabquery(step: toolstep): tabquery | null {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const value = options.tabquery;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const query = value as Record<string, unknown>;\n return {\n ...(typeof query.url === \"string\" && query.url ? { url: query.url } : {}),\n ...(typeof query.title === \"string\" && query.title ? { title: query.title } : {}),\n ...(typeof query.id === \"number\" && Number.isInteger(query.id) && query.id >= 0 ? { id: query.id } : {}),\n ...(typeof query.pattern === \"string\" && query.pattern ? { pattern: query.pattern } : {}),\n };\n}\n\n/** Matches one reviewed wildcard pattern against a url; `*` spans one path segment and `**` spans any part. */\nexport function tabpatternmatches(pattern: string, url: string): boolean {\n const source = pattern.split(\"**\").map(part => part.split(\"*\").map(piece => piece.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"[^/]*\")).join(\".*\");\n return new RegExp(`^${source}$`).test(url);\n}\n\n/** Resolves one reviewed tabquery against the live tab set: every matcher that exists must hold. */\nexport function querymatches(query: tabquery, tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => {\n if (query.id !== undefined && tab.tabid !== query.id) return false;\n if (query.url !== undefined && tab.url !== query.url) return false;\n if (query.title !== undefined && !tab.title.toLowerCase().includes(query.title.toLowerCase())) return false;\n if (query.pattern !== undefined && !tabpatternmatches(query.pattern, tab.url)) return false;\n return true;\n });\n}\n\n/** Normalizes one url for clone comparison by dropping the fragment and trailing slashes. */\nexport function normalizedtaburl(url: string): string {\n let normalized = url;\n const hash = normalized.indexOf(\"#\");\n if (hash >= 0) normalized = normalized.slice(0, hash);\n while (normalized.length > 1 && normalized.endsWith(\"/\")) normalized = normalized.slice(0, -1);\n return normalized;\n}\n\n/** One clone warning: a normalized url shared by more than one open tab. */\nexport interface clonewarning {\n url: string;\n tabids: number[];\n}\n\n/** Detects duplicate tabs by normalized url comparison and returns every url held by more than one tab. */\nexport function clonetabs(tabs: tabshape[]): clonewarning[] {\n const groups = new Map<string, number[]>();\n for (const tab of tabs) {\n if (!tab.url) continue;\n const key = normalizedtaburl(tab.url);\n groups.set(key, [...(groups.get(key) ?? []), tab.tabid]);\n }\n return [...groups.entries()].filter(([, tabids]) => tabids.length > 1).map(([url, tabids]) => ({ url, tabids }));\n}\n\n/** Searches across open tabs by title and url, case insensitive, returning matches in live order. */\nexport function searchtabmatches(tabs: tabshape[], text: string): tabshape[] {\n const needle = text.trim().toLowerCase();\n if (!needle) return [];\n return tabs.filter(tab => tab.title.toLowerCase().includes(needle) || tab.url.toLowerCase().includes(needle));\n}\n\n/** Lists the tabs that are playing audio: audible or muted but still playing. */\nexport function audiotabs(tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => tab.audible || (tab.muted && tab.audible));\n}\n\n/** Returns the inactive, unpinned and not yet discarded tabs a discardtab step may release. */\nexport function discardcandidates(tabs: tabshape[]): tabshape[] {\n return tabs.filter(tab => !tab.active && !tab.pinned && !tab.discarded && tab.url.length > 0);\n}\n\n/** Restores discarded tabs on demand without losing their urls; every discarded tab keeps its url for reload. */\nexport function restorediscarded(tabs: tabshape[]): Array<{ tabid: number; url: string }> {\n return tabs.filter(tab => tab.discarded && tab.url.length > 0).map(tab => ({ tabid: tab.tabid, url: tab.url }));\n}\n\n/** Captures one tab layout with name, tabs, groups, positions and window bounds from the live browser state. */\nexport function buildlayout(name: string, tabs: tabshape[], windows: windowshape[], groups: tabgrouprecord[], scratchwindowids: number[], at: number): tablayout {\n return {\n name,\n tabs: tabs.map(tab => ({ url: tab.url, title: tab.title, pinned: tab.pinned, index: tab.index, windowid: tab.windowid })),\n groups: groups.map(group => ({ name: group.name, color: group.color, tabids: group.tabids.filter(tabid => tabs.some(tab => tab.tabid === tabid)), collapsed: group.collapsed })),\n windows: windows.map(item => ({ windowid: item.windowid, state: { bounds: { left: item.left, top: item.top, width: item.width, height: item.height }, maximized: item.state === \"maximized\", profile: item.incognito ? \"incognito\" : scratchwindowids.includes(item.windowid) ? \"scratch\" : \"normal\" } })),\n savedat: at,\n };\n}\n\n/** Plans the restore of one saved layout: only urls that are not already open come back, in layout order. */\nexport function layoutrestoreplan(layout: tablayout, openurls: string[]): string[] {\n const open = new Set(openurls.map(url => normalizedtaburl(url)));\n return layout.tabs.map(tab => tab.url).filter(url => url.length > 0 && !open.has(normalizedtaburl(url)));\n}\n\n/** Keeps tabgroup membership through moves: member ids survive, their order follows the live tab order and closed members drop out. */\nexport function regroupaftermoves(groups: tabgrouprecord[], tabs: tabshape[], at: number): tabgrouprecord[] {\n const order = new Map(tabs.map(tab => [tab.tabid, tab.index]));\n return groups.map(group => {\n const members = group.tabids.filter(tabid => order.has(tabid));\n if (members.length === 0) return group;\n const ordered = [...members].sort((left, right) => (order.get(left) ?? 0) - (order.get(right) ?? 0));\n return ordered.length === group.tabids.length && ordered.every((tabid, index) => tabid === group.tabids[index]) ? group : { ...group, tabids: ordered, savedat: at };\n });\n}\n\n/** Renames one stored tab group while keeping its color choice, member tabs and collapse state. */\nexport function renamegroup(groups: tabgrouprecord[], name: string, newname: string, at: number): tabgrouprecord[] {\n return groups.map(group => group.name === name ? { ...group, name: newname, savedat: at } : group);\n}\n\n/** Counts the task tabs that live inside one window so the close gate can demand review. */\nexport function tasktabsinwindow(tabs: tabshape[], windowid: number, tasktabids: number[]): number {\n const tasks = new Set(tasktabids);\n return tabs.filter(tab => tab.windowid === windowid && tasks.has(tab.tabid)).length;\n}\n\n/** Selects the tabs a reviewed closepattern may close; the session tab itself is always refused protection. */\nexport function closeselection(query: tabquery, tabs: tabshape[], sessiontabid: number): { targets: tabshape[]; refused: tabshape[] } {\n const matches = querymatches(query, tabs);\n return {\n targets: matches.filter(tab => tab.tabid !== sessiontabid),\n refused: matches.filter(tab => tab.tabid === sessiontabid),\n };\n}\n\n/** Applies one reviewed zoom step with no code ceiling; a step never crosses zero, so it keeps the current zoom instead. */\nexport function zoomstep(current: number, direction: \"in\" | \"out\", step: number): number {\n const next = direction === \"in\" ? current + step : current - step;\n return next > 0 ? Number(next.toFixed(4)) : current;\n}\n\n/** Resolves the neighbor tab index a switchtab step activates, wrapping at both ends of the window. */\nexport function switchtarget(tabs: tabshape[], direction: \"next\" | \"previous\", currentindex: number): number | undefined {\n if (tabs.length === 0) return undefined;\n const offset = direction === \"next\" ? 1 : -1;\n return (currentindex + offset + tabs.length) % tabs.length;\n}\n\n/** Orders the quick switcher list by recency with filter keys; unseen tabs follow in live index order. */\nexport function switcherlist(tabs: tabshape[], recency: Array<{ tabid: number; at: number }>, filter: string): tabshape[] {\n const needle = filter.trim().toLowerCase();\n const matches = needle ? tabs.filter(tab => tab.title.toLowerCase().includes(needle) || tab.url.toLowerCase().includes(needle)) : [...tabs];\n const lastrun = new Map(recency.map(entry => [entry.tabid, entry.at]));\n return [...matches].sort((left, right) => {\n const leftat = lastrun.get(left.tabid) ?? -1;\n const rightat = lastrun.get(right.tabid) ?? -1;\n if (leftat !== rightat) return rightat - leftat;\n return left.index - right.index;\n });\n}\n\n/** Dispatches the tab events of one watchtab registration into the step result, honoring the reviewed event filters. */\nexport function watchtabdispatch(events: tabwatchevent[], watchid: string, filters: string[]): tabwatchevent[] {\n const allowed = filters.length > 0 ? new Set(filters) : undefined;\n return events.filter(event => event.watchid === watchid && (allowed === undefined || allowed.has(event.event)));\n}\n\n/** Computes the per task badge from the live progress state of the task. */\nexport function badgefromprogress(completed: number, total: number): { label: string; done: boolean } {\n if (total <= 0) return { label: \"idle\", done: false };\n if (completed >= total) return { label: \"done\", done: true };\n return { label: `${completed}/${total}`, done: false };\n}\n\n/** Grades the concurrent task tab budget: a user configured ceiling refuses, an absent ceiling never refuses. */\nexport function tasktabgauge(used: number, ceiling: number | undefined): { used: number; ceiling: number | undefined; over: boolean } {\n return { used, ceiling, over: ceiling !== undefined && used > ceiling };\n}\n\n/** True when a window profile inherits the session origin grants; incognito windows stay separated. */\nexport function windowprofilegrants(profile: \"normal\" | \"incognito\" | \"scratch\"): boolean {\n return profile !== \"incognito\";\n}\n\n/** Assigns every task tab of the plan progress, used when tabmeta routing records a tab for the plan steps. */\nexport function assigntasktabs(progress: planprogress | undefined, planid: string, tabids: number[], now: number): planprogress {\n let next = progress;\n for (const tabid of tabids) next = assigntasktab(next, planid, tabid, now);\n return next ?? { planid, completedsteps: [], tasktabs: [], updatedat: now };\n}\n\n/** Returns the task tabs tracked by one plan progress, used for window close review and badge refresh. */\nexport function trackedtasktabs(progress: planprogress | undefined, planid: string): number[] {\n return tasktabs(progress, planid);\n}\n", "import type { fielderror, fieldkind, fieldmatch, formrecord, formentry, formreport, toolstep } from \"../types.js\";\nimport { parseoptions } from \"../policy.js\";\nimport type { stepresult } from \"./pageactions.js\";\nimport { clean, elementlabel as label, elementselector as selector } from \"./pageresolve.js\";\n\n/**\n * Form field logics for reviewed steps.\n * Every correlated rule for field matching, field kind classification, seeded value generation, native value fills, honeypot detection, login and template detection, error association and form record parsing lives in this file.\n */\n\n/** One serializable form field shape resolved against the page controls. */\nexport interface fieldshape {\n selector: string;\n tag: string;\n type: string;\n name: string;\n label: string;\n placeholder: string;\n arialabel: string;\n autocomplete: string;\n options?: string[];\n}\n\n/** One surveyed field shape carrying the visibility, geometry and timing evidence the honeypot detector reads. */\nexport interface fieldsurvey extends fieldshape {\n hidden: boolean;\n offscreen: boolean;\n createdat?: number;\n}\n\n/** One honeypot field flagged by hidden, offscreen or time trap evidence. */\nexport interface honeypotevidence {\n selector: string;\n reason: \"hidden\" | \"offscreen\" | \"timetrap\";\n}\n\n/** One surveyed field with the aria describedby ref and the sibling message texts the error reader associates. */\nexport interface errorcontext extends fieldshape {\n describedby?: string;\n siblings: string[];\n}\n\n/** Resolves controls by label, placeholder, aria label and name attributes; matches are case insensitive substrings. */\nexport function matchfield(fields: fieldshape[], match: fieldmatch): fieldshape[] {\n const key = match.mode === \"label\" ? \"label\" : match.mode === \"placeholder\" ? \"placeholder\" : match.mode === \"arialabel\" ? \"arialabel\" : \"name\";\n const needle = (match[key] ?? \"\").trim().toLowerCase();\n if (!needle) return [];\n return fields.filter(field => {\n const primary = (field[key] as string).toLowerCase();\n const secondary = match.mode === \"label\" || match.mode === \"name\" ? field.name.toLowerCase() : match.mode === \"placeholder\" ? field.arialabel.toLowerCase() : field.placeholder.toLowerCase();\n return primary.includes(needle) || secondary.includes(needle);\n });\n}\n\n/** Infers the field kind of one control from its input type, autocomplete hint and label text. */\nexport function classifyfield(input: { type: string; autocomplete: string; label: string }): fieldkind {\n const type = input.type.toLowerCase();\n const autocomplete = input.autocomplete.toLowerCase();\n const label = input.label.toLowerCase();\n if (type === \"password\") return \"password\";\n if (autocomplete.startsWith(\"cc-\") || label.includes(\"card number\") || label.includes(\"credit card\") || label.includes(\"cardholder\")) return \"card\";\n if (autocomplete.includes(\"one-time-code\") || autocomplete.includes(\"otp\") || label.includes(\"one time code\") || label.includes(\"verification code\") || label.includes(\"otp\")) return \"code\";\n if (type === \"email\" || autocomplete.includes(\"email\") || label.includes(\"email\")) return \"email\";\n if (type === \"tel\" || autocomplete.includes(\"tel\") || label.includes(\"phone\") || label.includes(\"telephone\")) return \"phone\";\n if (type === \"date\") return \"date\";\n if (type === \"number\") return \"number\";\n if (type === \"checkbox\") return \"check\";\n if (type === \"radio\") return \"radio\";\n if (type === \"file\") return \"file\";\n if (type === \"select\" || type === \"select-one\") return \"select\";\n return \"text\";\n}\n\nconst firstnames: Record<string, string[]> = { en: [\"alex\", \"jordan\", \"taylor\", \"morgan\", \"casey\"], pt: [\"ana\", \"bruno\", \"carla\", \"diego\", \"helena\"] };\nconst lastnames: Record<string, string[]> = { en: [\"brooks\", \"carter\", \"diaz\", \"evans\", \"reyes\"], pt: [\"alves\", \"costa\", \"lima\", \"souza\", \"moraes\"] };\n\nfunction localekey(locale: string): string {\n const normalized = locale.toLowerCase();\n if (normalized.startsWith(\"pt\")) return \"pt\";\n return \"en\";\n}\n\n/** Generates one realistic value for a field kind, deterministically seeded and locale aware for names, emails and phones. */\nexport function generatevalue(kind: fieldkind, rule: { locale?: string; seed?: number }): string {\n const seed = typeof rule.seed === \"number\" && Number.isFinite(rule.seed) ? Math.abs(Math.floor(rule.seed)) : 1;\n const names = firstnames[localekey(rule.locale ?? \"en\")] ?? firstnames.en ?? [\"alex\"];\n const surnames = lastnames[localekey(rule.locale ?? \"en\")] ?? lastnames.en ?? [\"brooks\"];\n let state = seed * 1103515245 + 12345;\n const next = (): number => { state = (state * 1103515245 + 12345) % 2147483648; return state / 2147483648; };\n const pick = <T>(items: T[]): T => items[Math.floor(next() * items.length) % items.length] ?? items[0] as T;\n const digits = (count: number): string => Array.from({ length: count }, () => String(Math.floor(next() * 10))).join(\"\");\n const person = `${pick(names)} ${pick(surnames)}`;\n switch (kind) {\n case \"email\": return `${person.replace(\" \", \".\")}${digits(2)}@example.com`;\n case \"phone\": return localekey(rule.locale ?? \"en\") === \"pt\" ? `+55 (11) 9${digits(4)}-${digits(4)}` : `+1 (555) 010-${digits(4)}`;\n case \"date\": return `${2024 + Math.floor(next() * 2)}-${String(1 + Math.floor(next() * 12)).padStart(2, \"0\")}-${String(1 + Math.floor(next() * 28)).padStart(2, \"0\")}`;\n case \"number\": return String(Math.floor(next() * 1000));\n case \"select\": return `option ${1 + Math.floor(next() * 5)}`;\n case \"check\": return next() > 0.5 ? \"true\" : \"false\";\n case \"radio\": return `choice ${1 + Math.floor(next() * 4)}`;\n case \"file\": return `sample${digits(2)}.pdf`;\n case \"password\": return `pw-${digits(6)}-${pick(names)}`;\n case \"card\": return `4111 ${digits(4)} ${digits(4)} ${digits(4)}`;\n case \"code\": return digits(6);\n default: return person;\n }\n}\n\n/** Builds a deterministic values hash of the reviewed field values a submission ticket records. */\nexport function valueshash(values: Array<{ label: string; value: string }>): string {\n const source = values.map(entry => `${entry.label}=${entry.value}`).join(\"|\");\n let hash = 5381;\n for (let index = 0; index < source.length; index += 1) hash = ((hash * 33) ^ source.charCodeAt(index)) >>> 0;\n return hash.toString(16);\n}\n\n/** Parses the reviewed structured form record of a step; null when the step reviews none or the shape is invalid. */\nexport function parseformrecord(value: unknown): formrecord | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n if (!Array.isArray(record.entries)) return null;\n const entries: formentry[] = [];\n for (const item of record.entries) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n const entry = item as Record<string, unknown>;\n const match = entry.match;\n if (!match || typeof match !== \"object\" || Array.isArray(match)) continue;\n const shapes = match as Record<string, unknown>;\n if (typeof shapes.mode !== \"string\") continue;\n const fieldmatch: fieldmatch = {\n mode: shapes.mode as fieldmatch[\"mode\"],\n ...(typeof shapes.label === \"string\" ? { label: shapes.label } : {}),\n ...(typeof shapes.placeholder === \"string\" ? { placeholder: shapes.placeholder } : {}),\n ...(typeof shapes.arialabel === \"string\" ? { arialabel: shapes.arialabel } : {}),\n ...(typeof shapes.name === \"string\" ? { name: shapes.name } : {}),\n };\n if (typeof entry.kind !== \"string\" || typeof entry.value !== \"string\") continue;\n entries.push({ match: fieldmatch, kind: entry.kind as fieldkind, value: entry.value });\n }\n if (entries.length === 0) return null;\n return { ...(typeof record.form === \"string\" && record.form ? { form: record.form } : {}), entries };\n}\n\n/** Builds form record entries from reviewed label or placeholder value pairs. */\nexport function pairentries(pairs: Array<{ label?: string; placeholder?: string; value: string }>, mode: \"label\" | \"placeholder\"): formrecord {\n return { entries: pairs.map(pair => ({ match: mode === \"label\" ? { mode, label: pair.label ?? \"\" } : { mode, placeholder: pair.placeholder ?? \"\" }, kind: \"text\", value: pair.value })) };\n}\n\n/** One fill operation outcome: the entry, the matched control, the honeypot skip flag or the refusal reason. */\nexport interface filloutcome {\n entry: formentry;\n matched?: fieldshape;\n skipped?: boolean;\n reason?: string;\n}\n\n/** Resolves every entry of a form record against the surveyed fields, skipping honeypots and refusing unmatched or ambiguous entries. */\nexport function filloperations(record: formrecord, fields: fieldshape[], skippedselectors: string[] = []): filloutcome[] {\n return record.entries.map(entry => {\n const matches = matchfield(fields, entry.match);\n if (matches.length === 0) return { entry, reason: \"unmatched\" };\n if (matches.length > 1) return { entry, reason: \"ambiguous\" };\n const matched = matches[0] as fieldshape;\n if (skippedselectors.includes(matched.selector)) return { entry, matched, skipped: true };\n return { entry, matched };\n });\n}\n\n/** Masks one card segment so side panels can render card fills without exposing the full value. */\nexport function cardmask(value: string): string {\n const trimmed = value.trim();\n if (/^\\d[\\d\\s-]{11,18}$/.test(trimmed)) {\n const compact = trimmed.replace(/[\\s-]/g, \"\");\n const last = compact.slice(-4);\n return `${\"\u2022\".repeat(Math.max(0, compact.length - 4))}${last}`;\n }\n return \"\u2022\".repeat(trimmed.length);\n}\n\n/** Flags hidden, offscreen and time trap fields so fill steps skip them instead of tripping anti bot defenses. */\nexport function detecthoneypots(surveys: fieldsurvey[], loadedat: number): honeypotevidence[] {\n const traps: honeypotevidence[] = [];\n for (const field of surveys) {\n if (field.hidden) traps.push({ selector: field.selector, reason: \"hidden\" });\n else if (field.offscreen) traps.push({ selector: field.selector, reason: \"offscreen\" });\n else if (field.createdat !== undefined && loadedat > 0 && field.createdat > loadedat) traps.push({ selector: field.selector, reason: \"timetrap\" });\n }\n return traps;\n}\n\n/** Detects a login form: a password field plus an identifier field with session links nearby. */\nexport function detectlogin(fields: fieldshape[], links: string[]): { login: boolean; markers: string[] } {\n const markers: string[] = [];\n const password = fields.find(field => classifyfield(field) === \"password\");\n if (password) markers.push(\"password field\");\n const identifier = fields.find(field => {\n const kind = classifyfield(field);\n return kind === \"email\" || (kind === \"text\" && /user|login|account|identifier/i.test(`${field.name} ${field.label}`));\n });\n if (identifier) markers.push(\"identifier field\");\n const sessionlink = links.some(link => /sign in|log in|log on|forgot|create account|sign up/i.test(link));\n if (sessionlink) markers.push(\"session link\");\n return { login: Boolean(password && identifier && sessionlink), markers };\n}\n\nconst signupmarkers = [\"sign up\", \"create account\", \"register\", \"confirm password\", \"terms\"];\nconst checkoutmarkers = [\"checkout\", \"payment\", \"billing\", \"shipping\", \"card number\", \"place order\", \"cart\"];\n\n/** Detects signup and checkout templates by matching the field labels, autocompletes and page text against known markers. */\nexport function detecttemplate(fields: fieldshape[], text: string): { template: \"signup\" | \"checkout\" | \"unknown\"; markers: string[] } {\n const corpus = [text, ...fields.map(field => `${field.label} ${field.name} ${field.placeholder} ${field.arialabel} ${field.autocomplete}`)].join(\" \").toLowerCase();\n const signup = signupmarkers.filter(marker => corpus.includes(marker));\n const checkout = checkoutmarkers.filter(marker => corpus.includes(marker));\n if (signup.length >= 2 && signup.length >= checkout.length) return { template: \"signup\", markers: signup };\n if (checkout.length >= 2) return { template: \"checkout\", markers: checkout };\n return { template: \"unknown\", markers: [...signup, ...checkout] };\n}\n\n/** Associates validation messages with fields through aria describedby refs and the sibling text next to each field. */\nexport function associateerrors(contexts: errorcontext[], messages: Array<{ id?: string; text: string }>): fielderror[] {\n const errors: fielderror[] = [];\n for (const field of contexts) {\n const byref = field.describedby ? messages.find(message => message.id === field.describedby && message.text.trim()) : undefined;\n if (byref) { errors.push({ field: field.selector, message: byref.text.trim() }); continue; }\n const sibling = field.siblings.map(text => text.trim()).find(text => text.length > 0);\n if (sibling) errors.push({ field: field.selector, message: sibling });\n }\n return errors;\n}\n\n/** Resolves one reviewed artifact name against the run store before a file input is filled. */\nexport function attachplan(name: string, artifacts: Array<{ id: string; name: string; kind: string }>): { artifact?: { id: string; name: string; kind: string }; reason?: string } {\n const artifact = artifacts.find(item => item.name === name || item.id === name);\n if (!artifact) return { reason: \"The reviewed artifact name is not part of the run store.\" };\n return { artifact };\n}\n\n/** Selectors the captcha detector probes; a hit hands control back to the user instead of forcing the page. */\nexport const captchamarkers = ['iframe[src*=\"recaptcha\"]', 'iframe[title*=\"recaptcha\" i]', '.g-recaptcha', '[data-sitekey]', 'iframe[title*=\"captcha\" i]', '.h-captcha'];\n\n/** True when any captcha marker matched, so the plan pauses and hands control to the user. */\nexport function captchadetected(matched: string[]): boolean {\n return matched.length > 0;\n}\n\nfunction events(target: Element): void {\n target.dispatchEvent(new Event(\"input\", { bubbles: true }));\n target.dispatchEvent(new Event(\"change\", { bubbles: true }));\n}\n\n/** Fills one control through the native setter with input and change events; checks, radios and selects use their own grammar. */\nexport function fillcontrol(element: Element, entry: formentry): boolean {\n if (element instanceof HTMLInputElement && (entry.kind === \"check\" || element.type === \"checkbox\")) { element.checked = entry.value === \"true\" || entry.value === \"on\" || entry.value === \"checked\"; events(element); return true; }\n if (element instanceof HTMLInputElement && (entry.kind === \"radio\" || element.type === \"radio\")) { element.checked = true; events(element); return true; }\n if (element instanceof HTMLSelectElement) {\n const option = [...element.options].find(candidate => candidate.value === entry.value || candidate.textContent?.trim() === entry.value);\n if (!option) return false;\n element.value = option.value;\n events(element);\n return true;\n }\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n if (element instanceof HTMLInputElement && element.type === \"file\") return false;\n element.focus();\n const setter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), \"value\")?.set;\n if (setter) setter.call(element, entry.value); else element.value = entry.value;\n events(element);\n return true;\n }\n return false;\n}\n\nfunction controlshape(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): fieldshape {\n return {\n selector: selector(element),\n tag: element.tagName.toLowerCase(),\n type: element instanceof HTMLSelectElement ? \"select\" : element.getAttribute(\"type\") || \"text\",\n name: element.getAttribute(\"name\") || \"\",\n label: label(element),\n placeholder: element.getAttribute(\"placeholder\") || \"\",\n arialabel: element.getAttribute(\"aria-label\") || \"\",\n autocomplete: element.getAttribute(\"autocomplete\") || \"\",\n ...(element instanceof HTMLSelectElement ? { options: [...element.options].map(option => option.value) } : {}),\n };\n}\n\n/** Collects the serializable field shapes of one form scope; absent scopes survey the whole document. */\nfunction collectfields(root: Document, formscope?: string): Array<{ shape: fieldshape; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n const scope = formscope ? root.querySelector(formscope) : root;\n if (!scope) return [];\n const controls = [...scope.querySelectorAll<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>(\"input, select, textarea\")];\n return controls.filter(element => element.type !== \"hidden\").map(element => ({ shape: controlshape(element), element }));\n}\n\n/** Surveys the visibility and geometry evidence the honeypot detector reads for one form scope. */\nfunction surveyfields(root: Document, formscope?: string): Array<{ survey: fieldsurvey; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n const viewport = { left: 0, top: 0, right: window.innerWidth || 0, bottom: window.innerHeight || 0 };\n return collectfields(root, formscope).map(({ shape, element }) => {\n const rect = element.getBoundingClientRect();\n const hidden = element.getAttribute(\"aria-hidden\") === \"true\" || element.tabIndex < 0 && (element as HTMLElement).offsetParent === null || (element as HTMLElement).offsetParent === null && rect.width === 0 && rect.height === 0;\n const offscreen = rect.width > 0 && rect.height > 0 && (rect.bottom < viewport.top || rect.top > viewport.bottom || rect.right < viewport.left || rect.left > viewport.right);\n return { survey: { ...shape, hidden, offscreen }, element };\n });\n}\n\n/** Reads the error context of one form scope: describedby refs and the sibling texts after each field. */\nfunction collecterrorcontext(root: Document, formscope?: string): Array<{ context: errorcontext; element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }> {\n return collectfields(root, formscope).map(({ shape, element }) => {\n const siblings: string[] = [];\n let neighbor = element.nextElementSibling;\n for (let index = 0; neighbor && index < 3; index += 1) {\n const text = clean(neighbor.textContent || \"\");\n if (text && text !== shape.label) siblings.push(text);\n neighbor = neighbor.nextElementSibling;\n }\n const describedby = element.getAttribute(\"aria-describedby\");\n return { context: { ...shape, ...(describedby ? { describedby } : {}), siblings }, element };\n });\n}\n\n/** Runs one reviewed forms and data step inside the page: fills, surveys, detects and reads errors without leaving the form scope. */\nexport function runpageform(step: toolstep, target: Element | null, root: Document = document): stepresult | Promise<stepresult> {\n let options: Record<string, unknown> = {};\n try { options = parseoptions(step); } catch { options = {}; }\n const formscope = typeof options.form === \"string\" && options.form ? options.form : step.target;\n switch (step.kind) {\n case \"fillform\": {\n const record = parseformrecord(options.formrecord);\n if (!record) return { ok: false, summary: \"A reviewed form record with entries is required in options.\" };\n const surveys = surveyfields(root, record.form);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const operations = filloperations(record, surveys.map(entry => entry.survey), honeypots.map(trap => trap.selector));\n let filled = 0;\n const skipped: string[] = [];\n const failures: string[] = [];\n const values: Array<{ label: string; value: string }> = [];\n for (const operation of operations) {\n if (operation.skipped && operation.matched) { skipped.push(operation.matched.selector); continue; }\n if (!operation.matched) { failures.push(`${operation.reason}: ${operation.entry.match.label ?? operation.entry.match.name ?? operation.entry.match.placeholder ?? \"field\"}`); continue; }\n const element = surveys.find(entry => entry.survey.selector === operation.matched?.selector)?.element;\n if (!element || !fillcontrol(element, operation.entry)) { failures.push(`unfillable: ${operation.matched.selector}`); continue; }\n filled += 1;\n values.push({ label: operation.matched.label || operation.matched.name, value: operation.entry.kind === \"password\" ? \"\" : operation.entry.value });\n }\n const report: formreport = { form: record.form ?? \"\", fields: operations.map(operation => ({ selector: operation.matched?.selector ?? \"\", label: operation.matched?.label ?? operation.entry.match.label ?? \"\", kind: operation.entry.kind, matched: Boolean(operation.matched) })) };\n return {\n ok: failures.length === 0,\n summary: failures.length === 0 ? `Filled ${filled} reviewed field${filled === 1 ? \"\" : \"s\"} from the structured record${skipped.length > 0 ? ` and skipped ${skipped.length} honeypot field${skipped.length === 1 ? \"\" : \"s\"}` : \"\"}.` : `Filled ${filled} of ${record.entries.length} reviewed fields; ${failures.length} refusals: ${failures.join(\"; \")}.`,\n details: { filled, skipped, failures, values, report },\n };\n }\n case \"filllabel\":\n case \"fillplaceholder\": {\n const mode = step.kind === \"filllabel\" ? \"label\" : \"placeholder\";\n const pairs = Array.isArray(options.fields) ? (options.fields as Array<Record<string, unknown>>).filter(item => item && typeof item === \"object\") : [];\n const record = pairentries(pairs.map(pair => ({ label: typeof pair.label === \"string\" ? pair.label : \"\", placeholder: typeof pair.placeholder === \"string\" ? pair.placeholder : \"\", value: typeof pair.value === \"string\" ? pair.value : \"\" })), mode);\n if (record.entries.length === 0) return { ok: false, summary: \"A reviewed non-empty list of field pairs is required in options.\" };\n const surveys = surveyfields(root, formscope);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const operations = filloperations(record, surveys.map(entry => entry.survey), honeypots.map(trap => trap.selector));\n let filled = 0;\n const failures: string[] = [];\n for (const operation of operations) {\n if (operation.skipped) continue;\n if (!operation.matched) { failures.push(`${operation.reason}: ${mode === \"label\" ? operation.entry.match.label : operation.entry.match.placeholder}`); continue; }\n const element = surveys.find(entry => entry.survey.selector === operation.matched?.selector)?.element;\n const refined: formentry = { ...operation.entry, kind: classifyfield(operation.matched) };\n if (!element || !fillcontrol(element, refined)) { failures.push(`unfillable: ${operation.matched.selector}`); continue; }\n filled += 1;\n }\n return { ok: failures.length === 0, summary: failures.length === 0 ? `Filled ${filled} field${filled === 1 ? \"\" : \"s\"} matched by ${mode}.` : `Filled ${filled} of ${record.entries.length} fields matched by ${mode}; ${failures.join(\"; \")}.`, details: { filled, failures, mode } };\n }\n case \"detectfields\": {\n const collected = collectfields(root, formscope);\n const report: formreport = { form: formscope ?? \"\", fields: collected.map(entry => ({ selector: entry.shape.selector, label: entry.shape.label || entry.shape.name, kind: classifyfield(entry.shape), matched: Boolean(entry.shape.label || entry.shape.name) })) };\n return { ok: true, summary: `Detected ${collected.length} form field${collected.length === 1 ? \"\" : \"s\"} with their kinds.`, details: { report, count: collected.length } };\n }\n case \"generatevalues\": {\n const rule = options.valuegen && typeof options.valuegen === \"object\" && !Array.isArray(options.valuegen) ? options.valuegen as Record<string, unknown> : {};\n const locale = typeof rule.locale === \"string\" ? rule.locale : \"en\";\n const seed = typeof rule.seed === \"number\" && Number.isFinite(rule.seed) ? rule.seed : 1;\n const surveys = surveyfields(root, formscope);\n const honeypots = detecthoneypots(surveys.map(entry => entry.survey), 0);\n const skippedselectors = new Set(honeypots.map(trap => trap.selector));\n const candidates = surveys.filter(entry => !skippedselectors.has(entry.survey.selector));\n const values = candidates.map(entry => ({ label: entry.survey.label || entry.survey.name || entry.survey.selector, kind: classifyfield(entry.survey), value: generatevalue(classifyfield(entry.survey), { locale, seed }) }));\n const single = values.length === 0 && typeof rule.kind === \"string\" ? [{ label: rule.kind, kind: rule.kind, value: generatevalue(rule.kind as fieldkind, { locale, seed }) }] : values;\n return { ok: true, summary: `Generated ${single.length} realistic value${single.length === 1 ? \"\" : \"s\"} for the detected field kinds.`, details: { values: single, locale, seed } };\n }\n case \"readerrors\": {\n const contexts = collecterrorcontext(root, formscope);\n const messages = [...root.querySelectorAll<HTMLElement>(\"[id]\")].map(element => ({ id: element.id, text: clean(element.textContent || \"\") })).filter(message => message.text.length > 0);\n const errors = associateerrors(contexts.map(entry => entry.context), messages);\n return { ok: true, summary: errors.length === 0 ? \"No validation error was found next to the reviewed fields.\" : `Collected ${errors.length} inline validation message${errors.length === 1 ? \"\" : \"s\"}.`, details: { errors, form: formscope ?? \"\" } };\n }\n case \"skiphoneypot\": {\n const surveys = surveyfields(root, formscope);\n const traps = detecthoneypots(surveys.map(entry => entry.survey), 0);\n return { ok: true, summary: traps.length === 0 ? \"No honeypot field was detected.\" : `Skipped ${traps.length} honeypot field${traps.length === 1 ? \"\" : \"s\"}: ${traps.map(trap => `${trap.selector} (${trap.reason})`).join(\", \")}.`, details: { skipped: traps } };\n }\n case \"detectlogin\": {\n const collected = collectfields(root, formscope);\n const links = [...(formscope ? root.querySelectorAll(formscope) : [root] as unknown as Element[])].flatMap(scope => [...scope.querySelectorAll(\"a[href], button\")]).map(element => clean(element.textContent || \"\"));\n const detection = detectlogin(collected.map(entry => entry.shape), links);\n return { ok: true, summary: detection.login ? `Login form detected with ${detection.markers.join(\", \")}.` : \"No login form was detected.\", details: { login: detection.login, markers: detection.markers } };\n }\n case \"detecttemplate\": {\n const collected = collectfields(root, formscope);\n const text = clean(root.body?.innerText || \"\");\n const detection = detecttemplate(collected.map(entry => entry.shape), text);\n return { ok: true, summary: detection.template === \"unknown\" ? \"No signup or checkout template was detected.\" : `${detection.template} template detected with markers ${detection.markers.join(\", \")}.`, details: { template: detection.template, markers: detection.markers } };\n }\n case \"handoffcaptcha\": {\n const matched = captchamarkers.filter(marker => root.querySelector(marker) !== null);\n return { ok: true, summary: captchadetected(matched) ? `Captcha presence detected (${matched.join(\", \")}); control hands back to the user.` : \"No captcha was detected.\", details: { captcha: captchadetected(matched), markers: matched } };\n }\n case \"asksubmit\": {\n const collected = collectfields(root, step.value || undefined);\n const values = collected.map(entry => ({ label: entry.shape.label || entry.shape.name || entry.shape.selector, value: entry.element instanceof HTMLSelectElement ? entry.element.value : (entry.element as HTMLInputElement).value }));\n return { ok: true, summary: `Read ${values.length} field value${values.length === 1 ? \"\" : \"s\"} for the submission review.`, details: { values } };\n }\n case \"submitform\": {\n const form = target instanceof HTMLFormElement ? target : target instanceof HTMLElement ? target.closest(\"form\") : null;\n if (!form) return { ok: false, summary: \"No owning form was found for the reviewed submission.\" };\n form.requestSubmit();\n return { ok: true, summary: \"Form submitted programmatically through its owning form.\" };\n }\n case \"consentpassword\": {\n if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return { ok: false, summary: \"The reviewed password target cannot receive text.\" };\n const entry: formentry = { match: { mode: \"name\", name: target.name || target.getAttribute(\"id\") || \"\" }, kind: \"password\", value: step.value ?? \"\" };\n if (!fillcontrol(target, entry)) return { ok: false, summary: \"The password field refused the native setter fill.\" };\n return { ok: true, summary: \"Password field filled after the reviewed consent; the value never appears in the audit trail.\" };\n }\n case \"attachfile\": {\n if (!(target instanceof HTMLInputElement) || target.type !== \"file\") return { ok: false, summary: \"The reviewed target is not a file input.\" };\n const artifactname = typeof options.artifactname === \"string\" && options.artifactname ? options.artifactname : \"artifact\";\n try {\n const file = new File([new Blob([\"devthink artifact\"], { type: \"application/octet-stream\" })], artifactname);\n const transfer = new DataTransfer();\n transfer.items.add(file);\n target.files = transfer.files;\n events(target);\n return { ok: true, summary: `Artifact ${artifactname} attached to the reviewed file input.`, details: { artifact: options.artifact, artifactname } };\n } catch {\n return { ok: false, summary: \"The reviewed file input refused the artifact attachment.\" };\n }\n }\n default: return { ok: false, summary: \"Unsupported forms and data action.\" };\n }\n}\n", "import type { artifactrecord, columnspec, dataset, datasetrow, exportedartifact, extractsession, provenancerecord, streamstate, toolstep, transformrule } from \"../types.js\";\nimport { tocsv, toexcel, tojson } from \"./pagedata.js\";\n\n/**\n * Dataset command logics for the background executors.\n * Every correlated rule for dataset records, artifact exports with checksums, chunked streaming with backpressure, extraction cursors, loop row variables, provenance records and artifact retention lives in this file.\n */\n\n/** Builds one dataset record from a scraped grid result. */\nexport function builddataset(id: string, name: string, grid: { columns: columnspec[]; rows: datasetrow[]; children?: Array<{ parentrow: number; selector: string; columns: columnspec[]; rows: datasetrow[] }> }, at: number): dataset {\n return { id, name: name || id, columns: grid.columns, rows: grid.rows, sources: [], at };\n}\n\n/** Computes the deterministic checksum of an exported artifact's content. */\nexport function checksum(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) hash = ((hash * 33) ^ value.charCodeAt(index)) >>> 0;\n return `fnv1a-${hash.toString(16)}`;\n}\n\n/** Serializes one dataset into the reviewed export format. */\nexport function exportcontent(datasetvalue: dataset, format: \"csv\" | \"json\" | \"excel\", delimiter = \",\"): string {\n if (format === \"json\") return tojson(datasetvalue.columns, datasetvalue.rows);\n if (format === \"excel\") return toexcel(datasetvalue.columns, datasetvalue.rows, datasetvalue.name);\n return tocsv(datasetvalue.columns, datasetvalue.rows, delimiter);\n}\n\n/** Builds one exported artifact record with its content and checksum for the task artifact store. */\nexport function exportartifact(id: string, datasetvalue: dataset, format: \"csv\" | \"json\" | \"excel\", stepid: string, content: string, at: number): exportedartifact {\n const extension = format === \"excel\" ? \"xml\" : format;\n return { id, kind: format, name: `${datasetvalue.name || datasetvalue.id}.${extension}`, stepid, rowcount: datasetvalue.rows.length, content, checksum: checksum(content), at };\n}\n\n/** Converts one exported artifact into the artifact record shape the run store keeps. */\nexport function artifactrecordof(artifact: exportedartifact): artifactrecord {\n return { id: artifact.id, kind: artifact.kind, name: artifact.name, stepid: artifact.stepid, at: artifact.at };\n}\n\n/** Plans the chunk boundaries of a streaming export from a user configured chunk size with no code ceiling. */\nexport function chunkplan(rows: number, chunk: number): Array<{ index: number; from: number; to: number }> {\n const size = Math.max(1, Math.floor(chunk));\n const chunks: Array<{ index: number; from: number; to: number }> = [];\n for (let from = 0; from < rows || chunks.length === 0; from += size) {\n const to = Math.min(rows, from + size);\n chunks.push({ index: chunks.length, from, to });\n if (to >= rows) break;\n }\n return chunks;\n}\n\n/** True when the stream writer must wait for acknowledgements: pending writes reached the in-flight budget of one. */\nexport function backpressure(written: number, acknowledged: number): boolean {\n return written - acknowledged >= 1;\n}\n\n/** Advances one stream state by one acknowledged chunk of rows. */\nexport function advancestream(state: streamstate, chunk: { index: number; to: number }, at: number, done: boolean): streamstate {\n return { datasetid: state.datasetid, name: state.name, chunk: chunk.index + 1, chunks: state.chunks, written: chunk.to, ...(done ? { done: true } : {}), at };\n}\n\n/** Returns the first unwritten row index of a stream, starting a fresh stream at zero. */\nexport function streamfrom(state: streamstate | undefined, rows: number): number {\n if (!state || state.done) return 0;\n return Math.min(state.written, rows);\n}\n\n/** Builds the initial stream state of one dataset. */\nexport function newstream(datasetvalue: dataset, chunks: number, at: number): streamstate {\n return { datasetid: datasetvalue.id, name: datasetvalue.name, chunk: 0, chunks, written: 0, at };\n}\n\n/** Advances one extraction session by one extracted page with its row count. */\nexport function advancecursor(sessionvalue: extractsession, page: string, rows: number, at: number, done: boolean): extractsession {\n return {\n id: sessionvalue.id,\n datasetid: sessionvalue.datasetid,\n name: sessionvalue.name,\n target: sessionvalue.target,\n next: sessionvalue.next,\n planned: sessionvalue.planned,\n pages: [...sessionvalue.pages, page],\n rows: sessionvalue.rows + rows,\n cursor: sessionvalue.cursor + 1,\n ...(done || sessionvalue.cursor + 1 >= sessionvalue.planned ? { done: true } : {}),\n startedat: sessionvalue.startedat,\n updatedat: at,\n };\n}\n\n/** Builds the initial extraction session of one dataset extraction. */\nexport function newextractsession(id: string, datasetid: string, name: string, target: string, next: string, planned: number, at: number): extractsession {\n return { id, datasetid, name, target, next, planned, pages: [], rows: 0, cursor: 0, startedat: at, updatedat: at };\n}\n\n/** Returns the pages an interrupted extraction still owes after its stored cursor. */\nexport function remainingpages(sessionvalue: extractsession, planned: number): number {\n if (sessionvalue.done) return 0;\n return Math.max(0, Math.max(sessionvalue.planned, planned) - sessionvalue.cursor);\n}\n\n/** Builds one provenance record of an exported artifact with its source url, step ref, row range and checksum. */\nexport function provenancefor(artifact: { id: string; name: string; rowcount: number; checksum: string }, url: string, stepid: string, at: number): provenancerecord {\n return { artifact: artifact.id, name: artifact.name, url, stepid, rowstart: artifact.rowcount > 0 ? 1 : 0, rowend: artifact.rowcount, checksum: artifact.checksum, at };\n}\n\n/** Applies the user configured artifact retention to exported artifacts; an absent setting keeps everything. */\nexport function retainedexports<T>(records: T[], retention: number | undefined): T[] {\n return retention === undefined ? records : records.slice(0, retention);\n}\n\n/** Interpolates one text through the {{column}} tokens of a dataset row. */\nexport function interpolate(text: string, row: datasetrow): string {\n return text.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key: string) => row[key.trim()] ?? \"\");\n}\n\n/** Substitutes the row variables of one looprows iteration into the target, value and options of the inner step. */\nexport function loopstep(step: toolstep, row: datasetrow): toolstep {\n return {\n ...step,\n ...(step.target !== undefined ? { target: interpolate(step.target, row) } : {}),\n ...(step.value !== undefined ? { value: interpolate(step.value, row) } : {}),\n ...(step.options !== undefined ? { options: interpolate(step.options, row) } : {}),\n };\n}\n\n/** Exposes one dataset row as the step variables of a looprows iteration. */\nexport function loopvariables(row: datasetrow): datasetrow {\n return { ...row };\n}\n\n/** Builds the grid preview of a dataset with its column order, total rows and sampled rows. */\nexport function gridpreview(datasetvalue: dataset, sample: number): { datasetid: string; columns: string[]; rows: number; sample: datasetrow[] } {\n return { datasetid: datasetvalue.id, columns: datasetvalue.columns.map(column => column.key), rows: datasetvalue.rows.length, sample: datasetvalue.rows.slice(0, Math.max(0, Math.floor(sample))) };\n}\n\n/** Sorts dataset rows by one column key in the reviewed direction with a stable fallback for equal values. */\nexport function sortrows(rows: datasetrow[], key: string, direction: \"asc\" | \"desc\"): datasetrow[] {\n const sign = direction === \"desc\" ? -1 : 1;\n return [...rows].sort((left, right) => {\n const a = left[key] ?? \"\";\n const b = right[key] ?? \"\";\n const numeric = Number(a);\n const numericb = Number(b);\n if (Number.isFinite(numeric) && Number.isFinite(numericb) && a.trim() !== \"\" && b.trim() !== \"\") return (numeric - numericb) * sign;\n return a.localeCompare(b) * sign;\n });\n}\n\n/** Builds the sheet push payload of one dataset for a reviewed sheet endpoint. */\nexport function sheetpayload(datasetvalue: dataset, sheet: string): { sheet: string; columns: string[]; rows: datasetrow[] } {\n return { sheet, columns: datasetvalue.columns.map(column => column.key), rows: datasetvalue.rows };\n}\n\n/** Merges reviewed transform rules and dedupe keys into the task rules record of one task. */\nexport function mergetaskrules(existing: { taskid: string; transforms: transformrule[]; dedupekeys: string[] } | undefined, taskid: string, transforms: transformrule[], dedupekeys: string[], at: number): { taskid: string; transforms: transformrule[]; dedupekeys: string[]; at: number } {\n return {\n taskid,\n transforms: transforms.length > 0 ? transforms : (existing?.transforms ?? []),\n dedupekeys: dedupekeys.length > 0 ? dedupekeys : (existing?.dedupekeys ?? []),\n at,\n };\n}\n", "import type { a11ycapture, a11ynode, agentplan, artifactinventoryentry, artifactrecord, auditevent, autosnapshotstate, bannerreport, capabilityreport, captchahandoff, capturepolicy, cleanuprule, cleanuprun, clipboardconsentrecord, clipentry, clickablemap, closedtab, columnspec, consolediff, consoleconsentrecord, controltabstate, curatedlist, dataset, datasetrow, derivedselector, detectionrecord, diagnosticreport, downloadrecord, errorrecord, errorreport, extractsession, fielderror, focusevent, formprofile, listpattern, longtaskentry, mimefilter, mutationevent, navcontrol, navrecord, navqueues, netlogrecord, planprogress, provenancerecord, quarantineentry, ratelimitstate, readercapture, rejectionrecord, resolvedtarget, retryoutcome, safetyverdict, sessiondiff, sessionevent, sessionfolder, sessionrecord, sessionsnapshot, shotpair, snapshotdiff, stepoutcome, streamstate, submitticket, tabbadge, tabgrouprecord, tablayout, tabmeta, tableshape, taskrules, taskstate, timelineentry, toolstep, trailentry, transformrule, typeaheadpick, waitprofilerecord, wizardstate , actionkind, runlogentry, steptemplate, variablescope, workflowprovenance, workflowrecord, workflowrun, editormodel, editornode, editorlayout, exportformat, nestedparam, palettenode, runhistoryentry, siteoverride, steplibraryentry, variablekind, versiondiff, watchdogconfig, watchdogrecord, workflowversion} from \"../types.js\";\nimport { addedge, addnode, bindparam, buildsteplibrary, editstep, groupselect, markbreakpoint, minimapfocus, palettecategories, palettenodes, redoedit, removenode, removeedge, renderminimap, reordersteps, searchsteps, snapnode, undoedit, zoomcanvas } from \"../workfloweditor.js\";\nimport { switcherlist, type tabshape, type windowshape } from \"./tabscommand.js\";\nimport { cardmask } from \"./pageforms.js\";\nimport { sortrows } from \"./datacommand.js\";\n\nconst objective = document.querySelector<HTMLTextAreaElement>(\"#objective\");\nconst localbutton = document.querySelector<HTMLButtonElement>(\"#localplan\");\nconst remotebutton = document.querySelector<HTMLButtonElement>(\"#remoteplan\");\nconst diagnosticbutton = document.querySelector<HTMLButtonElement>(\"#diagnostic\");\nconst planroot = document.querySelector<HTMLElement>(\"#plan\");\nconst auditroot = document.querySelector<HTMLElement>(\"#audit\");\nconst diagnosticroot = document.querySelector<HTMLElement>(\"#diagnostics\");\nconst maproot = document.querySelector<HTMLElement>(\"#map\");\nconst a11yroot = document.querySelector<HTMLElement>(\"#a11y\");\nconst readerroot = document.querySelector<HTMLElement>(\"#reader\");\nconst detectionsroot = document.querySelector<HTMLElement>(\"#detections\");\nconst streamroot = document.querySelector<HTMLElement>(\"#stream\");\nconst diffsroot = document.querySelector<HTMLElement>(\"#diffs\");\nconst bannersroot = document.querySelector<HTMLElement>(\"#banners\");\nconst selectorsroot = document.querySelector<HTMLElement>(\"#selectors\");\nconst trailroot = document.querySelector<HTMLElement>(\"#trail\");\nconst navigationroot = document.querySelector<HTMLElement>(\"#navigation\");\nconst tabswindowsroot = document.querySelector<HTMLElement>(\"#tabswindows\");\nconst formsroot = document.querySelector<HTMLElement>(\"#forms\");\nconst datasetsroot = document.querySelector<HTMLElement>(\"#datasets\");\nconst filesroot = document.querySelector<HTMLElement>(\"#files\");\nconst capturesroot = document.querySelector<HTMLElement>(\"#captures\");\nconst mediaroot = document.querySelector<HTMLElement>(\"#media\");\nconst callsroot = document.querySelector<HTMLElement>(\"#calls\");\nconst trafficroot = document.querySelector<HTMLElement>(\"#traffic\");\nconst timelineroot = document.querySelector<HTMLElement>(\"#timeline\");\nconst consolediffroot = document.querySelector<HTMLElement>(\"#consolediff\");\nconst debuggerroot = document.querySelector<HTMLElement>(\"#debugger\");\nconst profilingroot = document.querySelector<HTMLElement>(\"#profiling\");\nconst emulationroot = document.querySelector<HTMLElement>(\"#emulation\");\nconst netviewroot = document.querySelector<HTMLElement>(\"#netview\");\nconst sessionsroot = document.querySelector<HTMLElement>(\"#sessions\");\nconst workflowsroot = document.querySelector<HTMLElement>(\"#workflows\");\nconst workfloweditorroot = document.querySelector<HTMLElement>(\"#workfloweditor\");\nconst triggersroot = document.querySelector<HTMLElement>(\"#triggers\");\nconst agentprotocolroot = document.querySelector<HTMLElement>(\"#agentprotocol\");\nconst triggerview = { manual: undefined as { id: string; workflowid: string; preview: Array<{ stepid: string; kind: string; label: string; block?: string; control?: Record<string, unknown> }>; at: number } | undefined, history: undefined as Array<{ id: string; ruleid: string; at: number; cause: string; url?: string; title?: string }> | undefined };\n/** Sessions view state: the search term and time window, the two diff selections, the pending restore review and the pending import review. */\nconst sessionsview = { term: \"\", window: \"all\" as \"all\" | \"hour\" | \"day\" | \"week\", diffselection: [] as string[], restorereview: undefined as sessionrecord | undefined, importreview: undefined as { records: Array<{ id: string; name: string; tabs: number }>; file: unknown } | undefined };\nconst workflowview = { review: undefined as { workflowid: string; name: string; risk: string; steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string; bindings?: unknown[]; expression?: { operator: string; result: string }; extract?: { groups: string[] }; control?: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } }> } | undefined, selected: \"\" as string };\n/** Workflow editor view state: the open canvas model with its undo and redo stacks, the node selection, the open step inspector, the palette and step library search terms, the run history filters with the last report, the pending import review and the version diff selection. */\nconst editorview = {\n workflowid: \"\" as string,\n model: undefined as editormodel | undefined,\n selected: [] as string[],\n inspector: \"\" as string,\n palettesearch: \"\",\n librarysearch: \"\",\n stepsearch: \"\",\n historyfilter: { workflowid: \"\", outcome: \"\" },\n history: undefined as runhistoryentry[] | undefined,\n importreview: undefined as { importid: string; workflowid: string; name: string; version: number; risk: string; steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> } | undefined,\n diff: undefined as versiondiff | undefined,\n library: undefined as steplibraryentry[] | undefined,\n palette: undefined as palettenode[] | undefined,\n};\nconst statusnode = document.querySelector<HTMLElement>(\"#status\");\nconst progressnode = document.querySelector<HTMLProgressElement>(\"#planprogress\");\nconst capabilitiestext = document.querySelector<HTMLElement>(\"#capabilitiestext\");\n\ntype previewresult = { ok: boolean; summary: string; resolvedtarget?: resolvedtarget; candidates?: string[] };\nconst previews = new Map<string, previewresult>();\n\n/** Live timeline view filters: level, source and step id; the filters stay user choices of the review panel. */\nconst timelinefilter = { level: \"\", source: \"\", stepid: \"\" };\n\n/** The last console diff result rendered by the diff view. */\nlet lastdiff: consolediff | undefined;\n\n/** Safely reads the reviewed options object of one step. */\nfunction options(step: toolstep): Record<string, unknown> {\n if (!step.options) return {};\n try {\n const parsed = JSON.parse(step.options);\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : {};\n } catch { return {}; }\n}\n\nfunction status(message: string, error = false): void { if (statusnode) { statusnode.textContent = message; statusnode.dataset.state = error ? \"error\" : \"ready\"; } }\nasync function request(message: unknown): Promise<unknown> { const response = await chrome.runtime.sendMessage(message) as { ok: boolean; value?: unknown; error?: string }; if (!response.ok) throw new Error(response.error); return response.value; }\nfunction button(label: string, action: () => Promise<void>, disabled = false): HTMLButtonElement { const element = document.createElement(\"button\"); element.type = \"button\"; element.textContent = label; element.disabled = disabled; element.addEventListener(\"click\", () => action().catch(error => status(error instanceof Error ? error.message : String(error), true))); return element; }\n\n/** Kinds addressable by a css target or a reviewed targetref; only these can be previewed. */\nconst previewkinds = [\"focus\", \"inspect\", \"click\", \"type\", \"scroll\", \"select\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"highlight\", \"setattribute\", \"removeattribute\", \"waitfor\", \"shiftclick\", \"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\", \"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\", \"verifyvisible\", \"verifyenabled\", \"pierceshadow\", \"clickpoint\", \"clicktext\", \"clickaria\", \"clickname\", \"resolvexpath\", \"deriveselector\", \"fingerprintsection\", \"submitform\", \"retryform\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"fillcode\", \"consentpassword\"];\n\n/** Topic rows that group the new interaction and observation kinds inside each risk class. */\nconst topictags: Array<{ topic: string; kinds: string[] }> = [\n { topic: \"pointer\", kinds: [\"movepointer\", \"clickpoint\", \"shiftclick\", \"clicktext\", \"clickaria\", \"clickname\", \"pierceshadow\"] },\n { topic: \"typing\", kinds: [\"typetime\", \"appendtext\", \"setvalue\", \"typeedit\", \"submitsearch\"] },\n { topic: \"keys\", kinds: [\"keyhold\", \"keyrelease\"] },\n { topic: \"controls\", kinds: [\"selectmulti\", \"chooseradio\", \"setslider\", \"setdate\", \"setcolor\", \"expanddetails\"] },\n { topic: \"dialogs\", kinds: [\"dismissdialog\"] },\n { topic: \"frames\", kinds: [\"enterframe\"] },\n { topic: \"retry\", kinds: [\"retryaction\"] },\n { topic: \"reads\", kinds: [\"mapclicks\", \"verifyvisible\", \"verifyenabled\", \"resolvexpath\"] },\n { topic: \"observation\", kinds: [\"a11ytree\", \"readvisible\", \"readertree\", \"readoutline\", \"readselection\", \"readopengraph\", \"readlang\", \"detectlanguage\", \"listshadow\", \"listframes\", \"readscrollpos\"] },\n { topic: \"detection\", kinds: [\"detectlists\", \"detecttables\", \"detectinfinitescroll\", \"detectvirtual\", \"detectlazy\", \"detectsticky\", \"detectscrolllock\", \"countpages\", \"classifypage\", \"fingerprintsection\"] },\n { topic: \"watch\", kinds: [\"watchmutate\", \"watchbanner\", \"watchfocus\", \"waitquiet\", \"readjson\", \"diffsnapshots\", \"deriveselector\"] },\n { topic: \"navigation\", kinds: [\"openlink\", \"openprivate\", \"reloadcache\", \"stopnav\", \"waitload\", \"waiturl\", \"followlink\", \"spanav\", \"spawait\", \"rewritequery\", \"setfragment\", \"navlist\", \"navprofile\", \"detecthttp\", \"readredirects\", \"readfinalurl\", \"handleauth\", \"printpdf\", \"prefetch\", \"preconnect\", \"deeplink\", \"reopentab\", \"trailaudit\", \"pausenav\", \"navintent\", \"navrate\", \"openclipboard\", \"checksafe\", \"batchopen\"] },\n { topic: \"tabs\", kinds: [\"querytabs\", \"duplicatetab\", \"closepattern\", \"pintab\", \"mutetab\", \"movetab\", \"movetabwindow\", \"grouptabs\", \"colorgroup\", \"collapsegroup\", \"discardtab\", \"reloadtabs\", \"zoomin\", \"zoomout\", \"watchtab\", \"switchtab\", \"maximizewindow\", \"minimizewindow\", \"restorewindow\", \"focuswindow\", \"scratchwindow\", \"incognitowindow\", \"restoretab\", \"savelayout\", \"restorelayout\", \"findclones\", \"searchtabs\", \"badgetab\", \"attachmeta\", \"listaudio\", \"reopenrun\", \"snapshotsession\"] },\n { topic: \"forms\", kinds: [\"fillform\", \"filllabel\", \"fillplaceholder\", \"detectfields\", \"generatevalues\", \"saveprofiles\", \"asksubmit\", \"submitform\", \"readerrors\", \"retryform\", \"runwizard\", \"selectchain\", \"picktypeahead\", \"pickdate\", \"attachfile\", \"handoffcaptcha\", \"fillcard\", \"fillcode\", \"consentpassword\", \"skiphoneypot\", \"detectlogin\", \"detecttemplate\"] },\n];\n\nfunction steptopic(kind: string): string | undefined {\n return topictags.find(tag => tag.kinds.includes(kind))?.topic;\n}\n\n/** Renders plan completion as a live progress ratio. */\nfunction renderprogress(plan: agentplan, completed: string[]): void {\n if (!progressnode) return;\n const total = plan.steps.length || 1;\n progressnode.max = total;\n progressnode.value = completed.length;\n progressnode.textContent = `${completed.length} of ${plan.steps.length} reviewed steps executed`;\n}\n\n/** Renders the latest structured outcome of one step beside its review entry. */\nfunction renderoutcome(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n const outcome = [...outcomes].reverse().find(item => item.stepid === step.id && item.ok) ?? [...outcomes].reverse().find(item => item.stepid === step.id);\n if (!outcome) return null;\n const node = document.createElement(\"details\");\n node.className = \"outcome\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `${outcome.ok ? \"result\" : \"failure\"}: ${outcome.summary}`;\n node.append(summary);\n if (outcome.details && Object.keys(outcome.details).length > 0) {\n const payload = document.createElement(\"pre\");\n payload.textContent = JSON.stringify(outcome.details, null, 2).slice(0, 4000);\n node.append(payload);\n }\n return node;\n}\n\n/** Renders the hold id of a key hold or release step beside its summary. */\nfunction holddetail(step: toolstep): string {\n if (step.kind === \"keyhold\") {\n const holdid = options(step).holdid;\n return typeof holdid === \"string\" && holdid ? ` \u00B7 hold id ${holdid}` : \"\";\n }\n if (step.kind === \"keyrelease\") return step.value ? ` \u00B7 releases hold id ${step.value}` : \"\";\n return \"\";\n}\n\n/** Renders the retry attempts of one retry step on the step timeline. */\nfunction retrydetail(step: toolstep, retries: retryoutcome[]): HTMLElement | null {\n const latest = [...retries].reverse().find(item => item.stepid === step.id);\n if (!latest) return null;\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `retry timeline: ${latest.attempts} attempt${latest.attempts === 1 ? \"\" : \"s\"} \u00B7 ${latest.movement.toFixed(1)} px movement \u00B7 ${latest.ok ? \"succeeded\" : \"failed\"}`;\n return node;\n}\n\n/** Renders the network quiet progress of one waitquiet step from its outcome evidence. */\nfunction quietdetail(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n if (step.kind !== \"waitquiet\") return null;\n const latest = [...outcomes].reverse().find(outcome => outcome.stepid === step.id);\n if (!latest) return null;\n const samples = Array.isArray(latest.details?.samples) ? latest.details?.samples as Array<{ at: number; quietfor: number }> : [];\n const idle = typeof latest.details?.idle === \"number\" ? latest.details?.idle : 0;\n const last = samples[samples.length - 1];\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `network quiet: ${samples.length} sample${samples.length === 1 ? \"\" : \"s\"} \u00B7 quiet for ${Math.round(last?.quietfor ?? 0)} ms \u00B7 idle threshold ${idle} ms \u00B7 ${latest.ok ? \"quiet reached\" : \"still busy\"}`;\n return node;\n}\n\n/** Renders the per iteration row variables of one looprows step on the step timeline. */\nfunction loopdetail(step: toolstep, progress: planprogress | undefined): HTMLElement | null {\n if (step.kind !== \"looprows\") return null;\n const iterations = (progress?.outcomes ?? []).filter(outcome => outcome.stepid === step.id && outcome.details?.iteration !== undefined);\n if (iterations.length === 0) return null;\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n const latest = iterations[iterations.length - 1];\n if (!latest) return null;\n const variables = latest.details?.variables as Record<string, string> | undefined;\n const shown = variables ? Object.entries(variables).slice(0, 4).map(([key, value]) => `${key}=${value}`).join(\", \") : \"\";\n node.textContent = `loop timeline: ${iterations.length} iteration${iterations.length === 1 ? \"\" : \"s\"} \u00B7 ${String(latest.details?.variable ?? \"row\")} variables ${shown}`;\n return node;\n}\n\n/** Renders the navlist progress of one navlist step with the current url and the remaining count. */\nfunction navlistdetail(step: toolstep, progress: planprogress | undefined, outcomes: stepoutcome[]): HTMLElement | null {\n if (step.kind !== \"navlist\") return null;\n const entries = (progress?.outcomes ?? []).filter(outcome => outcome.stepid === step.id && outcome.details?.naventry !== undefined).map(outcome => outcome.details?.naventry as { index: number; url: string; ok: boolean });\n const total = entries.length > 0 ? Math.max(...entries.map(entry => entry.index)) + 1 : 0;\n const latestoutcome = [...outcomes].reverse().find(outcome => outcome.stepid === step.id);\n const remaining = typeof latestoutcome?.details?.remaining === \"number\" ? latestoutcome.details?.remaining : 0;\n const current = entries[entries.length - 1];\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = entries.length === 0\n ? \"navigation list: no entry completed yet\"\n : `navigation list: ${entries.filter(entry => entry.ok).length} of ${total} entries completed \u00B7 current url ${current?.url ?? \"\"} \u00B7 ${remaining} remaining`;\n return node;\n}\n\n/** Renders the redirect chain and final url of one navigation step from its outcome evidence. */\nfunction redirectdetail(step: toolstep, outcomes: stepoutcome[]): HTMLElement | null {\n if (![\"navigate\", \"followlink\", \"spanav\", \"navlist\", \"openlink\", \"reloadcache\"].includes(step.kind)) return null;\n const latest = [...outcomes].reverse().find(outcome => outcome.stepid === step.id && outcome.details?.hops !== undefined);\n if (!latest) return null;\n const hops = typeof latest.details?.hops === \"number\" ? latest.details?.hops : 0;\n const final = typeof latest.details?.finalurl === \"string\" ? latest.details?.finalurl : \"\";\n const node = document.createElement(\"p\");\n node.className = \"timeline\";\n node.textContent = `redirects: ${Math.max(0, hops - 1)} hop${hops - 1 === 1 ? \"\" : \"s\"} \u00B7 final url ${final || \"unknown\"}`;\n return node;\n}\n\n/** Renders the resolved target details of one previewed interaction step before approval. */\nfunction renderpreview(step: toolstep): HTMLElement | null {\n const preview = previews.get(step.id);\n if (!preview) return null;\n const node = document.createElement(\"details\");\n node.className = \"outcome\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `preview: ${preview.summary}`;\n node.append(summary);\n if (preview.resolvedtarget) {\n const payload = document.createElement(\"pre\");\n payload.textContent = JSON.stringify(preview.resolvedtarget, null, 2);\n node.append(payload);\n }\n if (preview.candidates && preview.candidates.length > 1) {\n const chooser = document.createElement(\"p\");\n chooser.textContent = \"Ambiguous resolution; choose one candidate as the target hint:\";\n node.append(chooser);\n for (const candidate of preview.candidates) {\n node.append(\" \", button(`Choose \"${candidate}\"`, async () => { pickhint(`target hint: ${candidate}`); }));\n }\n }\n return node;\n}\n\nfunction stepitem(plan: agentplan, step: toolstep, completed: string[], outcomes: stepoutcome[], retries: retryoutcome[], progress?: planprogress): HTMLLIElement {\n const item = document.createElement(\"li\");\n const done = completed.includes(step.id);\n item.textContent = `${done ? \"\u2713\" : \"\"} ${step.summary}${holddetail(step)}`;\n const outcome = renderoutcome(step, outcomes);\n if (outcome) item.append(outcome);\n const timeline = step.kind === \"retryaction\" ? retrydetail(step, retries) : quietdetail(step, outcomes);\n if (timeline) item.append(timeline);\n const navlist = navlistdetail(step, progress, outcomes);\n if (navlist) item.append(navlist);\n const loopvars = loopdetail(step, progress);\n if (loopvars) item.append(loopvars);\n const redirects = redirectdetail(step, outcomes);\n if (redirects) item.append(redirects);\n const preview = renderpreview(step);\n if (preview) item.append(preview);\n const hastarget = Boolean(step.target) || options(step).targetref !== undefined;\n if (!done && hastarget && previewkinds.includes(step.kind) && [\"pending\", \"approved\"].includes(plan.state)) item.append(\" \", button(\"Preview current target\", async () => { const result = await request({ kind: \"preview\", stepid: step.id }) as previewresult; previews.set(step.id, result); status(result.summary); await refresh(); }));\n if (!done && plan.state === \"approved\") item.append(\" \", button(\"Run this reviewed step\", async () => { const result = await request({ kind: \"execute\", stepid: step.id }) as { summary: string }; status(result.summary); await refresh(); }));\n return item;\n}\n\nfunction steplist(plan: agentplan, steps: toolstep[], completed: string[], outcomes: stepoutcome[], retries: retryoutcome[], risk: toolstep[\"risk\"], progress?: planprogress): HTMLElement | null {\n const group = steps.filter(step => step.risk === risk);\n if (group.length === 0) return null;\n const section = document.createElement(\"section\");\n const heading = document.createElement(\"h3\");\n heading.textContent = `${risk} steps`;\n section.append(heading);\n const general = group.filter(step => steptopic(step.kind) === undefined);\n if (general.length > 0) {\n const list = document.createElement(\"ol\");\n for (const step of general) list.append(stepitem(plan, step, completed, outcomes, retries, progress));\n section.append(list);\n }\n for (const tag of topictags) {\n const tagged = group.filter(step => steptopic(step.kind) === tag.topic);\n if (tagged.length === 0) continue;\n const row = document.createElement(\"h4\");\n row.textContent = `${tag.topic} steps`;\n section.append(row);\n const list = document.createElement(\"ol\");\n for (const step of tagged) list.append(stepitem(plan, step, completed, outcomes, retries, progress));\n section.append(list);\n }\n return section;\n}\n\nfunction renderplan(plan?: agentplan, progress?: planprogress, outcomes: stepoutcome[] = [], retries: retryoutcome[] = []): void {\n if (!planroot) return;\n planroot.replaceChildren();\n if (!plan) { planroot.textContent = \"Start a session, then request a local or endpoint plan. No task runs before review.\"; if (progressnode) progressnode.value = 0; return; }\n const title = document.createElement(\"h2\"); title.textContent = `${plan.state}: ${plan.objective}`; planroot.append(title);\n const completed = progress?.planid === plan.id ? progress.completedsteps : [];\n renderprogress(plan, completed);\n const sensitive = steplist(plan, plan.steps, completed, outcomes, retries, \"sensitive\", progress);\n const interaction = steplist(plan, plan.steps, completed, outcomes, retries, \"interaction\", progress);\n const read = steplist(plan, plan.steps, completed, outcomes, retries, \"read\", progress);\n for (const group of [sensitive, interaction, read]) if (group) planroot.append(group);\n if (plan.state === \"pending\") { planroot.append(button(\"Approve reviewed plan\", async () => { await request({ kind: \"approve\" }); await refresh(); }), button(\"Reject plan\", async () => { await request({ kind: \"reject\" }); await refresh(); })); }\n if (plan.state === \"completed\" && plan.completedat) { const note = document.createElement(\"p\"); note.textContent = \"Every reviewed step has executed and the plan is closed.\"; planroot.append(note); }\n}\n\n/** Records one clickable map entry or candidate as the target hint for the next plan. */\nfunction pickhint(hint: string): void {\n if (objective) objective.value = objective.value ? `${objective.value}\\n${hint}` : hint;\n status(`${hint} recorded as the target hint for the next plan.`);\n}\n\n/** Renders the clickable map as a numbered list beside the plan and lets the user pick entries. */\nfunction rendermap(map?: clickablemap): void {\n if (!maproot) return;\n maproot.replaceChildren();\n if (!map || map.entries.length === 0) { maproot.textContent = \"Run a mapclicks step to number every clickable element on the page.\"; return; }\n for (const entry of map.entries) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `${entry.number}. ${entry.label || entry.selector} (${entry.role})`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${entry.selector} (map entry ${entry.number}, ${entry.label || entry.role})`));\n item.append(pick);\n maproot.append(item);\n }\n}\n\n/** Renders the latest accessibility tree beside the dom snapshot as indented role lines. */\nfunction rendera11y(capture?: a11ycapture): void {\n if (!a11yroot) return;\n a11yroot.replaceChildren();\n if (!capture) { a11yroot.textContent = \"Run an a11ytree step to capture the accessibility tree beside the dom snapshot.\"; return; }\n const lines: string[] = [];\n const walk = (node: a11ynode, depth: number): void => {\n if (lines.length >= 80) return;\n const states = node.states.length > 0 ? ` [${node.states.join(\", \")}]` : \"\";\n const value = node.value !== undefined ? ` = ${node.value}` : \"\";\n lines.push(`${\"\u00B7 \".repeat(depth)}${node.role}: ${node.name || \"(unnamed)\"}${states}${value}`);\n for (const child of node.children) walk(child, depth + 1);\n };\n walk(capture.tree, 0);\n const payload = document.createElement(\"pre\");\n payload.textContent = lines.join(\"\\n\");\n a11yroot.append(payload);\n}\n\n/** Renders the latest reader view text with heading blocks highlighted. */\nfunction renderreader(capture?: readercapture): void {\n if (!readerroot) return;\n readerroot.replaceChildren();\n if (!capture) { readerroot.textContent = \"Run a readertree step to extract the reader view.\"; return; }\n const title = document.createElement(\"p\");\n title.textContent = `${capture.article.title || \"Untitled\"}${capture.article.byline ? ` \u00B7 ${capture.article.byline}` : \"\"} \u00B7 ${capture.article.words} words \u00B7 ${capture.article.blocks.length} blocks`;\n readerroot.append(title);\n for (const block of capture.article.blocks.slice(0, 40)) {\n const line = document.createElement(\"p\");\n line.className = /^h\\d$/.test(block.kind) ? \"readerblock heading\" : \"readerblock\";\n line.textContent = `${block.kind}: ${block.text.slice(0, 200)}`;\n readerroot.append(line);\n }\n}\n\n/** Shows detected lists, tables and pagination shapes as plan suggestions the user can pick. */\nfunction renderdetections(plan: agentplan | undefined, outcomes: stepoutcome[]): void {\n if (!detectionsroot) return;\n detectionsroot.replaceChildren();\n if (!plan) { detectionsroot.textContent = \"Detection steps list their detected lists, tables and pagination shapes here as suggestions.\"; return; }\n const kindof = (stepid: string): string | undefined => plan.steps.find(step => step.id === stepid)?.kind;\n const latest = (kind: string): stepoutcome | undefined => [...outcomes].reverse().find(outcome => outcome.ok && kindof(outcome.stepid) === kind);\n let shown = 0;\n const listoutcome = latest(\"detectlists\");\n const lists = Array.isArray(listoutcome?.details?.lists) ? listoutcome?.details?.lists as listpattern[] : [];\n for (const pattern of lists.slice(0, 6)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `list of ${pattern.repeat} items \u00B7 ${pattern.itemselector}`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${pattern.itemselector} (repeated list item of ${pattern.container})`));\n item.append(pick);\n detectionsroot.append(item);\n shown += 1;\n }\n const tableoutcome = latest(\"detecttables\");\n const tables = Array.isArray(tableoutcome?.details?.tables) ? tableoutcome?.details?.tables as tableshape[] : [];\n for (const table of tables.slice(0, 6)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `table of ${table.rows} rows \u00B7 ${table.columns.length} columns \u00B7 ${table.selector}`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${table.selector} (detected data table)`));\n item.append(pick);\n detectionsroot.append(item);\n shown += 1;\n }\n const paginationoutcome = latest(\"countpages\");\n if (paginationoutcome) {\n const item = document.createElement(\"li\");\n const current = typeof paginationoutcome.details?.current === \"number\" ? paginationoutcome.details?.current : 0;\n const total = typeof paginationoutcome.details?.total === \"number\" ? paginationoutcome.details?.total : 0;\n const text = document.createElement(\"span\");\n text.textContent = `pagination: current page ${current} \u00B7 estimated total ${total}`;\n item.append(text);\n detectionsroot.append(item);\n shown += 1;\n }\n if (shown === 0) detectionsroot.textContent = \"Detected lists, tables and pagination shapes appear here as plan suggestions.\";\n}\n\n/** Shows the live mutation and focus stream observed during watched steps. */\nfunction renderstream(mutationevents: mutationevent[], focusevents: focusevent[]): void {\n if (!streamroot) return;\n streamroot.replaceChildren();\n if (mutationevents.length === 0 && focusevents.length === 0) { streamroot.textContent = \"Watched steps stream their mutation and focus events here.\"; return; }\n for (const event of mutationevents.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 mutation ${event.event} \u00B7 ${event.targetpath}`;\n streamroot.append(item);\n }\n for (const event of focusevents.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 focus ${event.kind} \u00B7 ${event.targetpath}`;\n streamroot.append(item);\n }\n}\n\n/** Renders the latest snapshot diff with added, removed and changed rows. */\nfunction renderdiffs(diffs: snapshotdiff[]): void {\n if (!diffsroot) return;\n diffsroot.replaceChildren();\n const latest = diffs[0];\n if (!latest) { diffsroot.textContent = \"Diff two captured observation versions with a diffsnapshots step.\"; return; }\n const heading = document.createElement(\"p\");\n heading.textContent = `version ${latest.baseversion} \u2192 ${latest.targetversion}: ${latest.added.length} added \u00B7 ${latest.removed.length} removed \u00B7 ${latest.changed.length} changed`;\n diffsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const entry of [...latest.added, ...latest.removed, ...latest.changed].slice(0, 12)) {\n const item = document.createElement(\"li\");\n item.className = `diffrow ${entry.kind}`;\n item.textContent = `${entry.kind} \u00B7 ${entry.selector} \u00B7 ${entry.summary}`;\n list.append(item);\n }\n diffsroot.append(list);\n}\n\n/** Flags consent banners with a review card before any interaction. */\nfunction renderbanners(banners: bannerreport[]): void {\n if (!bannersroot) return;\n bannersroot.replaceChildren();\n if (banners.length === 0) { bannersroot.textContent = \"No consent banner has been observed yet.\"; return; }\n for (const banner of banners.slice(0, 3)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `${banner.kind} banner detected \u2014 review it before any interaction.`;\n const text = document.createElement(\"p\");\n text.textContent = banner.text.slice(0, 160) || \"(no banner text)\";\n const controls = document.createElement(\"p\");\n controls.textContent = `controls: ${banner.controls.length > 0 ? banner.controls.join(\", \") : \"none\"}`;\n card.append(title, text, controls);\n bannersroot.append(card);\n }\n}\n\n/** Shows derived selector candidates with their stability scores for reuse. */\nfunction renderselectors(selectors: derivedselector[]): void {\n if (!selectorsroot) return;\n selectorsroot.replaceChildren();\n if (selectors.length === 0) { selectorsroot.textContent = \"Run a deriveselector step to rank stable selectors.\"; return; }\n for (const record of selectors.slice(0, 8)) {\n const item = document.createElement(\"li\");\n const pick = document.createElement(\"button\");\n pick.type = \"button\";\n pick.textContent = `${record.selector} (${record.strategy} \u00B7 stability ${record.score})`;\n pick.addEventListener(\"click\", () => pickhint(`target hint: ${record.selector} (derived ${record.strategy} selector)`));\n item.append(pick);\n selectorsroot.append(item);\n }\n}\n\n/** Renders the navigation trail of the session as a timeline of visited urls. */\nfunction rendertrail(trail: trailentry[]): void {\n if (!trailroot) return;\n trailroot.replaceChildren();\n if (trail.length === 0) { trailroot.textContent = \"No page has been visited inside a reviewed navigation step yet.\"; return; }\n for (const entry of [...trail].reverse().slice(0, 12)) {\n const item = document.createElement(\"li\");\n item.textContent = `${new Date(entry.at).toLocaleTimeString()} \u00B7 ${entry.url}${entry.title ? ` \u00B7 ${entry.title}` : \"\"}${entry.stepid ? ` \u00B7 step ${entry.stepid}` : \"\"}`;\n trailroot.append(item);\n }\n}\n\n/** Renders the navigation state: paused navigation, rate limit windows per domain, wait profiles, redirect chains, curated lists, safety verdicts, artifacts and the basic auth prompt behind the consent gate. */\nfunction rendernavigation(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; navcontrol?: navcontrol; ratestates?: ratelimitstate[]; waitprofiles?: waitprofilerecord[]; navrecords?: navrecord[]; curated?: curatedlist[]; safeties?: safetyverdict[]; auths?: Array<{ origin: string; username: string; reviewedat: number }>; navqueues?: navqueues; artifacts?: artifactrecord[] }): void {\n if (!navigationroot) return;\n navigationroot.replaceChildren();\n const paused = document.createElement(\"p\");\n if (context.navcontrol?.pausedat) {\n paused.className = \"bannercard\";\n paused.textContent = `Navigation is paused while ${context.navcontrol.reason ?? \"a consent prompt is open\"}; reviewed navigation steps are blocked until it resumes.`;\n } else {\n paused.textContent = \"Navigation is live; no consent prompt holds it.\";\n }\n navigationroot.append(paused);\n const rates = context.ratestates ?? [];\n if (rates.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"rate limit windows per domain:\";\n navigationroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const state of rates.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${state.domain}: ${state.count} of ${state.limit.ceiling} navigations inside the reviewed window of ${state.limit.window} ms`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const records = context.navrecords ?? [];\n const record = records[0];\n if (record) {\n const chain = document.createElement(\"p\");\n chain.textContent = `latest navigation: ${Math.max(0, record.chain.hops.length - 1)} redirect${record.chain.hops.length - 1 === 1 ? \"\" : \"s\"} \u00B7 final url ${record.finalurl}`;\n navigationroot.append(chain);\n const hops = document.createElement(\"ul\");\n for (const hop of record.chain.hops.slice(0, 6)) {\n const item = document.createElement(\"li\");\n let path = hop.url;\n try { path = new URL(hop.url).pathname; } catch { path = hop.url; }\n item.textContent = `hop ${path} \u00B7 status ${hop.status} \u00B7 ${new Date(hop.at).toLocaleTimeString()}`;\n hops.append(item);\n }\n navigationroot.append(hops);\n }\n const curatedlists = context.curated ?? [];\n if (curatedlists.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"curated link lists with per url safety states:\";\n navigationroot.append(heading);\n for (const list of curatedlists.slice(0, 3)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `${list.links.length} curated url${list.links.length === 1 ? \"\" : \"s\"}${list.reviewedat ? \" \u00B7 opened after review\" : \" \u00B7 waiting for review\"}`;\n card.append(title);\n for (const link of list.links.slice(0, 8)) {\n const line = document.createElement(\"p\");\n line.textContent = `${link.verdict === \"safe\" ? \"\u2713\" : \"\u2717\"} ${link.url}${link.reasons.length > 0 ? ` \u00B7 ${link.reasons.join(\"; \")}` : \"\"}`;\n card.append(line);\n }\n navigationroot.append(card);\n }\n }\n const safeties = context.safeties ?? [];\n const runner = document.createElement(\"p\");\n const checkinput = document.createElement(\"input\");\n checkinput.type = \"url\";\n checkinput.placeholder = \"https://external.example/link\";\n checkinput.setAttribute(\"aria-label\", \"url to verify with checksafe\");\n const checkbutton = button(\"Run checksafe\", async () => {\n const verdict = await request({ kind: \"checksafe\", url: checkinput.value }) as safetyverdict;\n status(verdict.safe ? `${verdict.url} passed every safety check.` : `${verdict.url} is unsafe: ${verdict.reasons.join(\"; \")}.`);\n await refresh();\n });\n runner.append(checkinput, \" \", checkbutton);\n navigationroot.append(runner);\n if (safeties.length > 0) {\n const list = document.createElement(\"ul\");\n for (const verdict of safeties.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${verdict.safe ? \"safe\" : \"unsafe\"} \u00B7 ${verdict.url}${verdict.reasons.length > 0 ? ` \u00B7 ${verdict.reasons.join(\"; \")}` : \"\"}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const authcard = document.createElement(\"div\");\n authcard.className = \"bannercard\";\n const authtitle = document.createElement(\"p\");\n authtitle.textContent = active ? \"basic auth credentials (stored only after your explicit review):\" : \"basic auth credentials need an active session before they can be reviewed.\";\n authcard.append(authtitle);\n if (active) {\n const origininput = document.createElement(\"input\");\n origininput.type = \"url\";\n origininput.placeholder = context.session?.origin ?? \"https://example.com\";\n origininput.setAttribute(\"aria-label\", \"auth origin\");\n const userinput = document.createElement(\"input\");\n userinput.type = \"text\";\n userinput.placeholder = \"username\";\n userinput.setAttribute(\"aria-label\", \"auth username\");\n const passinput = document.createElement(\"input\");\n passinput.type = \"password\";\n passinput.placeholder = \"password\";\n passinput.setAttribute(\"aria-label\", \"auth password\");\n const storebutton = button(\"Store reviewed credentials\", async () => {\n const stored = await request({ kind: \"storeauth\", origin: origininput.value, username: userinput.value, password: passinput.value }) as { origin: string };\n status(`Reviewed basic auth credentials stored for ${stored.origin}.`);\n await refresh();\n });\n authcard.append(origininput, \" \", userinput, \" \", passinput, \" \", storebutton);\n }\n navigationroot.append(authcard);\n const auths = context.auths ?? [];\n if (auths.length > 0) {\n const list = document.createElement(\"ul\");\n for (const record of auths.slice(0, 4)) {\n const item = document.createElement(\"li\");\n item.textContent = `basic auth for ${record.origin} as ${record.username}, reviewed ${new Date(record.reviewedat).toLocaleString()}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n const artifacts = context.artifacts ?? [];\n if (artifacts.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"task artifacts:\";\n navigationroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const artifact of artifacts.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${artifact.kind}: ${artifact.name} \u00B7 step ${artifact.stepid}`;\n list.append(item);\n }\n navigationroot.append(list);\n }\n}\n\n/** Renders the tabs and windows command surface: quick switcher, groups, badges, audio state, layouts, snapshots, clone warnings, the task tab budget gauge and the pinned control tab feed. */\nfunction rendertabswindows(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; progress?: planprogress; tabs?: tabshape[]; windows?: windowshape[]; tabgroups?: tabgrouprecord[]; badges?: tabbadge[]; tabmetas?: tabmeta[]; clones?: Array<{ url: string; tabids: number[] }>; layouts?: tablayout[]; snapshots?: sessionsnapshot[]; closedtabs?: closedtab[]; tasktabgauge?: { used: number; ceiling?: number; over: boolean }; controltab?: controltabstate }): void {\n if (!tabswindowsroot) return;\n tabswindowsroot.replaceChildren();\n const tabs = context.tabs ?? [];\n const badges = context.badges ?? [];\n const metas = context.tabmetas ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const gauge = context.tasktabgauge ?? { used: 0, ceiling: undefined, over: false };\n const budget = document.createElement(\"p\");\n budget.className = gauge.over ? \"bannercard\" : \"\";\n budget.textContent = `task tab budget: ${gauge.used} tab${gauge.used === 1 ? \"\" : \"s\"} with active tasks${gauge.ceiling !== undefined ? ` of the user configured ceiling ${gauge.ceiling}` : \" with no user ceiling configured\"}${gauge.over ? \" \u2014 over the reviewed budget\" : \"\"}`;\n tabswindowsroot.append(budget);\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.type = \"number\";\n ceilinginput.min = \"0\";\n ceilinginput.placeholder = gauge.ceiling !== undefined ? String(gauge.ceiling) : \"no ceiling\";\n ceilinginput.setAttribute(\"aria-label\", \"concurrent task tab ceiling\");\n const ceilingbutton = button(\"Save task tab ceiling\", async () => {\n await request({ kind: \"settasktabceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) });\n status(`Task tab ceiling saved as ${ceilinginput.value === \"\" ? \"no ceiling\" : ceilinginput.value}; the value stays a user choice.`);\n await refresh();\n });\n tabswindowsroot.append(ceilinginput, \" \", ceilingbutton);\n const switcherheading = document.createElement(\"p\");\n switcherheading.textContent = \"quick switcher (ordered by recency, filter by title or url):\";\n tabswindowsroot.append(switcherheading);\n const filterinput = document.createElement(\"input\");\n filterinput.type = \"search\";\n filterinput.placeholder = \"filter open tabs\";\n filterinput.setAttribute(\"aria-label\", \"quick switcher filter\");\n const switchlist = document.createElement(\"ul\");\n const renderswitchlist = (): void => {\n switchlist.replaceChildren();\n const ordered = switcherlist(tabs, [], filterinput.value).slice(0, 10);\n for (const tab of ordered) {\n const item = document.createElement(\"li\");\n const jump = document.createElement(\"button\");\n jump.type = \"button\";\n const badge = badges.find(entry => entry.tabid === tab.tabid);\n const meta = metas.find(entry => entry.tabid === tab.tabid);\n jump.textContent = `${tab.title || tab.url}${tab.pinned ? \" \uD83D\uDCCC\" : \"\"}${tab.audible || tab.muted ? ` ${tab.muted ? \"\uD83D\uDD07\" : \"\uD83D\uDD0A\"}` : \"\"}${badge ? ` [${badge.label}]` : \"\"}${meta && meta.labels.length > 0 ? ` (${meta.labels.join(\", \")})` : \"\"}`;\n jump.addEventListener(\"click\", () => request({ kind: \"jumptotab\", tabid: tab.tabid }).then(() => status(`Jumped to tab ${tab.tabid}.`)).catch(error => status(error instanceof Error ? error.message : String(error), true)));\n item.append(jump);\n switchlist.append(item);\n }\n if (ordered.length === 0) { const empty = document.createElement(\"li\"); empty.textContent = \"no open tab matches the filter\"; switchlist.append(empty); }\n };\n filterinput.addEventListener(\"input\", renderswitchlist);\n tabswindowsroot.append(filterinput, switchlist);\n renderswitchlist();\n const searchinput = document.createElement(\"input\");\n searchinput.type = \"search\";\n searchinput.placeholder = \"search across open tabs by title and url\";\n searchinput.setAttribute(\"aria-label\", \"searchtabs text\");\n const searchresults = document.createElement(\"ul\");\n const searchbutton = button(\"Run searchtabs\", async () => {\n const result = await request({ kind: \"tabsearch\", text: searchinput.value }) as { matches: tabshape[] };\n searchresults.replaceChildren();\n for (const tab of result.matches.slice(0, 10)) {\n const item = document.createElement(\"li\");\n const jump = document.createElement(\"button\");\n jump.type = \"button\";\n jump.textContent = `${tab.title || tab.url} \u00B7 ${tab.url}`;\n jump.addEventListener(\"click\", () => request({ kind: \"jumptotab\", tabid: tab.tabid }).then(() => status(`Jumped to tab ${tab.tabid}.`)).catch(error => status(error instanceof Error ? error.message : String(error), true)));\n item.append(jump);\n searchresults.append(item);\n }\n status(`searchtabs matched ${result.matches.length} open tab${result.matches.length === 1 ? \"\" : \"s\"}.`);\n });\n tabswindowsroot.append(searchinput, \" \", searchbutton, searchresults);\n const clones = context.clones ?? [];\n for (const clone of clones.slice(0, 3)) {\n const warning = document.createElement(\"p\");\n warning.className = \"bannercard\";\n warning.textContent = `duplicate tab warning: ${clone.tabids.length} open tabs share the url ${clone.url} (tabs ${clone.tabids.join(\", \")})`;\n tabswindowsroot.append(warning);\n }\n const groups = context.tabgroups ?? [];\n if (groups.length > 0) {\n const groupsheading = document.createElement(\"p\");\n groupsheading.textContent = \"tab groups with colors and collapse states:\";\n tabswindowsroot.append(groupsheading);\n const grouplist = document.createElement(\"ul\");\n for (const group of groups.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${group.name} \u00B7 ${group.color} \u00B7 ${group.collapsed ? \"collapsed\" : \"expanded\"} \u00B7 ${group.tabids.length} member tab${group.tabids.length === 1 ? \"\" : \"s\"}`;\n grouplist.append(item);\n }\n tabswindowsroot.append(grouplist);\n }\n const windows = context.windows ?? [];\n if (windows.length > 0) {\n const windowsheading = document.createElement(\"p\");\n windowsheading.textContent = \"windows with layouts and bounds:\";\n tabswindowsroot.append(windowsheading);\n const windowlist = document.createElement(\"ul\");\n for (const item of windows.slice(0, 6)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `window ${item.windowid} \u00B7 ${item.state} \u00B7 bounds ${item.left}\u00D7${item.top} ${item.width}\u00D7${item.height}${item.incognito ? \" \u00B7 incognito, grants not inherited\" : \"\"}${item.focused ? \" \u00B7 focused\" : \"\"}`;\n const closebutton = button(\"Close window\", async () => {\n const tasktabids = (context.progress?.tasktabs ?? []);\n const tabsoftask = (context.tabs ?? []).filter(tab => tab.windowid === item.windowid && tasktabids.includes(tab.tabid));\n const reviewed = tabsoftask.length > 1 ? window.confirm(`This window holds ${tabsoftask.length} task tabs. Close it anyway under explicit review?`) : true;\n await request({ kind: \"closewindow\", windowid: item.windowid, reviewed });\n status(`Closed window ${item.windowid}.`);\n await refresh();\n });\n entry.append(\" \", closebutton);\n windowlist.append(entry);\n }\n tabswindowsroot.append(windowlist);\n }\n const layoutcontrols = document.createElement(\"p\");\n const layoutname = document.createElement(\"input\");\n layoutname.type = \"text\";\n layoutname.placeholder = \"layout name\";\n layoutname.setAttribute(\"aria-label\", \"layout name\");\n const savebutton = button(\"Save layout\", async () => {\n if (!active) { status(\"Layout save stays inside an active session.\", true); return; }\n await request({ kind: \"savelayout\", name: layoutname.value });\n status(`Saved the tab layout ${layoutname.value}.`);\n await refresh();\n });\n const restorebutton = button(\"Restore layout\", async () => {\n if (!active) { status(\"Layout restore stays inside an active session.\", true); return; }\n const result = await request({ kind: \"restorelayout\", name: layoutname.value }) as { reopened: number };\n status(`Restored the tab layout ${layoutname.value}: ${result.reopened} tab${result.reopened === 1 ? \"\" : \"s\"} reopened.`);\n await refresh();\n });\n layoutcontrols.append(layoutname, \" \", savebutton, \" \", restorebutton);\n tabswindowsroot.append(layoutcontrols);\n const layouts = context.layouts ?? [];\n if (layouts.length > 0) {\n const layoutlist = document.createElement(\"ul\");\n for (const layout of layouts.slice(0, 4)) {\n const item = document.createElement(\"li\");\n item.textContent = `${layout.name} \u00B7 ${layout.tabs.length} tab${layout.tabs.length === 1 ? \"\" : \"s\"} \u00B7 ${layout.groups.length} group${layout.groups.length === 1 ? \"\" : \"s\"} \u00B7 ${layout.windows.length} window bound${layout.windows.length === 1 ? \"\" : \"s\"} \u00B7 saved ${new Date(layout.savedat).toLocaleString()}`;\n layoutlist.append(item);\n }\n tabswindowsroot.append(layoutlist);\n }\n const snapshots = context.snapshots ?? [];\n if (snapshots.length > 0) {\n const snapcard = document.createElement(\"div\");\n snapcard.className = \"bannercard\";\n const snaptitle = document.createElement(\"p\");\n snaptitle.textContent = `session snapshot card: ${snapshots.length} snapshot${snapshots.length === 1 ? \"\" : \"s\"} stored`;\n snapcard.append(snaptitle);\n for (const snapshot of snapshots.slice(0, 3)) {\n const row = document.createElement(\"p\");\n row.textContent = `${snapshot.layout.tabs.length} tabs \u00B7 captured ${new Date(snapshot.capturedat).toLocaleString()}`;\n const restore = button(\"Restore snapshot\", async () => {\n const result = await request({ kind: \"restoresnapshot\", id: snapshot.id }) as { reopened: number };\n status(`Restored the session snapshot: ${result.reopened} tab${result.reopened === 1 ? \"\" : \"s\"} reopened.`);\n await refresh();\n });\n row.append(\" \", restore);\n snapcard.append(row);\n }\n tabswindowsroot.append(snapcard);\n }\n const controlcard = document.createElement(\"div\");\n controlcard.className = \"bannercard\";\n const controlstate = context.controltab;\n const completed = context.progress?.completedsteps.length ?? 0;\n const total = context.plan?.steps.length ?? 0;\n controlcard.textContent = `pinned control tab feed: ${controlstate?.enabled ? `open as tab ${controlstate.tabid} with the live task status ${completed} of ${total} reviewed steps executed` : \"disabled\"}${context.plan ? ` \u00B7 ${context.plan.state}` : \" \u00B7 no plan\"}`;\n const controlbutton = button(controlstate?.enabled ? \"Close pinned control tab\" : \"Open pinned control tab\", async () => {\n await request({ kind: \"controltab\", enabled: !controlstate?.enabled });\n status(controlstate?.enabled ? \"The pinned control tab was closed.\" : \"The pinned control tab was opened with the live task feed.\");\n await refresh();\n });\n controlcard.append(\" \", controlbutton);\n tabswindowsroot.append(controlcard);\n}\n\n/** Renders the forms and data surface: the form map, generated values, saved profiles, asksubmit cards with the values diff, wizard progress, inline error reports, honeypot skips, template badges, the consent gated code entry and masked card fills. */\nfunction renderforms(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; plan?: agentplan; outcomes?: stepoutcome[]; profiles?: formprofile[]; tickets?: submitticket[]; wizards?: { wizards: wizardstate[]; picks: typeaheadpick[] }; errorreports?: errorreport[]; captchas?: captchahandoff[]; detections?: detectionrecord[]; codeentry?: boolean }): void {\n if (!formsroot) return;\n formsroot.replaceChildren();\n const outcomes = context.outcomes ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const opencaptcha = (context.captchas ?? []).find(handoff => !handoff.resolved);\n if (opencaptcha) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n card.textContent = `Captcha handoff open on ${opencaptcha.origin}: control is yours and the plan waits until you resolve it.`;\n card.append(\" \", button(\"Captcha resolved\", async () => { await request({ kind: \"resolvecaptcha\" }); status(\"Captcha handoff resolved; the plan continues.\"); await refresh(); }));\n formsroot.append(card);\n }\n const detections = context.detections ?? [];\n if (detections.length > 0) {\n const badges = document.createElement(\"p\");\n badges.textContent = `template badges: ${detections.slice(0, 6).map(record => `${record.kind} on ${record.origin}${record.markers.length > 0 ? ` (${record.markers.join(\", \")})` : \"\"}`).join(\" \u00B7 \")}`;\n formsroot.append(badges);\n }\n const mapoutcome = [...outcomes].reverse().find(outcome => outcome.details?.report !== undefined && outcome.details?.count !== undefined);\n const skippedselectors = new Set(outcomes.flatMap(outcome => Array.isArray(outcome.details?.skipped) ? outcome.details?.skipped as Array<{ selector: string }> : []).map(trap => trap.selector));\n if (mapoutcome) {\n const report = mapoutcome.details?.report as { form: string; fields: Array<{ selector: string; label: string; kind: string; matched: boolean }> };\n const heading = document.createElement(\"p\");\n heading.textContent = `form map${report.form ? ` of ${report.form}` : \"\"}: ${report.fields.length} detected field${report.fields.length === 1 ? \"\" : \"s\"} with their kinds${skippedselectors.size > 0 ? `; ${skippedselectors.size} honeypot field${skippedselectors.size === 1 ? \"\" : \"s\"} highlighted as skipped` : \"\"}`;\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const field of report.fields.slice(0, 10)) {\n const item = document.createElement(\"li\");\n const skipped = skippedselectors.has(field.selector);\n item.textContent = `${field.label || field.selector} \u00B7 ${field.kind}${field.matched ? \"\" : \" \u00B7 unmatched\"}${skipped ? \" \u00B7 honeypot, skipped\" : \"\"}`;\n list.append(item);\n }\n formsroot.append(list);\n }\n const valuesoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.values) && outcome.details?.locale !== undefined);\n if (valuesoutcome) {\n const values = valuesoutcome.details?.values as Array<{ label: string; kind: string; value: string }>;\n const locale = typeof valuesoutcome.details?.locale === \"string\" ? valuesoutcome.details.locale : \"en\";\n const seed = typeof valuesoutcome.details?.seed === \"number\" ? valuesoutcome.details.seed : 1;\n const heading = document.createElement(\"p\");\n heading.textContent = `generated values (locale ${locale}, seed ${seed}) with a regenerate button per field:`;\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const entry of values.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.label} \u00B7 ${entry.kind} \u00B7 ${entry.value}`;\n item.append(\" \", button(\"Regenerate\", async () => {\n const regenerated = await request({ kind: \"regeneratevalue\", field: entry.kind, locale, seed: seed + 1 }) as { value: string };\n status(`Regenerated ${entry.label}: ${regenerated.value}.`);\n }));\n list.append(item);\n }\n formsroot.append(list);\n }\n const cardoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.segments));\n if (cardoutcome) {\n const segments = cardoutcome.details?.segments as Array<{ label: string; masked: string }>;\n const cardline = document.createElement(\"p\");\n cardline.textContent = `card fill segments (masked): ${segments.map(segment => `${segment.label} ${cardmask(segment.masked)}`).join(\" \u00B7 \")}`;\n formsroot.append(cardline);\n }\n const profiles = context.profiles ?? [];\n if (profiles.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"saved form profiles with origin grants:\";\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const profile of profiles.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${profile.name} \u00B7 ${profile.fields.length} field${profile.fields.length === 1 ? \"\" : \"s\"} \u00B7 grants ${profile.grants.join(\", \")} \u00B7 saved ${new Date(profile.savedat).toLocaleString()}`;\n item.append(\" \", button(\"Apply\", async () => {\n const applied = await request({ kind: \"applyprofile\", name: profile.name }) as { profile: { fields: unknown[] } };\n pickhint(`profile hint: ${profile.name} with ${applied.profile.fields.length} reviewed field entries`);\n }), \" \", button(\"Remove\", async () => {\n await request({ kind: \"removeprofile\", name: profile.name });\n status(`Form profile ${profile.name} removed.`);\n await refresh();\n }));\n list.append(item);\n }\n formsroot.append(list);\n }\n const pending = (context.tickets ?? []).filter(ticket => ticket.approved === undefined);\n for (const ticket of pending) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `asksubmit for form ${ticket.form || \"the reviewed form\"} \u00B7 values hash ${ticket.valueshash}`;\n card.append(title);\n const askoutcome = [...outcomes].reverse().find(outcome => Array.isArray(outcome.details?.values) && outcome.details?.ticket !== undefined);\n const values = askoutcome?.details?.values as Array<{ label: string; value: string }> | undefined;\n if (values) {\n const diff = document.createElement(\"ul\");\n for (const entry of values.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.label}: ${entry.value}`;\n diff.append(item);\n }\n card.append(diff);\n } else {\n const note = document.createElement(\"p\");\n note.textContent = \"The full values diff appears here once the asksubmit step reads the form.\";\n card.append(note);\n }\n card.append(button(\"Approve submission\", async () => { await request({ kind: \"approvesubmit\", id: ticket.id, approved: true }); status(\"Submission approved; the reviewed submitform step may run.\"); await refresh(); }), \" \", button(\"Decline\", async () => { await request({ kind: \"approvesubmit\", id: ticket.id, approved: false }); status(\"Submission declined.\"); await refresh(); }));\n formsroot.append(card);\n }\n const wizards = context.wizards?.wizards ?? [];\n if (wizards.length > 0) {\n const wizard = wizards[0] as wizardstate;\n const heading = document.createElement(\"p\");\n const indicators = Array.from({ length: wizard.steps }, (_, index) => `${index < wizard.index ? (wizard.completed[index] ? \"\u2713\" : \"\u00B7\") : \"\u25CB\"}`).join(\" \");\n heading.textContent = `wizard progress: step ${Math.min(wizard.index + 1, wizard.steps)} of ${wizard.steps} ${indicators}`;\n formsroot.append(heading);\n }\n const picks = context.wizards?.picks ?? [];\n if (picks.length > 0) {\n const pickline = document.createElement(\"p\");\n pickline.textContent = `typeahead picks: ${picks.slice(0, 6).map(pick => `\"${pick.pick}\" for \"${pick.query}\"`).join(\" \u00B7 \")}`;\n formsroot.append(pickline);\n }\n const reports = context.errorreports ?? [];\n if (reports.length > 0) {\n const heading = document.createElement(\"p\");\n heading.textContent = \"inline error reports with field refs for correction loops:\";\n formsroot.append(heading);\n const list = document.createElement(\"ul\");\n for (const report of reports.slice(0, 3)) {\n const item = document.createElement(\"li\");\n item.textContent = `${report.form || \"the reviewed form\"}: ${report.errors.map((error: fielderror) => `${error.field} \u2014 ${error.message}`).join(\"; \") || \"no message\"}`;\n list.append(item);\n }\n formsroot.append(list);\n }\n const codecard = document.createElement(\"div\");\n codecard.className = \"bannercard\";\n const codetitle = document.createElement(\"p\");\n codetitle.textContent = active ? \"one time code entry (stored behind the consent gate of the active session):\" : \"one time code entry needs an active session first.\";\n codecard.append(codetitle);\n if (active) {\n const codeinput = document.createElement(\"input\");\n codeinput.type = \"text\";\n codeinput.inputMode = \"numeric\";\n codeinput.placeholder = context.codeentry ? \"a reviewed code is stored\" : \"one time code\";\n codeinput.setAttribute(\"aria-label\", \"one time code\");\n const storebutton = button(\"Store reviewed code\", async () => {\n await request({ kind: \"storecode\", code: codeinput.value });\n status(\"The reviewed one time code is stored behind the consent gate.\");\n await refresh();\n });\n codecard.append(codeinput, \" \", storebutton);\n }\n formsroot.append(codecard);\n}\n\n/** Renders the dataset surfaces: the preview grid with sortable columns, extraction progress cards with resume prompts, export actions per dataset, transform rule previews, dedupe results, provenance records, import pickers and sheet endpoint grant states. */\nfunction renderdatasets(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; outcomes?: stepoutcome[]; datasets?: dataset[]; imports?: dataset[]; extractsessions?: extractsession[]; streams?: streamstate[]; exports?: Array<{ id: string; kind: string; name: string; rowcount: number; checksum: string; at: number }>; provenances?: provenancerecord[]; taskrules?: taskrules[]; sheetendpoints?: Array<{ endpoint: string; origin: string; configuredat: number; granted: boolean }> }): void {\n if (!datasetsroot) return;\n datasetsroot.replaceChildren();\n const outcomes = context.outcomes ?? [];\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const extractsessions = context.extractsessions ?? [];\n for (const extract of extractsessions.slice(0, 4)) {\n const card = document.createElement(\"p\");\n const interrupted = extract.done !== true;\n card.textContent = `extraction ${extract.name}: ${extract.pages.length} page${extract.pages.length === 1 ? \"\" : \"s\"} visited \u00B7 ${extract.rows} row${extract.rows === 1 ? \"\" : \"s\"} collected \u00B7 cursor ${extract.cursor} of ${extract.planned}${extract.done ? \" \u00B7 complete\" : \" \u00B7 interrupted\"}`;\n datasetsroot.append(card);\n }\n const interrupted = extractsessions.find(extract => extract.done !== true);\n if (interrupted && active) {\n const prompt = document.createElement(\"div\");\n prompt.className = \"bannercard\";\n prompt.textContent = `Extraction ${interrupted.name} was interrupted at cursor ${interrupted.cursor}; run its resumeextract reviewed step to continue from the stored cursor.`;\n datasetsroot.append(prompt);\n }\n const streams = context.streams ?? [];\n if (streams.length > 0) {\n const stream = streams[0]!;\n const card = document.createElement(\"p\");\n card.textContent = `stream state: ${stream.name} chunk ${stream.chunk} of ${stream.chunks} \u00B7 ${stream.written} row${stream.written === 1 ? \"\" : \"s\"} written${stream.done ? \" \u00B7 complete\" : \" \u00B7 resumable\"}`;\n datasetsroot.append(card);\n }\n const rules = (context.taskrules ?? [])[0];\n if (rules && rules.transforms.length > 0) {\n const transforms = document.createElement(\"p\");\n transforms.textContent = `transform rules: ${rules.transforms.map(rule => `${rule.sources.join(\"+\")} \u2192 ${rule.target} (${rule.expression})`).join(\" \u00B7 \")}`;\n datasetsroot.append(transforms);\n }\n if (rules && rules.dedupekeys.length > 0) {\n const keys = document.createElement(\"p\");\n keys.textContent = `dedupe keys: ${rules.dedupekeys.join(\", \")}`;\n datasetsroot.append(keys);\n }\n const dedupeoutcome = [...outcomes].reverse().find(outcome => outcome.details?.dedupe !== undefined);\n if (dedupeoutcome) {\n const dedupe = dedupeoutcome.details?.dedupe as { removed: number; kept: number; keys: string[] };\n const card = document.createElement(\"p\");\n card.textContent = `last dedupe: removed ${dedupe.removed} duplicate row${dedupe.removed === 1 ? \"\" : \"s\"}, kept ${dedupe.kept} by ${dedupe.keys.join(\", \")}`;\n datasetsroot.append(card);\n }\n for (const datasetvalue of (context.datasets ?? []).slice(0, 4)) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `dataset ${datasetvalue.name}: ${datasetvalue.rows.length} row${datasetvalue.rows.length === 1 ? \"\" : \"s\"} \u00B7 ${datasetvalue.columns.length} column${datasetvalue.columns.length === 1 ? \"\" : \"s\"}${(context.imports ?? []).some(item => item.id === datasetvalue.id) ? \" \u00B7 imported csv\" : \"\"}`;\n card.append(head);\n const grid = document.createElement(\"table\");\n const headerrow = document.createElement(\"tr\");\n for (const column of datasetvalue.columns.slice(0, 6)) {\n const cell = document.createElement(\"th\");\n cell.textContent = `${column.label || column.key} ${column.kind === \"number\" ? \"#\" : \"\"}`;\n cell.addEventListener(\"click\", () => {\n const body = grid.querySelector(\"tbody\");\n if (!body) return;\n const sorted = sortrows(datasetvalue.rows.slice(0, 5), column.key, cell.dataset.sorted === \"asc\" ? \"desc\" : \"asc\");\n cell.dataset.sorted = cell.dataset.sorted === \"asc\" ? \"desc\" : \"asc\";\n body.replaceChildren(...sorted.map(row => {\n const line = document.createElement(\"tr\");\n for (const columnspec of datasetvalue.columns.slice(0, 6)) {\n const value = document.createElement(\"td\");\n value.textContent = row[columnspec.key] ?? \"\";\n line.append(value);\n }\n return line;\n }));\n });\n headerrow.append(cell);\n }\n grid.append(headerrow);\n const body = document.createElement(\"tbody\");\n for (const row of datasetvalue.rows.slice(0, 5)) {\n const line = document.createElement(\"tr\");\n for (const column of datasetvalue.columns.slice(0, 6)) {\n const cell = document.createElement(\"td\");\n cell.textContent = row[column.key] ?? \"\";\n line.append(cell);\n }\n body.append(line);\n }\n grid.append(body);\n card.append(grid);\n if (active) {\n const actions = document.createElement(\"p\");\n for (const format of [\"csv\", \"json\", \"excel\"] as const) {\n actions.append(\" \", button(`Export ${format}`, async () => {\n const artifact = await request({ kind: \"exportdataset\", datasetid: datasetvalue.id, format }) as { name: string; checksum: string };\n status(`Exported ${datasetvalue.name} to ${artifact.name} with checksum ${artifact.checksum}.`);\n await refresh();\n }));\n }\n card.append(actions);\n }\n datasetsroot.append(card);\n }\n const provenances = context.provenances ?? [];\n if (provenances.length > 0) {\n const list = document.createElement(\"ul\");\n for (const record of provenances.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.name}: rows ${record.rowstart}\u2013${record.rowend} \u00B7 checksum ${record.checksum} \u00B7 source ${record.url}`;\n list.append(item);\n }\n datasetsroot.append(list);\n }\n const sheetendpoints = context.sheetendpoints ?? [];\n if (sheetendpoints.length > 0) {\n const sheets = document.createElement(\"p\");\n sheets.textContent = `sheet endpoints: ${sheetendpoints.map(config => `${config.origin} ${config.granted ? \"granted\" : \"not granted\"}`).join(\" \u00B7 \")}`;\n datasetsroot.append(sheets);\n }\n if (active) {\n const importer = document.createElement(\"div\");\n importer.className = \"panel\";\n const csvinput = document.createElement(\"textarea\");\n csvinput.rows = 3;\n csvinput.placeholder = \"Paste reviewed csv content for a fill loop (header line first).\";\n const nameinput = document.createElement(\"input\");\n nameinput.placeholder = \"dataset name (optional)\";\n const mappinginput = document.createElement(\"input\");\n mappinginput.placeholder = \"column mapping json (optional, csv header \u2192 target)\";\n importer.append(csvinput, nameinput, mappinginput, \" \", button(\"Import csv\", async () => {\n let mapping: Record<string, string> = {};\n if (mappinginput.value.trim()) {\n try { mapping = JSON.parse(mappinginput.value) as Record<string, string>; } catch { status(\"The column mapping must be a json object.\", true); return; }\n }\n const imported = await request({ kind: \"importcsv\", csv: csvinput.value, name: nameinput.value, mapping }) as { name: string; rows: number };\n status(`Imported ${imported.rows} rows as dataset ${imported.name} for fill loops.`);\n await refresh();\n }));\n datasetsroot.append(importer);\n }\n}\n\n/** Renders the files, clipboard and downloads surface: the batch download queue with per file states and pause, resume and verify actions, mime interception rules with origin grants, clipboard consent prompts with the requesting step, the netlog viewer with step correlation filters and redaction notices, the quarantine list with scan verdicts and release actions, capture naming previews, cleanup policy editing, artifact inventories and copyscreen results. */\nfunction renderfiles(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; plan?: agentplan; downloads?: downloadrecord[]; mimefilters?: mimefilter[]; clipconsents?: clipboardconsentrecord[]; clips?: clipentry[]; netlogs?: netlogrecord[]; quarantines?: quarantineentry[]; capturecounters?: Array<{ taskid: string; counters: Record<string, number>; at: number }>; cleanuprules?: cleanuprule[]; cleanupruns?: cleanuprun[]; inventory?: artifactinventoryentry[]; scanhooks?: Array<{ scanner: string; endpoint: string; origin: string; configuredat: number; granted: boolean }> }): void {\n if (!filesroot) return;\n filesroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const downloads = context.downloads ?? [];\n if (downloads.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n const states = [\"queued\", \"running\", \"paused\", \"complete\", \"failed\"] as const;\n head.textContent = `batch download queue: ${downloads.length} file${downloads.length === 1 ? \"\" : \"s\"} (${states.map(state => `${downloads.filter(item => item.state === state).length} ${state}`).filter(part => !part.startsWith(\"0 \")).join(\" \u00B7 \") || \"none\"})`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const record of downloads.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.filename} \u00B7 ${record.state}${record.bytes !== undefined ? ` \u00B7 ${record.bytes} bytes` : \"\"}${record.checksum !== undefined ? ` \u00B7 checksum ${record.checksum}` : \"\"}${record.path !== undefined ? ` \u00B7 ${record.path}` : \"\"}`;\n if (active) {\n item.append(\" \", button(\"Pause\", () => request({ kind: \"downloadaction\", id: record.id, action: \"pause\" }).then(() => refresh()).then(() => status(`Paused the download of ${record.filename}.`)), record.state !== \"running\"));\n item.append(\" \", button(\"Resume\", () => request({ kind: \"downloadaction\", id: record.id, action: \"resume\" }).then(() => refresh()).then(() => status(`Resumed the download of ${record.filename}.`)), record.state !== \"paused\"));\n item.append(\" \", button(\"Verify\", () => request({ kind: \"downloadaction\", id: record.id, action: \"verify\" }).then(value => { const output = value as { summary: string }; status(output.summary); return refresh(); })));\n }\n list.append(item);\n }\n card.append(list);\n filesroot.append(card);\n }\n const filters = context.mimefilters ?? [];\n if (filters.length > 0) {\n const filter = filters[0]!;\n const card = document.createElement(\"p\");\n card.textContent = `mime interception: include ${filter.include.join(\", \")} \u00B7 exclude ${filter.exclude.join(\", \") || \"none\"} \u00B7 ${filter.default} default for unlisted mime types${context.session?.origin ? ` \u00B7 armed inside the ${context.session.origin} origin grants` : \"\"}`;\n filesroot.append(card);\n }\n const consents = (context.clipconsents ?? []).filter(record => record.approved === undefined);\n for (const consent of consents.slice(0, 4)) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n card.textContent = `Clipboard read consent ${consent.id} waits for your approval: step ${consent.stepid} on ${consent.origin} asked to read the clipboard \u2014 \"${consent.prompt}\".`;\n if (active) {\n card.append(\" \", button(\"Approve read\", async () => { await request({ kind: \"approveclipconsent\", id: consent.id, approved: true }); status(`Clipboard read consent ${consent.id} approved; run the step again to read once.`); await refresh(); }));\n card.append(\" \", button(\"Decline\", async () => { await request({ kind: \"approveclipconsent\", id: consent.id, approved: false }); status(`Clipboard read consent ${consent.id} declined.`); await refresh(); }));\n }\n filesroot.append(card);\n }\n const netlogs = context.netlogs ?? [];\n if (netlogs.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n const steps = [...new Set(netlogs.map(record => record.stepid))];\n head.textContent = `network log: ${netlogs.length} record${netlogs.length === 1 ? \"\" : \"s\"} correlated with ${steps.length} step${steps.length === 1 ? \"\" : \"s\"} (${steps.slice(0, 4).join(\", \")}${steps.length > 4 ? \"\u2026\" : \"\"})`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const record of netlogs.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${record.method} ${record.url} \u00B7 ${record.status} \u00B7 ${record.timing}ms \u00B7 request ${record.requestid ?? \"?\"} \u00B7 step ${record.stepid}`;\n list.append(item);\n }\n card.append(list);\n if (active) card.append(button(\"Export netlog (header values redacted)\", async () => { const exported = await request({ kind: \"exportnetlog\" }) as { records: unknown[]; redaction: string }; status(`Exported ${exported.records.length} netlog records; ${exported.redaction}.`); }));\n filesroot.append(card);\n }\n const quarantines = context.quarantines ?? [];\n if (quarantines.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `quarantine: ${quarantines.length} file${quarantines.length === 1 ? \"\" : \"s\"} outside the downloads folder (${quarantines.filter(entry => entry.scan === \"pending\").length} awaiting scan verdicts)`;\n card.append(head);\n const list = document.createElement(\"ul\");\n for (const entry of quarantines.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `${entry.path} \u00B7 scan ${entry.scan}${entry.release !== undefined ? ` \u00B7 released under ${entry.release}` : \"\"} \u00B7 ${entry.reason}`;\n if (active && entry.release === undefined && entry.scan === \"clean\") item.append(\" \", button(\"Release\", async () => { await request({ kind: \"releasequarantine\", id: entry.id }); status(`Released ${entry.path} from quarantine under the clean scan verdict.`); await refresh(); }));\n list.append(item);\n }\n card.append(list);\n filesroot.append(card);\n }\n const planid = context.plan?.id;\n const counters = (context.capturecounters ?? []).find(item => item.taskid === planid);\n if (counters) {\n const card = document.createElement(\"p\");\n card.textContent = `capture naming for task ${counters.taskid}: ${Object.entries(counters.counters).map(([step, sequence]) => `${step} \u2192 ${counters.taskid}-${step}-${sequence}`).join(\" \u00B7 \")}`;\n filesroot.append(card);\n }\n const rules = context.cleanuprules ?? [];\n const rulecard = document.createElement(\"div\");\n rulecard.className = \"panel\";\n const rulehead = document.createElement(\"p\");\n rulehead.textContent = `cleanup policy: ${rules.length > 0 ? rules.map(rule => `older than ${rule.age}ms of kind ${rule.kind} keep ${rule.keep}`).join(\" \u00B7 \") : \"no rule set stored yet\"}`;\n rulecard.append(rulehead);\n const runs = context.cleanupruns ?? [];\n if (runs.length > 0) {\n const lastrun = runs[0]!;\n const runline = document.createElement(\"p\");\n runline.textContent = `last sweep: removed ${lastrun.removed}, kept ${lastrun.kept} under ${lastrun.rules} rule${lastrun.rules === 1 ? \"\" : \"s\"}`;\n rulecard.append(runline);\n }\n if (active) {\n const ageinput = document.createElement(\"input\");\n ageinput.placeholder = \"age window in ms\";\n const kindinput = document.createElement(\"input\");\n kindinput.placeholder = \"artifact kind (any matches all)\";\n const keepinput = document.createElement(\"input\");\n keepinput.placeholder = \"keep policy: none, latest or all\";\n rulecard.append(ageinput, kindinput, keepinput, \" \", button(\"Add cleanup rule\", async () => {\n const age = Number(ageinput.value);\n const rule = { age, kind: kindinput.value.trim() || \"any\", keep: keepinput.value.trim() || \"none\" } as cleanuprule;\n const stored = await request({ kind: \"setcleanuprules\", rules: [...rules, rule] }) as { rules: number };\n status(`Stored ${stored.rules} reviewed cleanup rule${stored.rules === 1 ? \"\" : \"s\"}; ages stay your choice with no code ceiling.`);\n await refresh();\n }));\n }\n filesroot.append(rulecard);\n const inventory = context.inventory ?? [];\n if (inventory.length > 0) {\n const card = document.createElement(\"p\");\n card.textContent = `artifact inventory: ${inventory.slice(0, 5).map(entry => `${entry.name} (${entry.kind}, ${entry.size} characters, ${Math.max(0, Math.round((Date.now() - entry.at) / 60000))} minute${Math.round((Date.now() - entry.at) / 60000) === 1 ? \"\" : \"s\"} old)`).join(\" \u00B7 \")}${inventory.length > 5 ? ` and ${inventory.length - 5} more` : \"\"}`;\n filesroot.append(card);\n }\n const screens = (context.clips ?? []).filter(entry => entry.kind === \"screen\").slice(0, 2);\n for (const screen of screens) {\n const card = document.createElement(\"p\");\n card.textContent = `copyscreen result: ${screen.length} characters of png data with payload hash ${screen.hash} routed to the clipboard destination.`;\n filesroot.append(card);\n }\n const hooks = context.scanhooks ?? [];\n if (active) {\n const hookcard = document.createElement(\"div\");\n hookcard.className = \"panel\";\n const hookhead = document.createElement(\"p\");\n hookhead.textContent = hooks.length > 0 ? `scan hooks: ${hooks.map(hook => `${hook.scanner} at ${hook.origin} ${hook.granted ? \"granted\" : \"not granted\"}`).join(\" \u00B7 \")}` : \"scan hooks: none configured; scan verdicts stay pending without one.\";\n hookcard.append(hookhead);\n const scannerinput = document.createElement(\"input\");\n scannerinput.placeholder = \"scanner name\";\n const endpointinput = document.createElement(\"input\");\n endpointinput.placeholder = \"https://scanner.example/verdict\";\n hookcard.append(scannerinput, endpointinput, \" \", button(\"Configure scan hook\", async () => {\n await request({ kind: \"configurescanhook\", scanner: scannerinput.value, endpoint: endpointinput.value });\n status(`Scan hook ${scannerinput.value} configured; hook failures stay pending verdicts.`);\n await refresh();\n }));\n filesroot.append(hookcard);\n }\n}\n\n/** One capture metadata card of the gallery; bytes stay out of the context and load per capture on demand. */\ntype capturemeta = { id: string; runid: string; stepid: string; kind: string; format: string; width: number; height: number; capturedat: number; name?: string; annotated?: boolean; target?: string; bytesexpired?: boolean };\n\n/** Loads the bytes of one stored capture on demand; expired bytes resolve to undefined. */\nasync function capturebytes(id: string): Promise<string | undefined> {\n try {\n const record = await request({ kind: \"capturebytes\", id }) as { bytes: string };\n return record.bytes;\n } catch { return undefined; }\n}\n\n/** Opens any capture full size with its metadata, download and clipboard copy actions. */\nfunction opencapture(record: capturemeta): void {\n if (!capturesroot) return;\n const viewer = document.createElement(\"div\");\n viewer.className = \"panel captureviewer\";\n const head = document.createElement(\"p\");\n head.textContent = `${record.kind} \u00B7 ${record.format} \u00B7 ${record.width}\u00D7${record.height} px \u00B7 step ${record.stepid}${record.annotated ? \" \u00B7 annotated evidence\" : \"\"}${record.name !== undefined ? ` \u00B7 ${record.name}` : \"\"}`;\n viewer.append(head);\n const image = document.createElement(\"img\");\n image.alt = `Capture ${record.id} of kind ${record.kind}`;\n image.src = \"\";\n void capturebytes(record.id).then(bytes => { if (bytes) image.src = bytes; else viewer.append(Object.assign(document.createElement(\"p\"), { textContent: \"The capture bytes expired from the retention window; the metadata stays for the audit trail.\" })); });\n viewer.append(image);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Download\", () => request({ kind: \"downloadcapture\", id: record.id }).then(() => status(`Downloaded capture ${record.id} through the reviewed download flow.`))));\n actions.append(button(\"Copy to clipboard\", () => request({ kind: \"copycapture\", id: record.id }).then(() => status(`Copied capture ${record.id} to the clipboard.`))));\n actions.append(button(\"Close\", async () => viewer.remove()));\n viewer.append(actions);\n capturesroot.append(viewer);\n}\n\n\n/** One media record metadata card; bytes stay out of the context and load per record on demand. */\ntype mediameta = { id: string; runid: string; stepid: string; at: number; bytesexpired?: boolean } & Record<string, unknown>;\n\n/** Loads the bytes of one stored media record on demand; expired bytes resolve to undefined. */\nasync function mediabytes(id: string): Promise<string | undefined> {\n try {\n const record = await request({ kind: \"mediabytes\", id }) as { bytes: string };\n return record.bytes;\n } catch { return undefined; }\n}\n\n/** Plays an ordered frame sequence as a lapse: the image cycles through the frame bytes at the recorded interval. */\nfunction playframes(frameids: string[], interval: number, label: string): void {\n if (!mediaroot) return;\n const viewer = document.createElement(\"div\");\n viewer.className = \"panel captureviewer\";\n const head = document.createElement(\"p\");\n head.textContent = `${label}: ${frameids.length} frames at ${interval} millisecond intervals`;\n viewer.append(head);\n const image = document.createElement(\"img\");\n image.alt = \"Lapse frame\";\n viewer.append(image);\n let index = 0;\n let stopped = false;\n const show = async (): Promise<void> => {\n if (stopped) return;\n const bytes = await capturebytes(frameids[index] ?? \"\");\n if (bytes) image.src = bytes;\n index = (index + 1) % Math.max(1, frameids.length);\n };\n void show();\n const timer = window.setInterval(() => { void show(); }, Math.max(100, interval));\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Stop\", async () => { stopped = true; window.clearInterval(timer); viewer.remove(); }));\n viewer.append(actions);\n mediaroot.append(viewer);\n}\n\n/** Renders the media tab: the recording indicator, recording consents, pdf reports, image batches with match counts, video frames and lapse playback, recordings with play, download and delete controls, stream probe results, assets and the convertimage and makethumbs actions on stored captures. */\nfunction rendermedia(context: { session?: { stoppedat?: number; expiresat: number }; media?: mediameta[]; imagebatches?: Array<{ id: string; runid: string; stepid: string; images: Array<{ url: string; alt: string; width: number; height: number; bytes: number; mime: string }>; matched: number; downloaded: number; at: number }>; recordingconsents?: Array<{ id: string; prompt: string; origin: string; stepid: string; approved?: boolean; usedat?: number; at: number }>; recordingactive?: Array<{ id: string; kind: string; scope: string; startedat: number; stopat: number }>; recordingwindow?: number; captures?: capturemeta[] }): void {\n if (!mediaroot) return;\n mediaroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n if ((context.recordingactive ?? []).length > 0) {\n const indicator = document.createElement(\"p\");\n indicator.className = \"recordingindicator\";\n indicator.textContent = `\u25CF recording in progress: ${context.recordingactive?.map(item => `${item.kind} of ${item.scope} scope`).join(\", \")}`;\n mediaroot.append(indicator);\n }\n for (const consent of (context.recordingconsents ?? []).filter(item => item.approved === undefined)) {\n const card = document.createElement(\"div\");\n card.className = \"panel recordingcard\";\n const head = document.createElement(\"p\");\n head.textContent = `Recording consent ${consent.id} for step ${consent.stepid} on ${consent.origin}: ${consent.prompt}`;\n card.append(head);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve recording\", () => request({ kind: \"approverecordingconsent\", id: consent.id, approved: true }).then(() => status(`Recording consent ${consent.id} approved; rerun the recording step.`)).then(refresh)));\n actions.append(button(\"Decline\", () => request({ kind: \"approverecordingconsent\", id: consent.id, approved: false }).then(() => status(`Recording consent ${consent.id} declined.`)).then(refresh)));\n card.append(actions);\n mediaroot.append(card);\n }\n const records = context.media ?? [];\n const pdfs = records.filter(record => record.pages !== undefined);\n const recordings = records.filter(record => record.startedat !== undefined);\n const frames = records.filter(record => record.timestamp !== undefined);\n const canvases = records.filter(record => record.context !== undefined);\n const streams = records.filter(record => record.tracks !== undefined);\n const assets = records.filter(record => record.url !== undefined && record.kind !== undefined && (record.kind === \"favicon\" || record.kind === \"logo\"));\n if (pdfs.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `pdf reports: ${pdfs.length}`;\n card.append(head);\n for (const pdf of pdfs) {\n const row = document.createElement(\"p\");\n row.textContent = `${String(pdf.name ?? pdf.id)} \u00B7 ${String(pdf.pages)} page${String(pdf.pages) === \"1\" ? \"\" : \"s\"} \u00B7 ${String(pdf.pagewidth)}\u00D7${String(pdf.pageheight)} pt${pdf.landscape === true ? \" \u00B7 landscape\" : \"\"} \u00B7 ${String(pdf.bytes)} bytes${pdf.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n card.append(row);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Download pdf\", () => request({ kind: \"downloadmedia\", id: String(pdf.id) }).then(() => status(`Downloaded the pdf report ${String(pdf.name ?? pdf.id)} through the reviewed download flow.`)), !active || pdf.bytesexpired === true));\n card.append(actions);\n }\n mediaroot.append(card);\n }\n for (const batch of context.imagebatches ?? []) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `image batch of step ${batch.stepid}: ${batch.matched} of ${batch.images.length} observed images matched, ${batch.downloaded} downloaded`;\n card.append(head);\n const list = document.createElement(\"ol\");\n list.className = \"audit\";\n for (const image of batch.images.slice(0, 12)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${image.url}${image.alt ? ` \u00B7 ${image.alt}` : \"\"} \u00B7 ${image.width}\u00D7${image.height} \u00B7 ${image.bytes} bytes \u00B7 ${image.mime}`;\n list.append(entry);\n }\n card.append(list);\n mediaroot.append(card);\n }\n if (frames.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `video frames: ${frames.length}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const frame of frames) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${String(frame.source)} \u00B7 ${String(frame.timestamp)}s${frame.poster === true ? \" \u00B7 poster\" : \"\"}${frame.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Video frame ${String(frame.id)}`;\n if (frame.bytesexpired !== true) void mediabytes(String(frame.id)).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n grid.append(cell);\n }\n card.append(grid);\n mediaroot.append(card);\n }\n const timelapse = (context.captures ?? []).filter(record => record.kind === \"timelapse\");\n if (timelapse.length > 1) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `time lapse sequences: ${timelapse.length} frames`;\n card.append(head);\n card.append(button(\"Play lapse sequence\", async () => {\n const ordered = await request({ kind: \"capturereport\" }) as { records: Array<{ id: string; kind: string; capturedat: number }> };\n const ids = ordered.records.filter(record => record.kind === \"timelapse\").sort((left, right) => left.capturedat - right.capturedat).map(record => record.id);\n playframes(ids, 800, \"time lapse\");\n }));\n mediaroot.append(card);\n }\n if (canvases.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `canvas captures: ${canvases.length}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const canvas of canvases) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${String(canvas.element)} \u00B7 ${String(canvas.context)} \u00B7 ${String(canvas.width)}\u00D7${String(canvas.height)}${canvas.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Canvas capture ${String(canvas.id)}`;\n if (canvas.bytesexpired !== true) void mediabytes(String(canvas.id)).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n grid.append(cell);\n }\n card.append(grid);\n mediaroot.append(card);\n }\n for (const stream of streams) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `stream probe ${String(stream.label || stream.id)}: ${String(stream.tracks)} track${String(stream.tracks) === \"1\" ? \"\" : \"s\"} \u00B7 ${stream.live === true ? \"live\" : \"ended\"}`;\n card.append(head);\n const detail = stream.detail as Array<{ kind: string; label: string; width?: number; height?: number; framerate?: number; state: string }> | undefined;\n if (Array.isArray(detail)) {\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const track of detail) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${track.kind} track${track.label ? ` ${track.label}` : \"\"}${track.width !== undefined ? ` \u00B7 ${track.width}\u00D7${track.height}` : \"\"}${track.framerate !== undefined ? ` \u00B7 ${Math.round(track.framerate)} fps` : \"\"} \u00B7 ${track.state}`;\n list.append(entry);\n }\n card.append(list);\n }\n mediaroot.append(card);\n }\n if (assets.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `page assets: ${assets.filter(asset => asset.kind === \"favicon\").length} favicon and ${assets.filter(asset => asset.kind === \"logo\").length} logo entries`;\n card.append(head);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const asset of assets.slice(0, 12)) {\n const entry = document.createElement(\"li\");\n entry.textContent = `${String(asset.kind)} \u00B7 ${String(asset.url)}${asset.sizes !== undefined ? ` \u00B7 ${String(asset.sizes)}` : \"\"}`;\n list.append(entry);\n }\n card.append(list);\n mediaroot.append(card);\n }\n for (const recording of recordings) {\n const card = document.createElement(\"div\");\n card.className = \"panel recordingcard\";\n const head = document.createElement(\"p\");\n head.textContent = `${String(recording.kind)} recording ${String(recording.id)} \u00B7 ${String(recording.scope)} scope \u00B7 ${String(recording.duration ?? 0)} ms \u00B7 ${Array.isArray(recording.frames) ? String(recording.frames.length) : \"0\"} frames \u00B7 manifest ${String(recording.bytes ?? 0)} bytes${recording.bytesexpired === true ? \" \u00B7 bytes expired\" : \"\"}`;\n card.append(head);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n const frames = Array.isArray(recording.frames) ? recording.frames as string[] : [];\n if (String(recording.kind) === \"screen\" && frames.length > 0) {\n actions.append(button(\"Play frames\", async () => {\n const state = await request({ kind: \"recordingframes\", id: String(recording.id) }) as { frames: string[]; interval: number };\n playframes(state.frames, state.interval, `screen recording ${String(recording.id)}`);\n }));\n }\n actions.append(button(\"Download manifest\", () => request({ kind: \"downloadrecording\", id: String(recording.id) }).then(() => status(`Downloaded the recording manifest ${String(recording.id)} through the reviewed download flow.`)), !active));\n actions.append(button(\"Delete\", () => request({ kind: \"deleterecording\", id: String(recording.id) }).then(() => status(`Deleted the recording ${String(recording.id)}.`)).then(refresh), !active));\n card.append(actions);\n mediaroot.append(card);\n }\n const stored = (context.captures ?? []).filter(record => record.bytesexpired !== true).slice(0, 12);\n if (stored.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = \"capture transforms: convertimage and makethumbs actions on stored captures\";\n card.append(head);\n for (const record of stored) {\n const row = document.createElement(\"div\");\n row.className = \"actions\";\n const label = document.createElement(\"p\");\n label.textContent = `${record.kind} ${record.id} (${record.format})`;\n row.append(label);\n for (const target of [\"png\", \"jpeg\", \"webp\"] as const) {\n if (target !== record.format) row.append(button(`\u2192 ${target}`, () => request({ kind: \"convertcapture\", id: record.id, target }).then(() => status(`Converted capture ${record.id} to ${target}.`)).then(refresh), !active));\n }\n row.append(button(\"thumbnail\", () => request({ kind: \"thumbcapture\", id: record.id, size: 240, fit: \"cover\", suffix: \"thumb\" }).then(() => status(`Thumbnailed capture ${record.id}.`)).then(refresh), !active));\n card.append(row);\n }\n mediaroot.append(card);\n }\n if (records.length === 0 && (context.imagebatches ?? []).length === 0 && (context.recordingactive ?? []).length === 0) {\n mediaroot.append(Object.assign(document.createElement(\"p\"), { textContent: \"No media stored yet; run a capturepdf, recordscreen, captureaudio, captureframe, downloadimages, shotcanvas, probestream, readmedia, readassets, timelapse, convertimage or makethumbs step.\" }));\n }\n}\n/** Renders the capture gallery: the policy toggle, stitch progress, thumbnails per run, contact sheet cells and before and after pairs with a divider. */\nfunction rendercaptures(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; outcomes?: stepoutcome[]; captures?: capturemeta[]; capturepairs?: shotpair[]; capturepolicy?: string; stitchprogress?: Array<{ stepid: string; done: number; total: number }> }): void {\n if (!capturesroot) return;\n capturesroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const policy = (context.capturepolicy ?? \"manual\") as capturepolicy;\n const policyrow = document.createElement(\"div\");\n policyrow.className = \"actions\";\n const policylabel = document.createElement(\"p\");\n policylabel.textContent = `capture policy: ${policy}${policy === \"beforeafter\" ? \" \u2014 state pairs wrap every page moving action\" : \"\"}`;\n policyrow.append(policylabel);\n for (const mode of [\"off\", \"manual\", \"annotated\", \"beforeafter\"] as const) {\n policyrow.append(button(mode, async () => { await request({ kind: \"setcapturepolicy\", mode }); status(`Capture policy set to ${mode}.`); await refresh(); }, !active || mode === policy));\n }\n capturesroot.append(policyrow);\n for (const progress of context.stitchprogress ?? []) {\n const bar = document.createElement(\"progress\");\n bar.max = Math.max(1, progress.total);\n bar.value = progress.done;\n const label = document.createElement(\"p\");\n label.textContent = `stitching full page capture of step ${progress.stepid}: tile ${progress.done} of ${progress.total}`;\n capturesroot.append(label, bar);\n }\n const captures = context.captures ?? [];\n if (captures.length === 0 && (context.capturepairs ?? []).length === 0) {\n capturesroot.append(Object.assign(document.createElement(\"p\"), { textContent: \"No captures stored yet; run a shotview, shotfullpage, shotelement, shotregion or contactsheet step.\" }));\n return;\n }\n const runs = [...new Set(captures.map(record => record.runid))];\n for (const run of runs) {\n const runcaptures = captures.filter(record => record.runid === run);\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `run ${run}: ${runcaptures.length} capture${runcaptures.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n const grid = document.createElement(\"div\");\n grid.className = \"capturegrid\";\n for (const record of runcaptures) {\n const cell = document.createElement(\"button\");\n cell.type = \"button\";\n cell.className = record.annotated ? \"capturecard annotated\" : \"capturecard\";\n const label = document.createElement(\"span\");\n label.textContent = `${record.kind} \u00B7 ${record.format} \u00B7 ${record.width}\u00D7${record.height}${record.annotated ? \" \u00B7 annotated\" : \"\"}${record.bytesexpired ? \" \u00B7 bytes expired\" : \"\"}`;\n cell.append(label);\n const image = document.createElement(\"img\");\n image.alt = `Capture ${record.id} of kind ${record.kind}`;\n if (!record.bytesexpired) void capturebytes(record.id).then(bytes => { if (bytes) image.src = bytes; });\n cell.append(image);\n cell.addEventListener(\"click\", () => opencapture(record));\n grid.append(cell);\n if (record.kind === \"contactsheet\") {\n const cells = (context.outcomes ?? []).find(outcome => outcome.stepid === record.stepid && outcome.details?.cells !== undefined)?.details?.cells as Array<{ index: number; selector: string; caption: string }> | undefined;\n for (const sheetcell of cells ?? []) {\n const cellbutton = document.createElement(\"button\");\n cellbutton.type = \"button\";\n cellbutton.className = \"secondary\";\n cellbutton.textContent = sheetcell.caption || sheetcell.selector;\n cellbutton.addEventListener(\"click\", () => opencapture(record));\n grid.append(cellbutton);\n }\n }\n }\n card.append(grid);\n capturesroot.append(card);\n }\n for (const pair of context.capturepairs ?? []) {\n const card = document.createElement(\"div\");\n card.className = \"panel pairview\";\n const head = document.createElement(\"p\");\n head.textContent = `state pair around the ${pair.actionkind} action${pair.target !== undefined ? ` on ${pair.target}` : \"\"}${pair.domsnapshotid !== undefined ? ` \u00B7 dom snapshot ${pair.domsnapshotid}` : \"\"}`;\n card.append(head);\n const row = document.createElement(\"div\");\n row.className = \"pairrow\";\n const before = document.createElement(\"img\");\n before.alt = `Before shot ${pair.beforeid}`;\n const after = document.createElement(\"img\");\n after.alt = `After shot ${pair.afterid}`;\n void capturebytes(pair.beforeid).then(bytes => { if (bytes) before.src = bytes; });\n void capturebytes(pair.afterid).then(bytes => { if (bytes) after.src = bytes; });\n row.append(before, after);\n const divider = document.createElement(\"input\");\n divider.type = \"range\";\n divider.min = \"0\";\n divider.max = \"100\";\n divider.value = \"50\";\n divider.setAttribute(\"aria-label\", \"Before and after divider\");\n divider.addEventListener(\"input\", () => { before.style.width = `${100 - Number(divider.value)}%`; after.style.width = `${Number(divider.value)}%`; });\n card.append(row, divider);\n capturesroot.append(card);\n }\n}\n\n\n/** Renders the traffic control view: the active block, mock and rewrite rule lists with live hit counts, the cookie operations with values redacted, the oauth flow state with provider and scopes, the stored token metadata per provider, the proxy state with a manual revert button, the rate limit waits with reset times, the api key consent scope and the multipart upload progress of postfiles steps. */\nfunction rendertraffic(context: { session?: { stoppedat?: number; expiresat: number }; traffic?: { blocks: Array<{ id: string; urlpattern: string; hits: number; revertedat?: number; stepid: string }>; mocks: Array<{ id: string; urlpattern: string; status: number; hits: number; revertedat?: number }>; rewrites: Array<{ id: string; urlpattern: string; name: string; operation: string; value?: string; hits: number; revertedat?: number }>; cookies: Array<{ id: string; kind: string; domain: string; names: string[]; at: number }>; proxies: Array<{ id: string; scheme: string; host: string; port: number; bypass: string[]; appliedat: number; revertedat?: number }>; ratelimits: Array<{ origin: string; remaining?: number; limit?: number; resetat: number }> }; tokens?: { tokens: Array<{ id: string; provider: string; origin: string; scopes: string[]; expiresat: number; refreshedat?: number; revokedat?: number }> }; authflows?: Array<{ provider: string; redirectorigin: string; scopes: string[]; stepid: string; tabid: number; stage: string }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; activerules?: number; progress?: planprogress }): void {\n if (!trafficroot) return;\n trafficroot.replaceChildren();\n const head = document.createElement(\"p\");\n head.textContent = `active traffic rules: ${context.activerules ?? 0} (every rule reverts at run end)`;\n trafficroot.append(head);\n const traffic = context.traffic;\n if (traffic === undefined) return;\n if ( (traffic.blocks.length === 0 && traffic.mocks.length === 0 && traffic.rewrites.length === 0 && traffic.cookies.length === 0 && traffic.proxies.length === 0 && traffic.ratelimits.length === 0)) {\n trafficroot.append(Object.assign(document.createElement(\"p\"), { className: \"muted\", textContent: \"No traffic rule has been applied yet; blockrequest, mockresponse, rewriteheaders, setcookies, clearcookies, routeproxy, postform and postfiles steps land here.\" }));\n }\n for (const rule of traffic.blocks) {\n const row = document.createElement(\"p\");\n row.textContent = `block ${rule.urlpattern} \u00B7 ${rule.hits} blocked \u00B7 ${rule.revertedat !== undefined ? \"reverted\" : \"active\"} \u00B7 step ${rule.stepid}`;\n trafficroot.append(row);\n }\n for (const spec of traffic.mocks) {\n const row = document.createElement(\"p\");\n row.textContent = `mock ${spec.urlpattern} \u2192 ${spec.status} \u00B7 ${spec.hits} served \u00B7 ${spec.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n }\n for (const rule of traffic.rewrites) {\n const row = document.createElement(\"p\");\n row.textContent = `rewrite ${rule.operation} ${rule.name} on ${rule.urlpattern} \u00B7 ${rule.hits} applied \u00B7 ${rule.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n }\n for (const route of traffic.proxies) {\n const row = document.createElement(\"p\");\n row.textContent = `proxy ${route.scheme}://${route.host}:${route.port} \u00B7 bypass ${route.bypass.join(\", \")} \u00B7 ${route.revertedat !== undefined ? \"reverted\" : \"active\"}`;\n trafficroot.append(row);\n if (route.revertedat === undefined) {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Revert proxy route\", () => request({ kind: \"revertproxyroute\", id: route.id }).then(() => status(`Proxy route ${route.id} reverted; the previous routing state is restored.`)).then(refresh)));\n trafficroot.append(actions);\n }\n }\n for (const read of traffic.ratelimits) {\n const row = document.createElement(\"p\");\n row.textContent = `rate limit ${read.origin} \u00B7 ${read.remaining ?? \"?\"} of ${read.limit ?? \"?\"} remaining \u00B7 resets ${new Date(read.resetat).toLocaleTimeString()}`;\n trafficroot.append(row);\n }\n for (const flow of context.authflows ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `oauth ${flow.provider} \u00B7 scopes ${flow.scopes.join(\", \")} \u00B7 redirect ${flow.redirectorigin} \u00B7 ${flow.stage} in tab ${flow.tabid}`;\n trafficroot.append(row);\n }\n for (const token of context.tokens?.tokens ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `token ${token.provider} \u00B7 scopes ${token.scopes.join(\", \")} \u00B7 ${token.revokedat !== undefined ? \"revoked\" : `expires ${new Date(token.expiresat).toLocaleTimeString()}`}${token.refreshedat !== undefined ? \" \u00B7 refreshed\" : \"\"}`;\n trafficroot.append(row);\n if (token.revokedat === undefined) {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Revoke token\", () => request({ kind: \"revoketokens\", tokenids: [token.id], reason: \"review panel demand\" }).then(() => status(`Token ${token.id} of ${token.provider} revoked.`)).then(refresh)));\n trafficroot.append(actions);\n }\n }\n for (const op of traffic.cookies.slice(0, 8)) {\n const row = document.createElement(\"p\");\n row.textContent = `cookie ${op.kind} \u00B7 ${op.domain} \u00B7 ${op.names.length === 0 ? \"all cookies\" : op.names.join(\", \")} \u00B7 ${new Date(op.at).toLocaleTimeString()} (values never stored)`;\n trafficroot.append(row);\n }\n for (const ref of context.apikeys ?? []) {\n const row = document.createElement(\"p\");\n row.textContent = `api key ${ref.name} \u00B7 header ${ref.header} \u00B7 scoped to ${ref.origins.join(\", \")}${ref.lastuse !== undefined ? ` \u00B7 last use ${new Date(ref.lastuse).toLocaleTimeString()}` : \" \u00B7 unused\"}`;\n trafficroot.append(row);\n }\n const uploads = (context.progress?.outcomes ?? []).filter(outcome => outcome.details?.upload !== undefined).slice(-4);\n for (const outcome of uploads) {\n const entry = outcome.details?.upload as { chunk: number; chunks: number; uploaded: number; bytes: number };\n const row = document.createElement(\"p\");\n row.textContent = `upload chunk ${entry.chunk} of ${entry.chunks} \u00B7 ${entry.uploaded} of ${entry.bytes} bytes`;\n trafficroot.append(row);\n }\n}\n\n/** Renders the network calls view: every outbound call of the run with status, duration, retries and byte counts, expandable header names, parsed fields and errors, fetch consent prompts with name and value, stream progress bars, origin, method and status class filters, endpoint and api key configuration and the reviewed call list export. */\nfunction rendercalls(context: { session?: { stoppedat?: number; expiresat: number }; calls?: Array<{ id: string; runid: string; stepid: string; kind: string; url: string; origin: string; method: string; status: number; statusclass: string; duration: number; retries: number; bytes: number; headernames: string[]; endpoint?: string; bodyexpired?: boolean; fields?: Array<{ name: string; path: string; kind: string; value?: unknown; missing?: boolean }>; errors?: string[]; streambytes?: number }>; fetchconsents?: Array<{ id: string; origin: string; headers: Array<{ name: string; value: string }>; approved?: boolean; expiresat: number; at: number }>; endpoints?: Array<{ name: string; method: string; url: string; version: number; headers?: Record<string, string>; schema?: { fields: Array<{ name: string; kind: string; required?: boolean; default?: string | number | boolean }> } }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; callretention?: number; fetchesactive?: number }): void {\n if (!callsroot) return;\n callsroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n for (const consent of (context.fetchconsents ?? []).filter(item => item.approved === undefined)) {\n const card = document.createElement(\"div\");\n card.className = \"panel consentcard\";\n const head = document.createElement(\"p\");\n head.textContent = `Fetch consent ${consent.id} for ${consent.origin}: review every custom header before it is sent.`;\n card.append(head);\n for (const header of consent.headers) {\n const row = document.createElement(\"p\");\n row.textContent = `${header.name}: ${header.value}`;\n card.append(row);\n }\n const note = document.createElement(\"p\");\n note.className = \"muted\";\n note.textContent = `The prompt appears once per origin and expires ${new Date(consent.expiresat).toLocaleTimeString()}; header values never enter the audit trail.`;\n card.append(note);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve headers\", () => request({ kind: \"approvefetchconsent\", id: consent.id, approved: true }).then(() => status(`Fetch consent ${consent.id} approved; rerun the fetch step.`)).then(refresh)));\n actions.append(button(\"Decline\", () => request({ kind: \"approvefetchconsent\", id: consent.id, approved: false }).then(() => status(`Fetch consent ${consent.id} declined.`)).then(refresh)));\n card.append(actions);\n callsroot.append(card);\n }\n const endpoints = context.endpoints ?? [];\n if (endpoints.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `typed endpoints: ${endpoints.length}`;\n card.append(head);\n for (const endpoint of endpoints) {\n const row = document.createElement(\"p\");\n row.textContent = `${endpoint.name} \u00B7 ${endpoint.method} ${endpoint.url} \u00B7 v${endpoint.version} \u00B7 ${endpoint.schema?.fields.length ?? 0} payload field${endpoint.schema?.fields.length === 1 ? \"\" : \"s\"}${endpoint.headers !== undefined ? ` \u00B7 ${Object.keys(endpoint.headers).length} reviewed header${Object.keys(endpoint.headers).length === 1 ? \"\" : \"s\"}` : \"\"}`;\n card.append(row);\n }\n callsroot.append(card);\n }\n const apikeys = context.apikeys ?? [];\n if (apikeys.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `api key references: ${apikeys.length} (secrets never listed)`;\n card.append(head);\n for (const ref of apikeys) {\n const row = document.createElement(\"p\");\n row.textContent = `${ref.name} \u00B7 header ${ref.header} \u00B7 scoped to ${ref.origins.join(\", \")}`;\n card.append(row);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Remove ${ref.name}`, () => request({ kind: \"deleteapikey\", name: ref.name }).then(() => status(`Api key reference ${ref.name} removed.`)).then(refresh)));\n card.append(actions);\n }\n callsroot.append(card);\n }\n const callsmeta = context.calls ?? [];\n const filters = document.createElement(\"div\");\n filters.className = \"actions\";\n const originfilter = document.createElement(\"input\");\n originfilter.placeholder = \"filter by origin\";\n const methodfilter = document.createElement(\"input\");\n methodfilter.placeholder = \"filter by method\";\n const classfilter = document.createElement(\"input\");\n classfilter.placeholder = \"filter by status class\";\n filters.append(originfilter, methodfilter, classfilter);\n callsroot.append(filters);\n const list = document.createElement(\"div\");\n const applyfilters = (): void => {\n list.replaceChildren();\n const origin = originfilter.value.trim().toLowerCase();\n const method = methodfilter.value.trim().toUpperCase();\n const statusclass = classfilter.value.trim().toLowerCase();\n const matched = callsmeta.filter(call => (!origin || call.origin.toLowerCase().includes(origin)) && (!method || call.method.toUpperCase().includes(method)) && (!statusclass || call.statusclass.includes(statusclass)));\n if (matched.length === 0) { list.textContent = \"No outbound call matches the filters yet.\"; return; }\n for (const call of matched) {\n const card = document.createElement(\"details\");\n card.className = \"panel callcard\";\n const summary = document.createElement(\"summary\");\n const credential = call.headernames.some(name => name.toLowerCase().startsWith(\"apikey:\") || [\"authorization\", \"cookie\", \"proxy-authorization\", \"api-key\", \"x-api-key\", \"x-auth-token\"].includes(name.toLowerCase()));\n summary.textContent = `${call.method} ${call.kind} ${call.status} ${call.statusclass} \u00B7 ${new URL(call.url).host} \u00B7 ${call.duration} ms \u00B7 ${call.retries} retr${call.retries === 1 ? \"y\" : \"ies\"} \u00B7 ${call.bytes} bytes \u00B7 step ${call.stepid}`;\n if (credential) {\n const badge = document.createElement(\"span\");\n badge.className = \"credentialbadge\";\n badge.textContent = \" credential call \";\n summary.append(badge);\n }\n card.append(summary);\n const urlrow = document.createElement(\"p\");\n urlrow.textContent = `url: ${call.url}${call.endpoint !== undefined ? ` \u00B7 endpoint ${call.endpoint}` : \"\"}${call.bodyexpired === true ? \" \u00B7 body expired from retention\" : \"\"}`;\n card.append(urlrow);\n const headersrow = document.createElement(\"p\");\n headersrow.textContent = `request header names: ${call.headernames.length > 0 ? call.headernames.join(\", \") : \"none\"} (values never persist)`;\n card.append(headersrow);\n if ((call.fields ?? []).length > 0) {\n const fieldstitle = document.createElement(\"p\");\n fieldstitle.textContent = `parsed fields: ${(call.fields ?? []).length}`;\n card.append(fieldstitle);\n for (const field of call.fields ?? []) {\n const fieldrow = document.createElement(\"p\");\n fieldrow.textContent = `${field.name} (${field.kind}) from ${field.path}: ${field.missing === true ? \"miss filled by the reviewed default\" : JSON.stringify(field.value)}`;\n card.append(fieldrow);\n }\n }\n if (call.streambytes !== undefined) {\n const streamrow = document.createElement(\"p\");\n streamrow.textContent = `streamed ${call.streambytes} bytes of the response body`;\n card.append(streamrow);\n const gauge = document.createElement(\"progress\");\n gauge.max = Math.max(call.streambytes, call.bytes);\n gauge.value = call.streambytes;\n card.append(gauge);\n }\n for (const error of call.errors ?? []) {\n const errorrow = document.createElement(\"p\");\n errorrow.className = \"diffrow.removed\";\n errorrow.textContent = `error of step ${call.stepid}: ${error}`;\n card.append(errorrow);\n }\n list.append(card);\n }\n };\n originfilter.addEventListener(\"input\", applyfilters);\n methodfilter.addEventListener(\"input\", applyfilters);\n classfilter.addEventListener(\"input\", applyfilters);\n applyfilters();\n callsroot.append(list);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Export ${callsmeta.length} call${callsmeta.length === 1 ? \"\" : \"s\"}`, () => request({ kind: \"exportcalls\" }).then(() => status(`Exported ${callsmeta.length} call record${callsmeta.length === 1 ? \"\" : \"s\"} through the reviewed download flow.`)).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n if (active) {\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"call body retention (records)\";\n retentioninput.value = context.callretention !== undefined ? String(context.callretention) : \"\";\n retentioninput.setAttribute(\"aria-label\", \"call body retention window\");\n const retentionbutton = button(\"Save call retention\", () => request({ kind: \"setcallretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Call body retention saved as ${retentioninput.value === \"\" ? \"keep every body\" : retentioninput.value} records; metadata always survives.`)).then(refresh));\n actions.append(retentioninput, retentionbutton);\n }\n callsroot.append(actions);\n}\n\n\n/** Renders the network view: every observed exchange of the run with method, url, status, size and duration, expandable redacted headers and a body preview, failed requests with an error class badge, grouping by correlation id, the live channel state with message counters, the event stream subscriptions with event names, the poll loops with cursor values and stop conditions, the webrequest grant toggle and the netlog export. */\nfunction rendernetview(context: { session?: { stoppedat?: number; expiresat: number }; exchanges?: Array<{ id: string; runid: string; stepid: string; correlationid: string; url: string; origin: string; method: string; status: number; statusclass: string; errorclass?: string; source: string; timing: number; bytes: number; mime?: string; bodyref?: string; bodyexpired?: boolean; requestheaders?: Record<string, string>; responseheaders?: Record<string, string> }>; channels?: Array<{ id: string; kind: string; url: string; origin: string; state: string; sent: number; received: number; reconnects: number; lasteventid?: string }>; subscriptions?: Array<{ id: string; url: string; origin: string; state: string; events: number; names: string[]; lasteventid?: string; cancel: { kind: string; value: string | number } }>; apimap?: Array<{ endpoint: string; method: string; mime: string; frequency: number; jsonshare: number; stability: number; origin: string; payloadshape: string[] }>; progress?: planprogress; webrequestgrant?: boolean; bodyretention?: number; socketsactive?: number; activerules?: number; traffic?: { blocks: Array<{ id: string; urlpattern: string; hits: number; revertedat?: number; stepid: string }>; mocks: Array<{ id: string; urlpattern: string; status: number; hits: number; revertedat?: number }>; rewrites: Array<{ id: string; urlpattern: string; name: string; operation: string; value?: string; hits: number; revertedat?: number }>; cookies: Array<{ id: string; kind: string; domain: string; names: string[]; at: number }>; proxies: Array<{ id: string; scheme: string; host: string; port: number; bypass: string[]; appliedat: number; revertedat?: number }>; ratelimits: Array<{ origin: string; remaining?: number; limit?: number; resetat: number }> }; tokens?: { tokens: Array<{ id: string; provider: string; origin: string; scopes: string[]; expiresat: number; refreshedat?: number; revokedat?: number }> }; authflows?: Array<{ provider: string; redirectorigin: string; scopes: string[]; stepid: string; tabid: number; stage: string }> }): void {\n if (!netviewroot) return;\n netviewroot.replaceChildren();\n const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();\n const grantcard = document.createElement(\"div\");\n grantcard.className = \"panel\";\n const grantrow = document.createElement(\"p\");\n grantrow.textContent = `request watching: ${context.webrequestgrant === true ? \"granted\" : \"not granted\"} \u2014 the observation derives from the page timing buffers and adds no manifest permission.`;\n grantcard.append(grantrow);\n if (active) {\n const grantactions = document.createElement(\"div\");\n grantactions.className = \"actions\";\n grantactions.append(button(context.webrequestgrant === true ? \"Revoke request watching\" : \"Grant request watching\", () => request({ kind: \"setwebrequestgrant\", granted: context.webrequestgrant !== true }).then(() => status(context.webrequestgrant === true ? \"Request watching revoked.\" : \"Request watching granted; watchrequests steps can run now.\")).then(refresh)));\n grantcard.append(grantactions);\n }\n netviewroot.append(grantcard);\n const channels = context.channels ?? [];\n const subscriptions = context.subscriptions ?? [];\n if (channels.length > 0 || subscriptions.length > 0 || (context.socketsactive ?? 0) > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `live channels: ${channels.length} websocket channel${channels.length === 1 ? \"\" : \"s\"} \u00B7 ${subscriptions.length} event stream${subscriptions.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const channel of channels) {\n const row = document.createElement(\"p\");\n row.textContent = `${channel.kind} ${channel.state} \u00B7 ${channel.origin} \u00B7 ${channel.sent} sent \u00B7 ${channel.received} received \u00B7 ${channel.reconnects} reconnect${channel.reconnects === 1 ? \"\" : \"s\"}${channel.lasteventid !== undefined ? ` \u00B7 last event ${channel.lasteventid}` : \"\"}`;\n card.append(row);\n if (channel.state === \"open\" || channel.state === \"connecting\") {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Close ${channel.id}`, () => request({ kind: \"closesocket\", id: channel.id }).then(() => status(`Channel ${channel.id} closed cleanly.`)).then(refresh)));\n card.append(actions);\n }\n }\n for (const subscription of subscriptions) {\n const row = document.createElement(\"p\");\n row.textContent = `sse ${subscription.state} \u00B7 ${subscription.origin} \u00B7 ${subscription.events} event${subscription.events === 1 ? \"\" : \"s\"}${subscription.names.length > 0 ? ` (${subscription.names.slice(0, 4).join(\", \")}${subscription.names.length > 4 ? \"\u2026\" : \"\"})` : \"\"}${subscription.lasteventid !== undefined ? ` \u00B7 resume at ${subscription.lasteventid}` : \"\"} \u00B7 cancel on ${subscription.cancel.kind}`;\n card.append(row);\n }\n netviewroot.append(card);\n }\n const pollevidence = (context.progress?.outcomes ?? []).filter(outcome => outcome.details?.poll !== undefined).map(outcome => outcome.details?.poll as { poll: number; cursor?: string; status: number; stopped: boolean; reason: string });\n if (pollevidence.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `poll loops: ${pollevidence.length} iteration${pollevidence.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const poll of pollevidence.slice(0, 8)) {\n const row = document.createElement(\"p\");\n row.textContent = `poll ${poll.poll} \u00B7 status ${poll.status}${poll.cursor !== undefined ? ` \u00B7 cursor ${poll.cursor}` : \"\"} \u00B7 ${poll.stopped ? `stopped: ${poll.reason}` : \"continuing\"}`;\n card.append(row);\n }\n card.append(document.createRange().createContextualFragment(\"\"));\n netviewroot.append(card);\n }\n const exchanges = context.exchanges ?? [];\n const list = document.createElement(\"div\");\n if (exchanges.length === 0) { list.textContent = \"No request of the run has been observed yet; grant request watching and run a watchrequests step.\"; }\n for (const exchange of exchanges) {\n const card = document.createElement(\"details\");\n card.className = \"panel callcard\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `${exchange.method} ${exchange.status} ${exchange.statusclass} \u00B7 ${new URL(exchange.url).host} \u00B7 ${exchange.bytes} bytes \u00B7 ${exchange.timing} ms \u00B7 correlation ${exchange.correlationid} \u00B7 ${exchange.source === \"page\" ? \"derived\" : \"captured\"}`;\n if (exchange.errorclass !== undefined) {\n const badge = document.createElement(\"span\");\n badge.className = \"credentialbadge\";\n badge.textContent = ` ${exchange.errorclass} `;\n summary.append(badge);\n }\n card.append(summary);\n const urlrow = document.createElement(\"p\");\n urlrow.textContent = `url: ${exchange.url}${exchange.mime !== undefined ? ` \u00B7 ${exchange.mime}` : \"\"}${exchange.bodyref !== undefined ? ` \u00B7 body ${exchange.bodyref}` : \"\"}${exchange.bodyexpired === true ? \" \u00B7 body expired from retention\" : \"\"}`;\n card.append(urlrow);\n const requestheadernames = Object.keys(exchange.requestheaders ?? {});\n if (requestheadernames.length > 0 || Object.keys(exchange.responseheaders ?? {}).length > 0) {\n const headersrow = document.createElement(\"p\");\n headersrow.textContent = `stored headers (redacted on the redaction list): request ${requestheadernames.length > 0 ? requestheadernames.join(\", \") : \"none\"} \u00B7 response ${Object.keys(exchange.responseheaders ?? {}).join(\", \") || \"none\"}`;\n card.append(headersrow);\n } else {\n const headersrow = document.createElement(\"p\");\n headersrow.className = \"muted\";\n headersrow.textContent = \"no captured headers: derived page exchanges expose no header names through the timing buffers.\";\n card.append(headersrow);\n }\n if (exchange.bodyref !== undefined && exchange.bodyexpired !== true) {\n const bodyrow = document.createElement(\"p\");\n bodyrow.textContent = `captured body ${exchange.bodyref}`;\n card.append(bodyrow);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Preview body ${exchange.bodyref}`, () => request({ kind: \"exchangebody\", ref: exchange.bodyref }).then(value => {\n const record = value as { body: string; mime: string; bytes: number };\n bodyrow.textContent = `captured body ${exchange.bodyref} of ${record.mime} and ${record.bytes} bytes: ${record.body.slice(0, 400)}${record.body.length > 400 ? \"\u2026 (display preview truncates; the stored body keeps every byte)\" : \"\"}`;\n }).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n card.append(actions);\n }\n list.append(card);\n }\n netviewroot.append(list);\n const apimap = context.apimap ?? [];\n if (apimap.length > 0) {\n const card = document.createElement(\"div\");\n card.className = \"panel\";\n const head = document.createElement(\"p\");\n head.textContent = `page api map: ${apimap.length} ranked endpoint${apimap.length === 1 ? \"\" : \"s\"}`;\n card.append(head);\n for (const entry of apimap.slice(0, 10)) {\n const row = document.createElement(\"p\");\n row.textContent = `${entry.method} ${entry.endpoint} \u00B7 ${entry.frequency} call${entry.frequency === 1 ? \"\" : \"s\"} \u00B7 json ${Math.round(entry.jsonshare * 100)}% \u00B7 stable ${Math.round(entry.stability * 100)}%${entry.payloadshape.length > 0 ? ` \u00B7 ${entry.payloadshape.slice(0, 5).join(\", \")}` : \"\"}`;\n card.append(row);\n }\n netviewroot.append(card);\n }\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Export netlog (${exchanges.length} exchange${exchanges.length === 1 ? \"\" : \"s\"})`, () => request({ kind: \"exportnetlog\" }).then(() => status(\"Exported the captured run log through the reviewed download flow.\")).catch(error => status(error instanceof Error ? error.message : String(error), true))));\n if (active) {\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"captured body retention (records)\";\n retentioninput.value = context.bodyretention !== undefined ? String(context.bodyretention) : \"\";\n retentioninput.setAttribute(\"aria-label\", \"captured body retention window\");\n actions.append(retentioninput, button(\"Save body retention\", () => request({ kind: \"setbodyretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Captured body retention saved as ${retentioninput.value === \"\" ? \"keep every body\" : retentioninput.value} records; exchange metadata always survives.`)).then(refresh)));\n }\n netviewroot.append(actions);\n}\n\nfunction rendercapabilities(report?: capabilityreport): void {\n if (!capabilitiestext) return;\n if (!report) { capabilitiestext.textContent = \"Optional capabilities unknown.\"; return; }\n capabilitiestext.textContent = `tabs ${report.tabs ? \"granted\" : \"absent\"} \u00B7 downloads ${report.downloads ? \"granted\" : \"absent\"} \u00B7 clipboard read ${report.clipboardread ? \"granted\" : \"absent\"} \u00B7 clipboard write ${report.clipboardwrite ? \"granted\" : \"absent\"}`;\n}\n\nfunction renderaudit(events: auditevent[]): void { if (!auditroot) return; auditroot.replaceChildren(); for (const event of events.slice(0, 12)) { const item = document.createElement(\"li\"); item.textContent = `${new Date(event.at).toLocaleTimeString()} \u00B7 ${event.kind} \u00B7 ${event.summary}`; auditroot.append(item); } }\nfunction renderdiagnostic(report?: diagnosticreport): void { if (!diagnosticroot) return; diagnosticroot.replaceChildren(); if (!report) { diagnosticroot.textContent = \"Run a local diagnostic after starting a session to record bridge and page-shape health.\"; return; } const values = [`origin: ${report.origin}`, `title: ${report.title || \"untitled\"}`, `interactive elements: ${report.interactivecount}`, `forms: ${report.formcount}`, `page text length: ${report.textlength}`, `bridge available: ${report.bridgeavailable ? \"yes\" : \"no\"}`]; for (const value of values) { const item = document.createElement(\"li\"); item.textContent = value; diagnosticroot.append(item); } }\n/** Renders the run timeline view: console capture consent prompts, level, source and step filters, entries with spam collapse counts and step markers, errors expanded into their stack frames, long task bars beside their steps and the level count summary with the retention setting. */\nfunction rendertimeline(context: { plan?: agentplan; timeline?: { entries: timelineentry[]; errors: errorrecord[]; rejections: rejectionrecord[]; longtasks: longtaskentry[]; levelcounts: Record<string, number> }; consoleconsents?: consoleconsentrecord[]; timelineretention?: number; levelsummaries?: Array<{ runid: string; counts: Record<string, number>; at: number }>; rotationtargets?: Array<{ target: string; runid: string; entries: number; at: number }> }): void {\n if (!timelineroot) return;\n timelineroot.replaceChildren();\n const waiting = (context.consoleconsents ?? []).filter(consent => consent.approved === undefined);\n for (const consent of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Console capture consent: ${consent.prompt}`;\n card.append(prompt, button(\"Approve console capture\", () => request({ kind: \"approveconsoleconsent\", id: consent.id }).then(() => status(`Console capture on ${consent.origin} approved; run the watchconsole step again.`)).then(refresh)));\n timelineroot.append(card);\n }\n const entries = context.timeline?.entries ?? [];\n const errors = context.timeline?.errors ?? [];\n const rejections = context.timeline?.rejections ?? [];\n const longtasks = context.timeline?.longtasks ?? [];\n if (entries.length === 0 && errors.length === 0 && rejections.length === 0 && longtasks.length === 0) { timelineroot.textContent = \"Run watchconsole, watcherrors or watchtasks steps to fill the run timeline.\"; return; }\n const levels = [\"error\", \"warn\", \"info\", \"log\", \"debug\", \"trace\"] as const;\n const sources = [\"console\", \"error\", \"rejection\", \"resource\", \"longtask\", \"network\"] as const;\n const filters = document.createElement(\"div\");\n filters.className = \"actions\";\n for (const level of levels) filters.append(button(timelinefilter.level === level ? `level ${level} \u2713` : `level ${level}`, async () => { timelinefilter.level = timelinefilter.level === level ? \"\" : level; await refresh(); }));\n for (const source of sources) filters.append(button(timelinefilter.source === source ? `source ${source} \u2713` : `source ${source}`, async () => { timelinefilter.source = timelinefilter.source === source ? \"\" : source; await refresh(); }));\n timelineroot.append(filters);\n const stepids = [...new Set(entries.map(entry => entry.stepid))];\n if (stepids.length > 1) {\n const select = document.createElement(\"select\");\n select.style.width = \"100%\";\n const any = document.createElement(\"option\");\n any.value = \"\";\n any.textContent = \"every step\";\n select.append(any);\n for (const stepid of stepids) {\n const option = document.createElement(\"option\");\n option.value = stepid;\n option.textContent = `step ${stepid}`;\n if (timelinefilter.stepid === stepid) option.selected = true;\n select.append(option);\n }\n select.addEventListener(\"change\", () => { timelinefilter.stepid = select.value; void refresh(); });\n timelineroot.append(select);\n }\n const shown = entries.filter(entry => (timelinefilter.level === \"\" || entry.level === timelinefilter.level) && (timelinefilter.source === \"\" || entry.source === timelinefilter.source) && (timelinefilter.stepid === \"\" || entry.stepid === timelinefilter.stepid)).slice().reverse().slice(0, 60);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const entry of shown) {\n const item = document.createElement(\"li\");\n item.className = \"timelinerow\";\n item.dataset.level = entry.level;\n const head = document.createElement(\"p\");\n head.className = \"timeline\";\n head.textContent = `${new Date(entry.time).toLocaleTimeString()} \u00B7 ${entry.level} \u00B7 ${entry.source} \u00B7 step ${entry.stepid}${entry.repeat !== undefined && entry.repeat > 1 ? ` \u00B7 collapsed \u00D7${entry.repeat}` : \"\"}`;\n const message = document.createElement(\"p\");\n message.textContent = entry.message;\n item.append(head, message);\n if (entry.level === \"error\" && (entry.source === \"error\" || entry.source === \"rejection\")) {\n const record = entry.source === \"error\" ? errors.find(candidate => candidate.stepid === entry.stepid && candidate.message === entry.message) : rejections.find(candidate => candidate.stepid === entry.stepid && candidate.reason === entry.message);\n const frames = record && \"frames\" in record ? record.frames : [];\n if (frames.length > 0) {\n const expand = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = `${frames.length} stack frame${frames.length === 1 ? \"\" : \"s\"}`;\n const pre = document.createElement(\"pre\");\n pre.textContent = frames.map(frame => `at ${frame.functionname ?? \"<anonymous>\"} (${frame.url}:${frame.line}${frame.column !== undefined ? `:${frame.column}` : \"\"})`).join(\"\\n\");\n expand.append(summary, pre);\n item.append(expand);\n }\n }\n list.append(item);\n }\n timelineroot.append(list);\n const maxtask = longtasks.reduce((max, task) => Math.max(max, task.duration), 0);\n for (const task of longtasks.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `long task \u00B7 ${task.duration} ms${task.attributions.length > 0 ? ` \u00B7 ${task.attributions.join(\", \")}` : \"\"} \u00B7 step ${task.stepid}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = maxtask > 0 ? `${Math.round((task.duration / maxtask) * 100)}%` : \"0%\";\n gauge.append(fill);\n bar.append(label, gauge);\n timelineroot.append(bar);\n }\n const counts = context.timeline?.levelcounts ?? {};\n const summaryline = document.createElement(\"p\");\n summaryline.className = \"muted\";\n const expired = (context.levelsummaries ?? []).reduce((total, item) => total + Object.values(item.counts).reduce((sum, count) => sum + count, 0), 0);\n summaryline.textContent = `${entries.length} live entr${entries.length === 1 ? \"y\" : \"ies\"} (${levels.map(level => `${counts[level] ?? 0} ${level}`).join(\" \u00B7 \")})${expired > 0 ? ` \u00B7 ${expired} expired into level summaries` : \"\"}${(context.rotationtargets ?? []).length > 0 ? ` \u00B7 ${(context.rotationtargets ?? []).reduce((total, target) => total + target.entries, 0)} rotated to overflow stores` : \"\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.type = \"number\";\n retentioninput.min = \"0\";\n retentioninput.placeholder = \"timeline retention\";\n retentioninput.value = context.timelineretention !== undefined ? String(context.timelineretention) : \"\";\n timelineroot.append(summaryline, retentioninput, button(\"Save timeline retention\", () => request({ kind: \"settimelineretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }).then(() => status(`Timeline retention saved as ${retentioninput.value === \"\" ? \"keep every entry\" : retentioninput.value} entries; level count summaries always survive.`)).then(refresh)));\n}\n\n/** Renders the console diff view: two run id fields, the compare action and the added, removed and repeated lines of the compared console outputs. */\nfunction renderconsolediff(): void {\n if (!consolediffroot) return;\n consolediffroot.replaceChildren();\n const baseinput = document.createElement(\"input\");\n baseinput.placeholder = \"base run id\";\n const targetinput = document.createElement(\"input\");\n targetinput.placeholder = \"target run id\";\n consolediffroot.append(baseinput, targetinput, button(\"Compare console output\", () => request({ kind: \"consolediff\", base: baseinput.value, target: targetinput.value }).then(value => {\n const parsed = value as { diff: consolediff };\n if (!parsed) throw new Error(\"The console diff returned no result.\");\n lastdiff = parsed.diff;\n status(`Diffed runs ${parsed.diff.base} and ${parsed.diff.target}: ${parsed.diff.added} added, ${parsed.diff.removed} removed and ${parsed.diff.repeated} repeated line${parsed.diff.added + parsed.diff.removed + parsed.diff.repeated === 1 ? \"\" : \"s\"}.`);\n renderconsolediff();\n })));\n if (!lastdiff) { const hint = document.createElement(\"p\"); hint.className = \"muted\"; hint.textContent = \"Compare the console output of two runs to see added, removed and repeated lines.\"; consolediffroot.append(hint); return; }\n const headline = document.createElement(\"p\");\n headline.className = \"muted\";\n headline.textContent = `Run ${lastdiff.base} became run ${lastdiff.target}: ${lastdiff.added} added, ${lastdiff.removed} removed and ${lastdiff.repeated} repeated.`;\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const line of lastdiff.lines.slice(0, 80)) {\n const item = document.createElement(\"li\");\n item.className = `diffrow ${line.kind}`;\n item.textContent = `${line.kind}${line.count !== undefined ? ` \u00D7${line.count}` : \"\"}: ${line.text}`;\n list.append(item);\n }\n consolediffroot.append(headline, list);\n}\n\n/** Renders the debugger view: the debugger consent prompts with the domain allowlist shown, the session state with its domains and honest derivation, the sent commands with durations and results, the breakpoints with hit counts and conditions, the pause banner with call frames, the watch expression values per pause, the script override list with revert controls and the domain event counts streamed beside the run timeline. */\nfunction renderdebugger(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number; origin?: string }; cdpsessions?: Array<{ id: string; runid: string; tabid: number; origin: string; attachedat: number; domains: string[]; debuggerversion: string; detachedat?: number; userdetached?: boolean }>; cdpcommands?: Array<{ id: string; sessionid: string; method: string; domain: string; duration: number; errorclass?: string; at: number }>; cdpeventrules?: Array<{ id: string; domain: string; event: string; events: number; closedat?: number; match?: string }>; breakpoints?: Array<{ id: string; runid: string; url: string; line: number; column?: number; condition?: string; hits: number; revertedat?: number }>; pauses?: Array<{ id: string; runid: string; stepid: string; reason: string; callframes: Array<{ functionname?: string; url: string; line: number; column?: number }>; hitbreakpoint?: string; domsnapshotid?: string; at: number; framesexpired?: boolean }>; watchexpressions?: Array<{ id: string; expression: string; scope: string; values: Array<{ pauseid: string; value: string; at: number }>; reviewed: boolean }>; scriptoverrides?: Array<{ id: string; urlpattern: string; hits: number; appliedat: number; revertedat?: number; reviewed: boolean }>; debuggergrants?: Array<{ id: string; origin: string; domains: string[]; approved?: boolean; consentedat: number; revokedat?: number }>; pauseretention?: number; breakpointceiling?: number; cdpattached?: number }): void {\n if (!debuggerroot) return;\n debuggerroot.replaceChildren();\n const waiting = (context.debuggergrants ?? []).filter(grant => grant.approved === undefined && grant.revokedat === undefined);\n for (const grant of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Debugger attach on ${grant.origin} waits for your consent with the domain allowlist ${grant.domains.join(\", \")} shown.`;\n card.append(prompt, button(\"Approve debugger consent\", () => request({ kind: \"approvedebuggerconsent\", id: grant.id }).then(() => status(`Debugger consent on ${grant.origin} approved for ${grant.domains.join(\", \")}; run the attachcdp step again.`)).then(refresh)));\n debuggerroot.append(card);\n }\n const granted = (context.debuggergrants ?? []).filter(grant => grant.approved === true && grant.revokedat === undefined);\n if (granted.length > 0) debuggerroot.append(button(\"Detach debugger now\", () => request({ kind: \"revokedebuggerconsent\" }).then(value => { const parsed = value as { revoked: number; paused: boolean }; status(`Detached the debugger: ${parsed.revoked} consent record${parsed.revoked === 1 ? \"\" : \"s\"} revoked, every breakpoint and override reverted and the run paused for review.`); return refresh(); })));\n const sessions = context.cdpsessions ?? [];\n const attached = sessions.filter(session => session.detachedat === undefined);\n const sessionline = document.createElement(\"p\");\n sessionline.className = \"muted\";\n sessionline.textContent = attached.length === 0\n ? \"No devtools session is attached; run the attachcdp step behind the reviewed debugger consent.\"\n : `${attached.length} attached devtools session${attached.length === 1 ? \"\" : \"s\"}${attached[0] !== undefined ? ` of ${attached[0].origin} with the domains ${attached[0].domains.join(\", \")} enabled through ${attached[0].debuggerversion}` : \"\"}.`;\n debuggerroot.append(sessionline);\n const lastpause = (context.pauses ?? [])[0];\n if (lastpause !== undefined && context.cdpattached !== 0) {\n const banner = document.createElement(\"div\");\n banner.className = \"bannercard\";\n const head = document.createElement(\"p\");\n head.textContent = `Paused on ${lastpause.reason}${lastpause.hitbreakpoint !== undefined ? ` at breakpoint ${lastpause.hitbreakpoint}` : \"\"}${lastpause.domsnapshotid !== undefined ? ` with dom snapshot ${lastpause.domsnapshotid}` : \"\"}.`;\n banner.append(head);\n if (lastpause.framesexpired === true) {\n const expired = document.createElement(\"p\");\n expired.textContent = \"The call frames expired from the pause retention window; the pause reason and hit breakpoint survive.\";\n banner.append(expired);\n } else {\n for (const frame of lastpause.callframes.slice(0, 6)) {\n const row = document.createElement(\"p\");\n row.textContent = `${frame.functionname ?? \"anonymous\"} ${frame.url}:${frame.line}${frame.column !== undefined ? `:${frame.column}` : \"\"}`;\n banner.append(row);\n }\n }\n debuggerroot.append(banner);\n }\n const commands = context.cdpcommands ?? [];\n if (commands.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Raw protocol commands\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const command of commands.slice(0, 12)) {\n const item = document.createElement(\"li\");\n const badge = document.createElement(\"span\");\n badge.className = \"protocolbadge\";\n badge.textContent = \"raw protocol\";\n item.append(`${command.method} \u00B7 ${command.duration} ms${command.errorclass !== undefined ? ` \u00B7 ${command.errorclass}` : \"\"} \u00B7 session ${command.sessionid.slice(0, 8)}`, badge);\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const breakpoints = (context.breakpoints ?? []).filter(spec => spec.revertedat === undefined);\n if (breakpoints.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Breakpoints\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const spec of breakpoints) {\n const item = document.createElement(\"li\");\n item.textContent = `${spec.url}:${spec.line}${spec.column !== undefined ? `:${spec.column}` : \"\"} \u00B7 ${spec.hits} hit${spec.hits === 1 ? \"\" : \"s\"}${spec.condition !== undefined ? ` \u00B7 condition ${spec.condition}` : \"\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const watches = context.watchexpressions ?? [];\n if (watches.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Watch expressions\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const watch of watches) {\n const item = document.createElement(\"li\");\n const values = watch.values.slice(-4).map(value => `${value.value} @${value.pauseid.slice(0, 6)}`).join(\" \u00B7 \");\n item.textContent = `${watch.expression} (${watch.scope} scope${watch.reviewed ? \", reviewed\" : \"\"})${values ? `: ${values}` : \": no value captured yet\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const overrides = context.scriptoverrides ?? [];\n if (overrides.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Script overrides\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const spec of overrides) {\n const item = document.createElement(\"li\");\n item.textContent = `${spec.urlpattern} \u00B7 ${spec.hits} applied evaluation${spec.hits === 1 ? \"\" : \"s\"}${spec.reviewed ? \" \u00B7 reviewed fixture\" : \"\"}${spec.revertedat !== undefined ? \" \u00B7 reverted\" : \" \u00B7 active\"}`;\n if (spec.revertedat === undefined) item.append(button(\"Revert fixture\", () => request({ kind: \"revertcdpoverride\", id: spec.id }).then(() => status(`Reverted the script override of ${spec.urlpattern}; later evaluations run the original source again.`)).then(refresh)));\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const rules = context.cdpeventrules ?? [];\n if (rules.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Domain events beside the timeline\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const rule of rules.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${rule.domain}.${rule.event}${rule.match !== undefined ? ` matching ${rule.match}` : \"\"} \u00B7 ${rule.events} matched event${rule.events === 1 ? \"\" : \"s\"}${rule.closedat !== undefined ? \" \u00B7 closed\" : \"\"}`;\n list.append(item);\n }\n debuggerroot.append(head, list);\n }\n const settingsline = document.createElement(\"p\");\n settingsline.className = \"muted\";\n settingsline.textContent = `Pause retention ${context.pauseretention ?? \"keeps every capture\"} \u00B7 breakpoint ceiling ${context.breakpointceiling ?? \"none\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"pause retention\";\n retentioninput.value = context.pauseretention !== undefined ? String(context.pauseretention) : \"\";\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.placeholder = \"breakpoint ceiling\";\n ceilinginput.value = context.breakpointceiling !== undefined ? String(context.breakpointceiling) : \"\";\n debuggerroot.append(settingsline, retentioninput, ceilinginput, button(\"Save debugger settings\", () => Promise.all([request({ kind: \"setpauseretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }), request({ kind: \"setbreakpointceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) })]).then(() => status(`Debugger settings saved: pause retention ${retentioninput.value === \"\" ? \"keeps every capture\" : retentioninput.value} and breakpoint ceiling ${ceilinginput.value === \"\" ? \"none\" : ceilinginput.value}.`)).then(refresh)));\n}\n\n/** Renders the emulation view: the pending location consent prompts with their coordinates, the active layers per run with their revert plans and the manual revert button, the stacking warning when layers pile on one tab, the offline note when a network layer cuts the traffic, the user curated preset libraries with the preset editor, the blackbox patterns of the current run, the permission override history with restore states, the import and export of preset files through review and the restore of the stored state after a crash. */\nfunction renderemulation(context: { plan?: agentplan; session?: { stoppedat?: number; expiresat: number; origin?: string }; emulation?: { layers: Array<{ id: string; runid: string; stepid: string; family: string; name: string; originscope: string; appliedat: number; revertedat?: number; revertplan: string[] }>; devices: Array<{ name: string; width: number; height: number; pixelratio: number; mobile: boolean }>; networks: Array<{ name: string; latency: number; download: number; upload: number; offline: boolean }>; locations: Array<{ name: string; latitude: number; longitude: number; accuracy: number }>; agents: Array<{ name: string; useragent: string; platform: string; brands: string[] }>; blackbox: Array<{ origin: string; rules: Array<{ urlpatterns: string[]; tracescope: string }> }>; permissions: Array<{ id: string; runid: string; origin: string; name: string; state: string; priorstate: string; appliedat: number; restoredat?: number }>; consents: Array<{ id: string; origin: string; latitude: number; longitude: number; approved?: boolean; consentedat: number; revokedat?: number }> }; emulatedlayers?: string[]; emulationretention?: number }): void {\n if (!emulationroot) return;\n emulationroot.replaceChildren();\n const emulation = context.emulation;\n if (!emulation) { emulationroot.textContent = \"No emulation state is available yet; start a session and review a plan with emulation steps.\"; return; }\n const pending = emulation.consents.filter(consent => consent.approved === undefined && consent.revokedat === undefined);\n for (const consent of pending) {\n const card = document.createElement(\"div\");\n card.className = \"bannercard\";\n const title = document.createElement(\"p\");\n title.textContent = `Location consent needed on ${consent.origin}`;\n const coordinates = document.createElement(\"p\");\n coordinates.textContent = `Reviewed coordinates: ${consent.latitude}, ${consent.longitude}; the override applies through a page-injected geolocation mask and the true browser location stays untouched.`;\n card.append(title, coordinates, button(\"Approve location consent\", () => request({ kind: \"approvelocationconsent\", id: consent.id }).then(() => { status(`Approved the location consent for ${consent.latitude}, ${consent.longitude} on ${consent.origin}.`); return refresh(); })));\n emulationroot.append(card);\n }\n const active = emulation.layers.filter(layer => layer.revertedat === undefined);\n const state = document.createElement(\"p\");\n state.textContent = `${active.length} active emulation layer${active.length === 1 ? \"\" : \"s\"} of run ${active[0]?.runid ?? \"none\"}${active.length > 1 ? \"; the last applied layer wins conflicts\" : \"\"}.`;\n emulationroot.append(state);\n if (active.length > 1) {\n const warn = document.createElement(\"p\");\n warn.textContent = `Warning: ${active.length} layers stack on one tab (${active.map(layer => layer.name).join(\", \")}); every mask reverts at run end in reverse order.`;\n warn.className = \"muted\";\n emulationroot.append(warn);\n }\n const offlinelayer = active.find(layer => layer.family === \"network\" && emulation.networks.some(preset => preset.name === layer.name && preset.offline));\n if (offlinelayer !== undefined) {\n const offline = document.createElement(\"p\");\n offline.textContent = `Offline: the network layer ${offlinelayer.name} cuts the traffic the extension initiates; page traffic stays observed only.`;\n offline.className = \"muted\";\n emulationroot.append(offline);\n }\n for (const layer of active) {\n const row = document.createElement(\"div\");\n row.className = \"emulationrow\";\n row.dataset.stacked = active.length > 1 ? \"true\" : \"false\";\n const line = document.createElement(\"p\");\n line.textContent = `${layer.family} layer ${layer.name} on ${layer.originscope} applied ${new Date(layer.appliedat).toLocaleTimeString()} with the revert plan ${layer.revertplan.join(\", \")}.`;\n row.append(line, button(\"Revert now\", () => request({ kind: \"revertemulation\" }).then(() => { status(\"Reverted every active emulation layer of the run on review panel demand.\"); return refresh(); })));\n emulationroot.append(row);\n }\n if (active.length > 0) {\n emulationroot.append(button(\"Restore stored layers after a crash\", () => request({ kind: \"restoreemulation\" }).then(() => { status(\"Restored the stored emulation layers of the run record.\"); return refresh(); })));\n }\n const families: Array<{ label: string; presets: Array<{ label: string; kind: string }> }> = [\n { label: \"device presets\", presets: emulation.devices.map(preset => ({ label: `${preset.name}: ${preset.width}x${preset.height} @${preset.pixelratio}${preset.mobile ? \" mobile\" : \"\"}`, kind: \"device\" })) },\n { label: \"network presets\", presets: emulation.networks.map(preset => ({ label: `${preset.name}: ${preset.latency}ms, ${preset.download}/${preset.upload} kbps${preset.offline ? \", offline\" : \"\"}`, kind: \"network\" })) },\n { label: \"location presets\", presets: emulation.locations.map(preset => ({ label: `${preset.name}: ${preset.latitude}, ${preset.longitude} \u00B1${preset.accuracy}m`, kind: \"location\" })) },\n { label: \"agent presets\", presets: emulation.agents.map(preset => ({ label: `${preset.name}: ${preset.platform} with ${preset.brands.length} brands`, kind: \"agent\" })) },\n ];\n for (const family of families) {\n const head = document.createElement(\"h4\");\n head.textContent = family.label;\n emulationroot.append(head);\n if (family.presets.length === 0) {\n const empty = document.createElement(\"p\");\n empty.className = \"muted\";\n empty.textContent = \"No user curated preset yet; the library stays user data instead of a hardcoded list.\";\n emulationroot.append(empty);\n continue;\n }\n for (const preset of family.presets) {\n const line = document.createElement(\"p\");\n line.textContent = preset.label;\n emulationroot.append(line);\n }\n }\n const editor = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = \"Preset editor\";\n editor.append(summary);\n const nameinput = document.createElement(\"input\");\n nameinput.placeholder = \"preset name\";\n const valueinput = document.createElement(\"input\");\n valueinput.placeholder = 'preset json, for example {\"name\":\"phone\",\"width\":390,\"height\":844,\"pixelratio\":3,\"mobile\":true}';\n const familyselect = document.createElement(\"select\");\n for (const family of [\"device\", \"network\", \"location\", \"agent\"]) {\n const option = document.createElement(\"option\");\n option.value = family;\n option.textContent = family;\n familyselect.append(option);\n }\n editor.append(nameinput, valueinput, familyselect, button(\"Save preset\", async () => {\n let payload: unknown;\n try { payload = JSON.parse(valueinput.value); } catch { throw new Error(\"The preset payload must be reviewed JSON.\"); }\n if (payload && typeof payload === \"object\" && !Array.isArray(payload) && nameinput.value.trim()) payload = { ...(payload as Record<string, unknown>), name: nameinput.value.trim() };\n const kind = familyselect.value === \"device\" ? \"setdevicepreset\" : familyselect.value === \"network\" ? \"setnetworkpreset\" : familyselect.value === \"location\" ? \"setlocationpreset\" : \"setagentpreset\";\n const field = familyselect.value;\n await request({ kind, [field]: payload });\n status(`Stored the ${familyselect.value} preset in the user curated library.`);\n await refresh();\n }));\n const exportrow = document.createElement(\"div\");\n exportrow.className = \"actions\";\n exportrow.append(button(\"Export preset file\", () => request({ kind: \"exportpresets\" }).then(value => { const parsed = value as { exported: number }; status(`Exported ${parsed.exported} preset${parsed.exported === 1 ? \"\" : \"s\"} through the reviewed download flow.`); return refresh(); })));\n const importinput = document.createElement(\"input\");\n importinput.type = \"file\";\n importinput.accept = \"application/json\";\n importinput.addEventListener(\"change\", () => {\n const file = importinput.files?.[0];\n if (!file) return;\n void file.text().then(content => JSON.parse(content)).then(filevalue => request({ kind: \"importpresets\", file: filevalue })).then(value => { const parsed = value as { imported: number }; status(`Imported ${parsed.imported} reviewed preset${parsed.imported === 1 ? \"\" : \"s\"} into the library.`); return refresh(); }).catch(error => status(error instanceof Error ? error.message : String(error), true));\n });\n exportrow.append(importinput);\n editor.append(exportrow);\n emulationroot.append(editor);\n const blackbox = emulation.blackbox.filter(entry => entry.rules.length > 0);\n if (blackbox.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"blackboxed patterns of the run\";\n emulationroot.append(head);\n for (const entry of blackbox) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.origin}: ${entry.rules.flatMap(rule => rule.urlpatterns).join(\", \")} (${entry.rules.map(rule => rule.tracescope).join(\", \")} scope)`;\n emulationroot.append(line);\n }\n }\n const restored = emulation.permissions.filter(record => record.restoredat === undefined);\n if (restored.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"permission overrides pending restore\";\n emulationroot.append(head);\n for (const record of restored) {\n const line = document.createElement(\"p\");\n line.textContent = `${record.name} of ${record.origin} answered ${record.state} for run ${record.runid}; the prior ${record.priorstate} state restores at run end.`;\n emulationroot.append(line);\n }\n }\n const retentionrow = document.createElement(\"p\");\n retentionrow.className = \"muted\";\n retentionrow.textContent = `Reverted layer state retention: ${context.emulationretention === undefined ? \"keep every prior state\" : `${context.emulationretention} layer${context.emulationretention === 1 ? \"\" : \"s\"}`}; the layer history itself always survives.`;\n emulationroot.append(retentionrow);\n}\n\nasync function refresh(): Promise<void> { const context = await request({ kind: \"context\" }) as { plan?: agentplan; progress?: planprogress; diagnostic?: diagnosticreport; audit: auditevent[]; outcomes?: stepoutcome[]; capabilities?: capabilityreport; session?: { id: string; pausedat?: number; stoppedat?: number; expiresat: number; origin?: string }; map?: clickablemap; retries?: retryoutcome[]; a11y?: a11ycapture; reader?: readercapture; banners?: bannerreport[]; mutationevents?: mutationevent[]; focusevents?: focusevent[]; diffs?: snapshotdiff[]; selectors?: derivedselector[]; trail?: { trail: trailentry[] }; navrecords?: navrecord[]; ratestates?: ratelimitstate[]; safeties?: safetyverdict[]; curated?: curatedlist[]; waitprofiles?: waitprofilerecord[]; auths?: Array<{ origin: string; username: string; reviewedat: number }>; navcontrol?: navcontrol; navqueues?: navqueues; artifacts?: artifactrecord[]; tabs?: tabshape[]; windows?: windowshape[]; tabgroups?: tabgrouprecord[]; badges?: tabbadge[]; tabmetas?: tabmeta[]; clones?: Array<{ url: string; tabids: number[] }>; layouts?: tablayout[]; snapshots?: sessionsnapshot[]; closedtabs?: closedtab[]; tasktabgauge?: { used: number; ceiling?: number; over: boolean }; controltab?: controltabstate; profiles?: formprofile[]; tickets?: submitticket[]; wizards?: { wizards: wizardstate[]; picks: typeaheadpick[] }; picks?: typeaheadpick[]; errorreports?: errorreport[]; captchas?: captchahandoff[]; detections?: detectionrecord[]; codeentry?: boolean; datasets?: dataset[]; imports?: dataset[]; extractsessions?: extractsession[]; streams?: streamstate[]; exports?: Array<{ id: string; kind: string; name: string; rowcount: number; checksum: string; at: number }>; provenances?: provenancerecord[]; taskrules?: taskrules[]; sheetendpoints?: Array<{ endpoint: string; origin: string; configuredat: number; granted: boolean }>; downloads?: downloadrecord[]; mimefilters?: mimefilter[]; clipconsents?: clipboardconsentrecord[]; clips?: clipentry[]; netlogs?: netlogrecord[]; quarantines?: quarantineentry[]; capturecounters?: Array<{ taskid: string; counters: Record<string, number>; at: number }>; cleanuprules?: cleanuprule[]; cleanupruns?: cleanuprun[]; inventory?: artifactinventoryentry[]; scanhooks?: Array<{ scanner: string; endpoint: string; origin: string; configuredat: number; granted: boolean }>; captures?: Array<{ id: string; runid: string; stepid: string; kind: string; format: string; width: number; height: number; capturedat: number; name?: string; annotated?: boolean; target?: string; bytesexpired?: boolean }>; capturepairs?: shotpair[]; capturepolicy?: string; stitchprogress?: Array<{ stepid: string; done: number; total: number }>; media?: Array<{ id: string; runid: string; stepid: string; at: number; bytesexpired?: boolean } & Record<string, unknown>>; imagebatches?: Array<{ id: string; runid: string; stepid: string; images: Array<{ url: string; alt: string; width: number; height: number; bytes: number; mime: string }>; matched: number; downloaded: number; at: number }>; recordingconsents?: Array<{ id: string; prompt: string; origin: string; stepid: string; approved?: boolean; usedat?: number; at: number }>; recordingactive?: Array<{ id: string; kind: string; scope: string; startedat: number; stopat: number }>; recordingwindow?: number; calls?: Array<{ id: string; runid: string; stepid: string; kind: string; url: string; origin: string; method: string; status: number; statusclass: string; duration: number; retries: number; bytes: number; headernames: string[]; endpoint?: string; bodyexpired?: boolean; fields?: Array<{ name: string; path: string; kind: string; value?: unknown; missing?: boolean }>; errors?: string[]; streambytes?: number }>; fetchconsents?: Array<{ id: string; origin: string; headers: Array<{ name: string; value: string }>; approved?: boolean; expiresat: number; at: number }>; endpoints?: Array<{ name: string; method: string; url: string; version: number; headers?: Record<string, string>; schema?: { fields: Array<{ name: string; kind: string; required?: boolean; default?: string | number | boolean }> } }>; apikeys?: Array<{ name: string; origins: string[]; header: string; createdat: number; lastuse?: number }>; callretention?: number; fetchesactive?: number; exchanges?: Array<{ id: string; runid: string; stepid: string; correlationid: string; url: string; origin: string; method: string; status: number; statusclass: string; errorclass?: string; source: string; timing: number; bytes: number; mime?: string; bodyref?: string; bodyexpired?: boolean; requestheaders?: Record<string, string>; responseheaders?: Record<string, string> }>; channels?: Array<{ id: string; kind: string; url: string; origin: string; state: string; sent: number; received: number; reconnects: number; lasteventid?: string }>; subscriptions?: Array<{ id: string; url: string; origin: string; state: string; events: number; names: string[]; lasteventid?: string; cancel: { kind: string; value: string | number } }>; apimap?: Array<{ endpoint: string; method: string; mime: string; frequency: number; jsonshare: number; stability: number; origin: string; payloadshape: string[] }>; webrequestgrant?: boolean; bodyretention?: number; timelineretention?: number; timeline?: { entries: timelineentry[]; errors: errorrecord[]; rejections: rejectionrecord[]; longtasks: longtaskentry[]; levelcounts: Record<string, number> }; consoleconsents?: consoleconsentrecord[]; rotationtargets?: Array<{ target: string; runid: string; entries: number; at: number }>; levelsummaries?: Array<{ runid: string; counts: Record<string, number>; at: number }>; cdpsessions?: Array<{ id: string; runid: string; tabid: number; origin: string; attachedat: number; domains: string[]; debuggerversion: string; detachedat?: number; userdetached?: boolean }>; cdpcommands?: Array<{ id: string; sessionid: string; method: string; domain: string; duration: number; errorclass?: string; at: number }>; cdpeventrules?: Array<{ id: string; domain: string; event: string; events: number; closedat?: number; match?: string }>; breakpoints?: Array<{ id: string; runid: string; url: string; line: number; column?: number; condition?: string; hits: number; revertedat?: number }>; pauses?: Array<{ id: string; runid: string; stepid: string; reason: string; callframes: Array<{ functionname?: string; url: string; line: number; column?: number }>; hitbreakpoint?: string; domsnapshotid?: string; at: number; framesexpired?: boolean }>; watchexpressions?: Array<{ id: string; expression: string; scope: string; values: Array<{ pauseid: string; value: string; at: number }>; reviewed: boolean }>; scriptoverrides?: Array<{ id: string; urlpattern: string; hits: number; appliedat: number; revertedat?: number; reviewed: boolean }>; debuggergrants?: Array<{ id: string; origin: string; domains: string[]; approved?: boolean; consentedat: number; revokedat?: number }>; pauseretention?: number; breakpointceiling?: number; cdpattached?: number; socketsactive?: number; profileretention?: number; traceceiling?: number; profileactive?: number; profiletargets?: Array<{ kind: string; url: string; sessionid: string; attachedat: number }>; profile?: { flows: Array<{ id: string; runid: string; stepid: string; name: string; duration: number; steps: string[] }>; heaps: Array<{ id: string; runid: string; origin: string; bytesize: number; nodecount: number; capturedat: number; bytesexpired?: boolean }>; samples: Array<{ id: string; runid: string; stepid: string; usedbytes: number; limitbytes: number; at: number }>; trends: Array<{ runid: string; slope: number; samples: number; flaggedsteps: string[]; at: number }>; profiles: Array<{ id: string; runid: string; duration: number; samplecount: number; hotfunctions: string[]; at: number; samplesexpired?: boolean }>; shifts: Array<{ id: string; runid: string; stepid: string; score: number; starttime: number; selectors: string[]; at: number }>; traces: Array<{ id: string; runid: string; origin: string; categories: string[]; bytesize: number; events: number; annotations: Array<{ stepid: string; label: string; offset: number }>; startedat: number; endedat: number; bytesexpired?: boolean; exportedat?: number }>; sourcemaps: Array<{ id: string; runid: string; origin: string; scripturl: string; mapurl: string; parsed: boolean; at: number }>; consents: Array<{ id: string; origin: string; approved?: boolean; consentedat: number; revokedat?: number }> }; emulation?: { layers: Array<{ id: string; runid: string; stepid: string; family: string; name: string; originscope: string; appliedat: number; revertedat?: number; revertplan: string[] }>; devices: Array<{ name: string; width: number; height: number; pixelratio: number; mobile: boolean }>; networks: Array<{ name: string; latency: number; download: number; upload: number; offline: boolean }>; locations: Array<{ name: string; latitude: number; longitude: number; accuracy: number }>; agents: Array<{ name: string; useragent: string; platform: string; brands: string[] }>; blackbox: Array<{ origin: string; rules: Array<{ urlpatterns: string[]; tracescope: string }> }>; permissions: Array<{ id: string; runid: string; origin: string; name: string; state: string; priorstate: string; appliedat: number; restoredat?: number }>; consents: Array<{ id: string; origin: string; latitude: number; longitude: number; approved?: boolean; consentedat: number; revokedat?: number }> }; emulatedlayers?: string[]; emulationretention?: number; sessionmemory?: { records: sessionrecord[]; events: sessionevent[]; folders: sessionfolder[]; diffs: sessiondiff[]; auto?: { period: number; maxsnapshots: number; expiry: number }; crashed?: boolean }; autosnapshotstate?: autosnapshotstate; sessionretention?: number; taskstate?: taskstate; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[]; provenance: workflowprovenance[] }; runlogretention?: number; trigger?: { rules: Array<{ id: string; kind: string; workflowid: string; workflowname?: string; label: string; enabled: boolean; paused?: boolean; cooldown: number; lastfireat?: number; nextfireat?: number; fires: number; launches: number; suppressions: number; summary: Record<string, unknown> }>; queued: number }; triggerretention?: number; mcp?: { state: string; config: { bind?: string; port: number; transports: string[]; framesize?: number; queuedepth?: number; callretention?: number; enabled: boolean; remote?: boolean; httpstream?: { endpoint: string; streampath: string; tls: { mode: string; certificatefingerprint?: string; verifiedat?: number }; heartbeatms?: number; idlewindowms?: number }; remoteaccess?: { endpoint: string; tls: { mode: string }; maxclients?: number; tokenlifetimems?: number; approvaltimeout?: { windowms: number } } }; bind: string; port: number; localhost: boolean; clients: Array<{ id: string; transport: string; paired: boolean; connectedat: number; capabilities?: { protocolversion: string; toolversion: number; tools: number; transports: string[] }; toolfloor?: number; fingerprint?: string; pairedat?: number }>; bridge?: { id: string; host: string; connected: boolean; restarts: number; received: number; sent: number; startedat: number }; calls: Array<{ id: string; clientid: string; tool: string; origin: string; ok: boolean; code?: string; at: number }>; catalog: { tools: Array<{ name: string; version: number; description: string; risk: string; consentmeta?: { review: string; riskclass: string; approvalrequired: boolean; originscope: string }; inputschema: { type: string; properties: Record<string, { type: string; description: string; required?: boolean }>; required: string[] } }> }; launches: Array<{ id: string; host: string; pid: number; restart: boolean; at: number }>; remote: { endpoint: string; tls: { mode: string; certificaterequired: boolean; verified: boolean }; clients: number; paired: number; channelsopen: number; channelsdead: number; tokenslive: number }; pairing: Array<{ code: string; scopes: string[]; issuedat: number; expiresat: number }>; allowlist: Array<{ fingerprint: string; displayname: string; namespaces: string[]; grantedat: number; history: Array<{ at: number; actor: string; change: string }> }>; tokens: Array<{ id: string; clientid: string; scopes: string[]; issuedat: number; expiresat: number; revokedat?: number }>; identities: Array<{ fingerprint: string; displayname: string }>; handshakes: Array<{ id: string; clientid: string; method: string; outcome: string; at: number }>; channels: Array<{ id: string; clientid: string; openedat: number; lastbeatat: number; closedat?: number }>; approvals: Array<{ id: string; clientid: string; tool: string; reason: string; params: Record<string, unknown>; state: string; raisedat: number; timeoutat?: number; decidedat?: number; secretfields?: string[] }> }; }; renderplan(context.plan, context.progress, context.outcomes ?? [], context.retries ?? []); renderdiagnostic(context.diagnostic); rendermap(context.map); rendera11y(context.a11y); renderreader(context.reader); renderdetections(context.plan, context.outcomes ?? []); renderstream(context.mutationevents ?? [], context.focusevents ?? []); renderdiffs(context.diffs ?? []); renderbanners(context.banners ?? []); renderselectors(context.selectors ?? []); rendertrail(context.trail?.trail ?? []); rendernavigation(context); rendertabswindows(context); renderforms(context); renderdatasets(context); renderfiles(context); rendercaptures(context); rendermedia(context); rendercalls(context); rendernetview(context); rendertraffic(context); rendertimeline(context); renderdebugger(context); renderprofiling(context); renderemulation(context); rendersessions(context); renderworkflows(context); renderworkfloweditor(context); rendertriggers(context); renderagentprotocol(context); renderconsolediff(); renderaudit(context.audit); rendercapabilities(context.capabilities); if (context.session?.pausedat) status(\"Session paused. Reviewed actions are blocked until resume.\"); else status(context.session ? \"Active session is visible. The extension is waiting for review.\" : \"No active browser session.\"); }\nasync function create(kind: \"proposelocal\" | \"proposeremote\"): Promise<void> { await request({ kind, objective: objective?.value ?? \"\" }); await refresh(); }\nlocalbutton?.addEventListener(\"click\", () => create(\"proposelocal\").catch(error => status(error instanceof Error ? error.message : String(error), true)));\nremotebutton?.addEventListener(\"click\", () => create(\"proposeremote\").catch(error => status(error instanceof Error ? error.message : String(error), true)));\ndiagnosticbutton?.addEventListener(\"click\", () => request({ kind: \"diagnostic\" }).then(() => refresh()).catch(error => status(error instanceof Error ? error.message : String(error), true)));\nrefresh().catch(error => status(error instanceof Error ? error.message : String(error), true));\n\n/** Renders the profiling view: the source map consent prompts, the flow duration bars per step, the heap samples with the growth trend line, the hot functions of the cpu profiles, the layout shifts with scores and impacted selectors, the trace records with export and replay controls grouped by category and step, the attach target state of iframes and workers, and the profile retention and trace byte ceiling settings. */\nfunction renderprofiling(context: { session?: { stoppedat?: number; expiresat: number; origin?: string }; profile?: { flows: Array<{ id: string; runid: string; stepid: string; name: string; duration: number; steps: string[] }>; heaps: Array<{ id: string; runid: string; origin: string; bytesize: number; nodecount: number; capturedat: number; bytesexpired?: boolean }>; samples: Array<{ id: string; runid: string; stepid: string; usedbytes: number; limitbytes: number; at: number }>; trends: Array<{ runid: string; slope: number; samples: number; flaggedsteps: string[]; at: number }>; profiles: Array<{ id: string; runid: string; duration: number; samplecount: number; hotfunctions: string[]; at: number; samplesexpired?: boolean }>; shifts: Array<{ id: string; runid: string; stepid: string; score: number; starttime: number; selectors: string[]; at: number }>; traces: Array<{ id: string; runid: string; origin: string; categories: string[]; bytesize: number; events: number; annotations: Array<{ stepid: string; label: string; offset: number }>; startedat: number; endedat: number; bytesexpired?: boolean; exportedat?: number }>; sourcemaps: Array<{ id: string; runid: string; origin: string; scripturl: string; mapurl: string; parsed: boolean; at: number }>; consents: Array<{ id: string; origin: string; approved?: boolean; consentedat: number; revokedat?: number }> }; profileretention?: number; traceceiling?: number; profileactive?: number; profiletargets?: Array<{ kind: string; url: string; sessionid: string; attachedat: number }> }): void {\n if (!profilingroot) return;\n profilingroot.replaceChildren();\n const report = context.profile;\n const waiting = (report?.consents ?? []).filter(consent => consent.approved === undefined && consent.revokedat === undefined);\n for (const consent of waiting) {\n const card = document.createElement(\"div\");\n card.className = \"consentcard\";\n const prompt = document.createElement(\"p\");\n prompt.textContent = `Source map capture on ${consent.origin} waits for your consent; the map files of the loaded same origin scripts are fetched and parsed locally.`;\n card.append(prompt, button(\"Approve source map capture\", () => request({ kind: \"approvesourcemapconsent\", id: consent.id }).then(() => status(`Source map capture on ${consent.origin} approved; run the capturesourcemaps step again.`)).then(refresh)));\n profilingroot.append(card);\n }\n const granted = (report?.consents ?? []).filter(consent => consent.approved === true && consent.revokedat === undefined);\n if (granted.length > 0) profilingroot.append(button(\"Revoke source map consent\", () => request({ kind: \"revokesourcemapconsent\" }).then(value => { const parsed = value as { revoked: number }; status(`Revoked ${parsed.revoked} source map consent record${parsed.revoked === 1 ? \"\" : \"s\"}; the next capture needs a new reviewed prompt.`); return refresh(); })));\n const stateline = document.createElement(\"p\");\n stateline.className = \"muted\";\n stateline.textContent = `${context.profileactive ?? 0} profiling instrument${(context.profileactive ?? 0) === 1 ? \"\" : \"s\"} active${(context.profiletargets ?? []).length > 0 ? ` with the targets ${(context.profiletargets ?? []).map(target => `${target.kind} ${target.url} (${target.sessionid.slice(0, 10)})`).join(\", \")} attached through flattened sub sessions` : \"\"}.`;\n profilingroot.append(stateline);\n const flows = report?.flows ?? [];\n if (flows.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Flow durations per step\";\n profilingroot.append(head);\n const maxflow = flows.reduce((max, metric) => Math.max(max, metric.duration), 0);\n for (const metric of flows.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `${metric.name} \u00B7 ${metric.duration} ms \u00B7 steps ${metric.steps.join(\", \")}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = maxflow > 0 ? `${Math.round((metric.duration / maxflow) * 100)}%` : \"0%\";\n gauge.append(fill);\n bar.append(label, gauge);\n profilingroot.append(bar);\n }\n }\n const heaps = report?.heaps ?? [];\n const samples = report?.samples ?? [];\n const trend = (report?.trends ?? [])[0];\n if (samples.length > 0 || heaps.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Heap samples with the growth trend\";\n profilingroot.append(head);\n const maxused = samples.reduce((max, sample) => Math.max(max, sample.usedbytes), 1);\n for (const sample of samples.slice(0, 12)) {\n const bar = document.createElement(\"div\");\n bar.className = \"taskbar\";\n const label = document.createElement(\"p\");\n label.className = \"timeline\";\n label.textContent = `${sample.usedbytes} of ${sample.limitbytes} bytes \u00B7 step ${sample.stepid}`;\n const gauge = document.createElement(\"div\");\n gauge.className = \"taskgauge\";\n const fill = document.createElement(\"div\");\n fill.className = \"taskfill\";\n fill.style.width = `${Math.round((sample.usedbytes / maxused) * 100)}%`;\n gauge.append(fill);\n bar.append(label, gauge);\n profilingroot.append(bar);\n }\n const trendline = document.createElement(\"p\");\n trendline.className = \"muted\";\n trendline.textContent = trend !== undefined ? `Trend slope ${trend.slope.toFixed(2)} bytes per millisecond over ${trend.samples} sample${trend.samples === 1 ? \"\" : \"s\"}${trend.flaggedsteps.length > 0 ? `; flagged steps ${trend.flaggedsteps.join(\", \")}` : \"\"}.` : \"No growth trend computed yet; trackmemory computes it from the samples beside every step.\";\n profilingroot.append(trendline);\n if (heaps.length > 0) {\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const heap of heaps.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `snapshot ${heap.id.slice(0, 8)} \u00B7 ${heap.bytesize} bytes \u00B7 ${heap.nodecount} dom nodes${heap.bytesexpired === true ? \" \u00B7 heavy bytes expired\" : \"\"}`;\n list.append(item);\n }\n profilingroot.append(list);\n }\n }\n const cpuprofiles = report?.profiles ?? [];\n if (cpuprofiles.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Cpu profiles with hot functions\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const profile of cpuprofiles.slice(0, 6)) {\n const item = document.createElement(\"li\");\n item.textContent = `profile ${profile.id.slice(0, 8)} \u00B7 ${profile.duration} ms \u00B7 ${profile.samplecount} sample${profile.samplecount === 1 ? \"\" : \"s\"} \u00B7 hot ${profile.hotfunctions.slice(0, 4).join(\", \") || \"none\"}${profile.samplesexpired === true ? \" \u00B7 heavy samples expired\" : \"\"}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const shifts = report?.shifts ?? [];\n if (shifts.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Layout shifts with scores and selectors\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const shift of shifts.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `score ${shift.score.toFixed(4)} at ${Math.round(shift.starttime)} ms${shift.selectors.length > 0 ? ` \u00B7 impacted ${shift.selectors.join(\", \")}` : \"\"} \u00B7 step ${shift.stepid}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const traces = report?.traces ?? [];\n if (traces.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Traces with step annotations\";\n profilingroot.append(head);\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const trace of traces.slice(0, 8)) {\n const item = document.createElement(\"li\");\n item.textContent = `trace ${trace.id.slice(0, 8)} \u00B7 ${trace.categories.join(\", \")} \u00B7 ${trace.events} event${trace.events === 1 ? \"\" : \"s\"} \u00B7 ${trace.bytesize} bytes \u00B7 ${trace.annotations.length} annotation${trace.annotations.length === 1 ? \"\" : \"s\"}${trace.bytesexpired === true ? \" \u00B7 heavy bytes expired\" : \"\"}${trace.exportedat !== undefined ? \" \u00B7 exported\" : \"\"}`;\n item.append(button(\"Replay trace\", () => request({ kind: \"tracereplay\", traceid: trace.id }).then(value => { const replay = value as { events: Array<{ name: string; category: string; offset: number; stepid?: string }>; categories: Record<string, number>; annotations: Array<{ stepid: string; label: string }> }; const grouped = Object.entries(replay.categories).map(([category, count]) => `${category} ${count}`).join(\", \"); const steps = [...new Set(replay.events.map(event => event.stepid).filter((stepid): stepid is string => stepid !== undefined))].join(\", \"); status(`Trace replay of ${trace.id.slice(0, 8)}: ${replay.events.length} event${replay.events.length === 1 ? \"\" : \"s\"} grouped by category (${grouped}) and by step (${steps || \"none\"}) with ${replay.annotations.length} annotation${replay.annotations.length === 1 ? \"\" : \"s\"}.`); return refresh(); })));\n if (trace.bytesexpired !== true) item.append(button(\"Export trace\", () => request({ kind: \"exporttrace\", traceid: trace.id }).then(() => status(`Exported the trace ${trace.id.slice(0, 8)} through the reviewed download flow with its ${trace.annotations.length} step annotation${trace.annotations.length === 1 ? \"\" : \"s\"}.`)).then(refresh)));\n list.append(item);\n }\n profilingroot.append(list);\n }\n const sourcemaps = report?.sourcemaps ?? [];\n if (sourcemaps.length > 0) {\n const head = document.createElement(\"h4\");\n head.textContent = \"Source maps\";\n const list = document.createElement(\"ul\");\n list.className = \"audit\";\n for (const ref of sourcemaps.slice(0, 10)) {\n const item = document.createElement(\"li\");\n item.textContent = `${ref.scripturl} \u2192 ${ref.mapurl} \u00B7 ${ref.parsed ? \"parsed\" : \"unparsed\"}`;\n list.append(item);\n }\n profilingroot.append(head, list);\n }\n const settingsline = document.createElement(\"p\");\n settingsline.className = \"muted\";\n settingsline.textContent = `Profile retention ${context.profileretention ?? \"keeps every heavy artifact\"} \u00B7 trace byte ceiling ${context.traceceiling ?? \"none\"}.`;\n const retentioninput = document.createElement(\"input\");\n retentioninput.placeholder = \"profile retention ms\";\n retentioninput.value = context.profileretention !== undefined ? String(context.profileretention) : \"\";\n const ceilinginput = document.createElement(\"input\");\n ceilinginput.placeholder = \"trace byte ceiling\";\n ceilinginput.value = context.traceceiling !== undefined ? String(context.traceceiling) : \"\";\n profilingroot.append(settingsline, retentioninput, ceilinginput, button(\"Save profiling settings\", () => Promise.all([request({ kind: \"setprofileretention\", retention: retentioninput.value === \"\" ? undefined : Number(retentioninput.value) }), request({ kind: \"settraceceiling\", ceiling: ceilinginput.value === \"\" ? undefined : Number(ceilinginput.value) })]).then(() => status(`Profiling settings saved: profile retention ${retentioninput.value === \"\" ? \"keeps every heavy artifact\" : `${retentioninput.value} milliseconds`} and trace byte ceiling ${ceilinginput.value === \"\" ? \"none\" : `${ceilinginput.value} bytes`}.`)).then(refresh)));\n}\n\n/** Renders the sessions view of the 1.1.49 memory release: the crash restore banner after a browser restart, the auto snapshot state, the search box with its time window, the saved sessions grouped by folder with tags and timestamps, the restore review listing tabs, form state and captures before approval, the diff selection and its change view, the export review and the import review. */\nfunction rendersessions(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; sessionmemory?: { records: sessionrecord[]; events: sessionevent[]; folders: sessionfolder[]; diffs: sessiondiff[]; auto?: { period: number; maxsnapshots: number; expiry: number }; crashed?: boolean }; autosnapshotstate?: autosnapshotstate; sessionretention?: number; taskstate?: taskstate }): void {\n if (!sessionsroot) return;\n sessionsroot.replaceChildren();\n const memory = context.sessionmemory;\n const auto = context.autosnapshotstate;\n const crashed = memory?.crashed === true;\n if (crashed) {\n const banner = document.createElement(\"div\");\n banner.className = \"crashbanner\";\n const title = document.createElement(\"p\");\n title.textContent = `Browser restart interrupted the run${context.taskstate ? ` at step cursor ${context.taskstate.stepcursor}` : \"\"}; the crash restore stays inside the session consent model.`;\n banner.append(title);\n banner.append(button(\"Resume the interrupted run\", async () => { const result = await request({ kind: \"resumerun\" }) as { executed: number; remaining: number }; status(`Resumed the run: ${result.executed} of ${result.remaining} remaining steps executed.`); await refresh(); }));\n banner.append(\" \", button(\"Dismiss crash banner\", async () => { await request({ kind: \"clearautosnapshot\" }).catch(() => undefined); status(\"Crash banner dismissed; the saved sessions stay available for restore.\"); await refresh(); }));\n sessionsroot.append(banner);\n }\n if (auto) {\n const state = document.createElement(\"p\");\n state.textContent = `Auto snapshots: every ${auto.interval.period} ms \u00B7 ${auto.count} of ${auto.interval.maxsnapshots} taken \u00B7 expiry ${auto.interval.expiry} ms.`;\n sessionsroot.append(state, button(\"Clear auto snapshot interval\", async () => { await request({ kind: \"clearautosnapshot\" }); status(\"Auto snapshot interval cleared.\"); await refresh(); }));\n }\n const search = document.createElement(\"div\");\n search.className = \"actions\";\n const term = document.createElement(\"input\");\n term.type = \"search\";\n term.placeholder = \"Search sessions by name, url, title or captured text\";\n term.value = sessionsview.term;\n term.addEventListener(\"input\", () => { sessionsview.term = term.value; rendersessions(context); });\n const windowselect = document.createElement(\"select\");\n for (const option of [[\"all\", \"all time\"], [\"hour\", \"last hour\"], [\"day\", \"last day\"], [\"week\", \"last week\"]] as const) {\n const candidate = document.createElement(\"option\");\n candidate.value = option[0];\n candidate.textContent = option[1];\n candidate.selected = sessionsview.window === option[0];\n windowselect.append(candidate);\n }\n windowselect.addEventListener(\"change\", () => { sessionsview.window = windowselect.value as typeof sessionsview.window; rendersessions(context); });\n search.append(term, windowselect);\n sessionsroot.append(search);\n const importfile = document.createElement(\"input\");\n importfile.type = \"file\";\n importfile.accept = \"application/json\";\n importfile.addEventListener(\"change\", async () => {\n const file = importfile.files?.[0];\n if (!file) return;\n const content = await file.text();\n const review = await request({ kind: \"loadsessionfile\", content }) as { formatversion: number; records: Array<{ id: string; name: string; tabs: number }>; bytesize: number };\n sessionsview.importreview = { records: review.records, file: JSON.parse(content) };\n status(`Session file loaded: ${review.records.length} record${review.records.length === 1 ? \"\" : \"s\"} await review.`);\n await refresh();\n });\n sessionsroot.append(importfile);\n if (sessionsview.importreview) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const title = document.createElement(\"p\");\n title.textContent = `Import review: ${sessionsview.importreview.records.map(record => `${record.name} (${record.tabs} tabs)`).join(\", \")}.`;\n review.append(title, button(\"Approve full record import\", async () => { const result = await request({ kind: \"importsessionrecords\", file: sessionsview.importreview?.file }) as { imported: number }; sessionsview.importreview = undefined; status(`Imported ${result.imported} session record${result.imported === 1 ? \"\" : \"s\"} after review.`); await refresh(); }), \" \", button(\"Cancel import\", async () => { sessionsview.importreview = undefined; status(\"Import cancelled.\"); await refresh(); }));\n sessionsroot.append(review);\n }\n const now = Date.now();\n const windowspan: Record<typeof sessionsview.window, number> = { all: Number.POSITIVE_INFINITY, hour: 3_600_000, day: 86_400_000, week: 604_800_000 };\n const records = (memory?.records ?? []).filter(record => {\n if (now - record.createdat > windowspan[sessionsview.window]) return false;\n if (!sessionsview.term.trim()) return true;\n const haystack = [record.name, record.folder ?? \"\", ...record.tags, ...record.tabs.flatMap(tab => [tab.url, tab.title, ...tab.forms.map(form => form.value)])].join(\" \").toLowerCase();\n return sessionsview.term.trim().toLowerCase().split(/\\s+/).every(term => haystack.includes(term));\n });\n if (sessionsview.diffselection.length >= 2) {\n const [left, right] = sessionsview.diffselection;\n sessionsroot.append(button(\"Diff the two selected sessions\", async () => { const result = await request({ kind: \"sessiondiff\", left, right }) as { changes: Array<{ class: string; subject: string; detail: string }> }; status(`Session diff: ${result.changes.length} change${result.changes.length === 1 ? \"\" : \"s\"}.`); await refresh(); }));\n }\n const groups = new Map<string, sessionrecord[]>();\n for (const record of records) {\n const key = record.folder ?? \"\";\n groups.set(key, [...(groups.get(key) ?? []), record]);\n }\n for (const [folder, entries] of groups) {\n const group = document.createElement(\"details\");\n group.className = \"sessiongroup\";\n group.open = true;\n const summary = document.createElement(\"summary\");\n summary.textContent = folder === \"\" ? \"Saved sessions\" : `Folder ${folder} (${entries.length})`;\n group.append(summary);\n for (const record of entries) group.append(sessionrow(record, context.plan));\n sessionsroot.append(group);\n }\n if (records.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No saved session matches the search yet; run a capturesession step to snapshot the browsing session.\";\n sessionsroot.append(empty);\n }\n if (memory && memory.diffs.length > 0) {\n const diff = memory.diffs[0];\n if (diff) {\n const diffview = document.createElement(\"details\");\n diffview.className = \"sessiongroup\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Latest session diff (${diff.changes.length} changes)`;\n diffview.append(summary);\n for (const change of diff.changes) {\n const line = document.createElement(\"p\");\n line.textContent = `${change.class} ${change.subject}: ${change.detail}`;\n line.dataset.class = change.class;\n diffview.append(line);\n }\n sessionsroot.append(diffview);\n }\n }\n if (sessionsview.restorereview) renderrestorereview(sessionsview.restorereview);\n}\n\n/** Renders one saved session row with its name, folder, tags, timestamp, restored badge and the restore, diff and export actions; the snapshot action runs through the reviewed capturesession step of the approved plan. */\nfunction sessionrow(record: sessionrecord, plan?: agentplan): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n row.dataset.selected = sessionsview.diffselection.includes(record.id) ? \"true\" : \"false\";\n const title = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = record.restoredat !== undefined ? \"true\" : \"false\";\n badge.textContent = record.restoredat !== undefined ? \"restored\" : record.auto === true ? \"auto\" : \"saved\";\n title.append(`${record.name} \u00B7 ${new Date(record.createdat).toLocaleString()} \u00B7 ${record.tabs.length} tabs${record.folder !== undefined ? ` \u00B7 folder ${record.folder}` : \"\"}${record.tags.length > 0 ? ` \u00B7 ${record.tags.join(\", \")}` : \"\"}`, badge);\n row.append(title);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Restore under review\", async () => { sessionsview.restorereview = record; await refresh(); }, record.sectionsexpired === true));\n actions.append(\" \", button(sessionsview.diffselection.includes(record.id) ? \"Unselect diff\" : \"Select diff\", async () => {\n sessionsview.diffselection = sessionsview.diffselection.includes(record.id) ? sessionsview.diffselection.filter(id => id !== record.id) : [...sessionsview.diffselection, record.id].slice(-2);\n await refresh();\n }));\n actions.append(\" \", button(\"Export reviewed file\", async () => { const result = await request({ kind: \"exportsessionfile\", ids: [record.id] }) as { bytes: number }; status(`Exported the session file of ${result.bytes} bytes through the download flow.`); }));\n const capturestep = plan?.state === \"approved\" ? plan.steps.find(step => step.kind === \"capturesession\") : undefined;\n if (capturestep) actions.append(\" \", button(\"Run reviewed snapshot step\", async () => { const result = await request({ kind: \"execute\", stepid: capturestep.id }) as { summary: string }; status(result.summary); await refresh(); }));\n row.append(actions);\n return row;\n}\n\n/** Renders the restore review of one saved session: every tab, form state and capture is listed before the approval reopens anything. */\nfunction renderrestorereview(record: sessionrecord): void {\n if (!sessionsroot) return;\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const title = document.createElement(\"p\");\n title.textContent = `Restore review of ${record.name}: ${record.tabs.length} tabs, ${record.tabs.reduce((total, tab) => total + tab.forms.length, 0)} captured form fields, ${record.captures.length} linked captures.`;\n review.append(title);\n for (const tab of record.tabs) {\n const line = document.createElement(\"p\");\n line.textContent = `Tab ${tab.index}: ${tab.title || tab.url} \u00B7 ${tab.forms.length} form fields \u00B7 scroll ${tab.scrollx},${tab.scrolly}`;\n review.append(line);\n }\n for (const entry of record.storage) {\n const line = document.createElement(\"p\");\n line.textContent = `Local storage of ${entry.origin}: ${entry.keys.length} keys captured.`;\n review.append(line);\n }\n for (const entry of record.cookies) {\n const line = document.createElement(\"p\");\n line.textContent = `Cookies of ${entry.origin}: ${entry.names.length} names captured, values held back.`;\n review.append(line);\n }\n review.append(button(\"Approve restore\", async () => { const result = await request({ kind: \"approverestore\", sessionid: record.id }) as { restored: number; skippedorigins: string[] }; sessionsview.restorereview = undefined; status(`Restored ${result.restored} tabs${result.skippedorigins.length > 0 ? `; skipped ${result.skippedorigins.join(\", \")}` : \"\"}.`); await refresh(); }), \" \", button(\"Cancel restore\", async () => { sessionsview.restorereview = undefined; status(\"Restore cancelled.\"); await refresh(); }));\n sessionsroot.append(review);\n}\n\n/** Renders the control flow summary of one reviewed step: the branch paths with the else path preview, the loop bounds and bodies, the parallel branches with the join policy and the try retry and timeout policies. */\nfunction controlreviewtext(control: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } | undefined): string {\n if (control === undefined) return \"\";\n if (control.kind === \"condition\") return ` \u00B7 condition ${control.expression ?? \"expression\"}`;\n if (control.kind === \"branch\") return ` \u00B7 paths ${(control.paths ?? []).join(\", \")} \u00B7 else ${control.elsepath ?? \"else\"} when no path matches`;\n if (control.kind === \"loop\") return ` \u00B7 loops ${control.list ?? \"list\"} binding ${control.item ?? \"item\"} and ${control.index ?? \"index\"} per iteration \u00B7 safety bound ${control.bound ?? 1000}`;\n if (control.kind === \"repeatuntil\") return ` \u00B7 repeats until convergence \u00B7 safety bound ${control.bound ?? 1000}`;\n if (control.kind === \"whileloop\") return ` \u00B7 while the condition holds \u00B7 safety bound ${control.bound ?? \"reviewed\"}`;\n if (control.kind === \"foreach\") return ` \u00B7 foreach ${control.selector ?? \"selector\"} binding ${control.item ?? \"item\"} and ${control.index ?? \"index\"} per element`;\n if (control.kind === \"parallel\") return ` \u00B7 branches ${(control.branches ?? []).join(\", \")} \u00B7 join ${control.strategy ?? \"last\"} \u00B7 on failure ${control.onfail ?? \"continue\"}`;\n return ` \u00B7 try with catch${control.rerun === true ? \" and rerun\" : \"\"}${control.attempts !== undefined ? ` \u00B7 ${control.attempts} attempt${control.attempts === 1 ? \"\" : \"s\"} of ${control.backoff ?? \"fixed\"} backoff` : \"\"}${control.stepms !== undefined ? ` \u00B7 step budget ${control.stepms} ms` : \"\"}${control.runms !== undefined ? ` \u00B7 run budget ${control.runms} ms` : \"\"}`;\n}\n\n/** Renders one control flow decision of the runlog: the chosen branch path highlighted, the loop iterations as a collapsible group, the retry attempts with their backoff countdowns, the parallel branch lanes, the join result with the merged variables, the catch path of a try block and the timeout aborts with the exceeded budget. */\nfunction rendercontroldecision(entry: runlogentry): HTMLElement {\n const block = document.createElement(\"details\");\n block.className = \"sessiongroup\";\n const control = entry.details?.control as { kind?: string; branch?: { path: string; reason: string }; loops?: Array<{ path: string; ok: boolean }>; retries?: Array<{ attempt: number; delay: number; errorclass: string }>; timeouts?: Array<{ budget: number; scope: string }>; join?: { strategy: string; conflicts: string[]; merged: string[] }; branches?: Array<{ branchid: string; ok: boolean; summary: string; cancelled?: boolean }>; catch?: { errorclass: string; rerun: boolean } } | undefined;\n const summary = document.createElement(\"summary\");\n summary.textContent = `control flow \u00B7 ${control?.kind ?? \"decision\"} \u00B7 ${entry.summary}`;\n block.append(summary);\n if (control?.branch !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `Chose the path ${control.branch.path}: ${control.branch.reason}`;\n line.dataset.class = \"added\";\n line.dataset.branch = control.branch.path;\n block.append(line);\n }\n if (control?.loops !== undefined && control.loops.length > 0) {\n const group = document.createElement(\"details\");\n group.className = \"sessiongroup\";\n const groupsummary = document.createElement(\"summary\");\n groupsummary.textContent = `Loop iterations (${control.loops.length})`;\n group.append(groupsummary);\n for (const counter of control.loops) {\n const line = document.createElement(\"p\");\n line.textContent = `${counter.path} \u00B7 ${counter.ok ? \"completed\" : \"failed\"}`;\n line.dataset.class = counter.ok ? \"added\" : \"changed\";\n group.append(line);\n }\n block.append(group);\n }\n if (control?.retries !== undefined && control.retries.length > 0) {\n for (const attempt of control.retries) {\n const line = document.createElement(\"p\");\n line.textContent = `Retry attempt ${attempt.attempt} after a ${attempt.delay} ms backoff countdown for the ${attempt.errorclass} error class.`;\n line.dataset.class = \"changed\";\n block.append(line);\n }\n }\n if (control?.timeouts !== undefined && control.timeouts.length > 0) {\n for (const abort of control.timeouts) {\n const line = document.createElement(\"p\");\n line.textContent = `Timeout abort: the ${abort.scope} exceeded its reviewed budget of ${abort.budget} milliseconds.`;\n line.dataset.class = \"changed\";\n line.dataset.timeout = \"true\";\n block.append(line);\n }\n }\n if (control?.branches !== undefined && control.branches.length > 0) {\n const lanes = document.createElement(\"details\");\n lanes.className = \"sessiongroup\";\n const lannessummary = document.createElement(\"summary\");\n lannessummary.textContent = `Parallel branch lanes (${control.branches.length})`;\n lanes.append(lannessummary);\n for (const outcome of control.branches) {\n const lane = document.createElement(\"p\");\n lane.textContent = `lane ${outcome.branchid} \u00B7 ${outcome.cancelled === true ? \"cancelled\" : outcome.ok ? \"completed\" : \"failed\"} \u00B7 ${outcome.summary}`;\n lane.dataset.class = outcome.ok && outcome.cancelled !== true ? \"added\" : \"changed\";\n lanes.append(lane);\n }\n block.append(lanes);\n }\n if (control?.join !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `Join under the ${control.join.strategy} strategy merged ${control.join.merged.join(\", \") || \"no variable\"}${control.join.conflicts.length > 0 ? ` with the conflicts ${control.join.conflicts.join(\", \")}` : \" with no conflict\"}.`;\n line.dataset.class = control.join.conflicts.length > 0 ? \"changed\" : \"added\";\n block.append(line);\n }\n if (control?.catch !== undefined) {\n const line = document.createElement(\"p\");\n line.textContent = `The catch handler ran after the ${control.catch.errorclass} failure${control.catch.rerun ? \" and reran the fragile body\" : \"\"}.`;\n line.dataset.class = \"changed\";\n block.append(line);\n }\n return block;\n}\n\n/** Renders the workflow view: the composed workflows with their run and dry run actions behind the plan review, the approval prompt of the first real run with the expanded step list, the live step timeline with checkpoint markers and dry run marks, the variable values per scope, the inline expression results, the active block highlight, the runlog stream and the single step execution from the step context. */\nfunction renderworkflows(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[]; provenance: workflowprovenance[] } }): void {\n if (!workflowsroot) return;\n workflowsroot.replaceChildren();\n const state = context.workflow;\n const runs = state?.runs ?? [];\n const running = runs.filter(run => run.state === \"running\");\n const latest = runs[0];\n const title = document.createElement(\"p\");\n title.textContent = `${state?.workflows.length ?? 0} composed workflow${(state?.workflows.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${running.length} running in the background \u00B7 ${state?.templates.length ?? 0} shared step template${(state?.templates.length ?? 0) === 1 ? \"\" : \"s\"}.`;\n workflowsroot.append(title);\n for (const record of state?.workflows ?? []) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = record.risk === \"sensitive\" ? \"sensitive\" : record.risk;\n headline.append(`${record.name} v${record.version} \u00B7 ${record.steps.length} steps \u00B7 ${record.origins.join(\", \")}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n const planstep = (kind: \"runworkflow\" | \"dryrun\"): toolstep | undefined => (context.plan?.state === \"approved\" ? context.plan.steps.find(step => step.kind === kind && (() => { try { return JSON.parse(step.options ?? \"{}\").workflowid === record.id; } catch { return false; } })()) : undefined);\n const runstepofplan = planstep(\"runworkflow\");\n const drystepofplan = planstep(\"dryrun\");\n actions.append(button(\"Review expanded steps\", async () => { const review = await request({ kind: \"workflowreview\", workflowid: record.id }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string; bindings?: unknown[]; expression?: { operator: string; result: string }; extract?: { groups: string[] }; control?: { kind: string; paths?: string[]; elsepath?: string; list?: string; item?: string; index?: string; bound?: number; selector?: string; branches?: string[]; strategy?: string; onfail?: string; attempts?: number; backoff?: string; rerun?: boolean; stepms?: number; runms?: number; expression?: string } }> }; workflowview.review = { workflowid: record.id, name: record.name, risk: record.risk, steps: review.steps }; status(`Workflow review: ${review.steps.length} expanded steps of ${record.name}.`); await refresh(); }));\n actions.append(\" \", button(\"Approve run review\", async () => { const result = await request({ kind: \"approveworkflowrun\", workflowid: record.id }) as { steps: number }; status(`Run review approved: ${result.steps} steps shown; the plan review still gates every run.`); await refresh(); }));\n actions.append(\" \", button(\"Run reviewed workflow\", async () => { if (!runstepofplan) { status(\"No approved runworkflow step of this workflow is in the plan.\", true); return; } const result = await request({ kind: \"execute\", stepid: runstepofplan.id }) as { summary: string }; status(result.summary); await refresh(); }, runstepofplan === undefined));\n actions.append(\" \", button(\"Dry run\", async () => { if (!drystepofplan) { status(\"No approved dryrun step of this workflow is in the plan.\", true); return; } const result = await request({ kind: \"execute\", stepid: drystepofplan.id }) as { summary: string }; status(result.summary); await refresh(); }, drystepofplan === undefined));\n row.append(actions);\n workflowsroot.append(row);\n }\n if ((state?.workflows.length ?? 0) === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No composed workflow yet; run a composeworkflow step to freeze a reviewed step list.\";\n workflowsroot.append(empty);\n }\n if (workflowview.review) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Workflow approval of ${workflowview.review.name} (${workflowview.review.risk} for review): every expanded step shows before the first real run.`;\n review.append(headline);\n const list = document.createElement(\"ol\");\n for (const step of workflowview.review.steps) {\n const line = document.createElement(\"li\");\n line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.target !== undefined ? ` \u00B7 ${step.target}` : \"\"}${step.expression !== undefined ? ` \u00B7 expression ${step.expression.operator} into ${step.expression.result}` : \"\"}${step.extract !== undefined && step.extract.groups.length > 0 ? ` \u00B7 extracts ${step.extract.groups.join(\", \")}` : \"\"}${Array.isArray(step.bindings) && step.bindings.length > 0 ? ` \u00B7 ${step.bindings.length} binding${step.bindings.length === 1 ? \"\" : \"s\"}` : \"\"}${controlreviewtext(step.control)}`;\n list.append(line);\n if (step.control !== undefined && (step.control.kind === \"loop\" || step.control.kind === \"repeatuntil\")) {\n const boundrow = document.createElement(\"div\");\n boundrow.className = \"actions\";\n const boundlabel = document.createElement(\"label\");\n boundlabel.textContent = `Safety bound of ${step.label}: `;\n const boundinput = document.createElement(\"input\");\n boundinput.type = \"number\";\n boundinput.min = \"1\";\n boundinput.value = String(step.control.bound ?? 1000);\n boundlabel.append(boundinput);\n boundrow.append(boundlabel, \" \", button(\"Apply bound before a run\", async () => {\n const bound = Number(boundinput.value);\n if (!Number.isInteger(bound) || bound < 1) { status(\"The loop safety bound must be a positive integer with no code ceiling.\", true); return; }\n const result = await request({ kind: \"setloopbound\", workflowid: workflowview.review?.workflowid, stepid: step.id, bound }) as { version: number };\n status(`Loop bound applied: the workflow was recomposed as version ${result.version} and the older version survives for the audit trail.`);\n await refresh();\n }));\n list.append(boundrow);\n }\n }\n review.append(list);\n review.append(button(\"Close workflow review\", async () => { workflowview.review = undefined; status(\"Workflow review closed.\"); await refresh(); }));\n workflowsroot.append(review);\n }\n if (latest) {\n const timeline = document.createElement(\"details\");\n timeline.className = \"sessiongroup\";\n timeline.open = latest.state === \"running\" || latest.state === \"paused\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Run ${latest.id.slice(0, 8)} of ${latest.workflowid.slice(0, 8)}: ${latest.state}${latest.dryrun === true ? \" (dry run)\" : \"\"} at step cursor ${latest.cursor}.`;\n timeline.append(summary);\n const controls = document.createElement(\"div\");\n controls.className = \"actions\";\n controls.append(button(\"Pause run\", async () => { const result = await request({ kind: \"pauseworkflowrun\", runid: latest.id }) as { state: string }; status(`Workflow run ${result.state}.`); await refresh(); }, latest.state !== \"running\"));\n controls.append(\" \", button(\"Resume run\", async () => { const result = await request({ kind: \"resumeworkflowrun\", runid: latest.id }) as { state: string; cursor: number }; status(`Workflow run resumed and ended ${result.state} at cursor ${result.cursor}.`); await refresh(); }, latest.state !== \"paused\"));\n controls.append(\" \", button(\"Cancel run\", async () => { const result = await request({ kind: \"cancelworkflowrun\", runid: latest.id, reason: \"sidepanel cancel\" }) as { state: string }; status(`Workflow run ${result.state}.`); await refresh(); }, latest.state === \"done\" || latest.state === \"cancelled\"));\n timeline.append(controls);\n const record = state?.workflows.find(entry => entry.id === latest.workflowid);\n if (record) {\n const steps = document.createElement(\"ol\");\n for (const [index, step] of record.steps.entries()) {\n const line = document.createElement(\"li\");\n const entry = state?.log.find(candidate => candidate.stepid === step.id);\n const done = index < latest.cursor;\n line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"})${done ? ` \u00B7 done${entry?.checkpoint === true ? \" \u00B7 checkpointed\" : \"\"}` : \"\"}${entry !== undefined ? ` \u00B7 ${entry.state}: ${entry.summary}` : \"\"}`;\n line.dataset.class = entry?.state === \"failed\" || entry?.state === \"refused\" ? \"changed\" : done ? \"added\" : \"unavailable\";\n if (step.block !== undefined && index === latest.cursor) line.dataset.blockactive = \"true\";\n const singlestep = document.createElement(\"div\");\n singlestep.className = \"actions\";\n singlestep.append(button(\"Run single step\", async () => { const outcome = await request({ kind: \"executeworkflowstep\", runid: latest.id, stepid: step.id }) as { steps: Array<{ stepid: string; state: string; summary: string }> }; status(outcome.steps[0] ? `Single step ${outcome.steps[0].state}: ${outcome.steps[0].summary}` : \"The single step returned no outcome.\"); await refresh(); }));\n line.append(singlestep);\n steps.append(line);\n }\n timeline.append(steps);\n }\n const runlog = document.createElement(\"div\");\n for (const entry of state?.log ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.state} \u00B7 ${entry.label} \u00B7 ${entry.duration} ms${entry.produced !== undefined && entry.produced.length > 0 ? ` \u00B7 produced ${entry.produced.join(\", \")}` : \"\"}${entry.consumed !== undefined && entry.consumed.length > 0 ? ` \u00B7 consumed ${entry.consumed.join(\", \")}` : \"\"} \u00B7 ${entry.summary}`;\n line.dataset.class = entry.state === \"failed\" || entry.state === \"refused\" ? \"changed\" : \"added\";\n runlog.append(line);\n if (entry.details !== undefined && entry.details.control !== undefined) runlog.append(rendercontroldecision(entry));\n }\n timeline.append(runlog);\n workflowsroot.append(timeline);\n const scopes = state?.scopes ?? [];\n if (scopes.length > 0) {\n const scopeview = document.createElement(\"details\");\n scopeview.className = \"sessiongroup\";\n const scopesummary = document.createElement(\"summary\");\n scopesummary.textContent = `Variables per scope (${scopes.reduce((total, scope) => total + scope.variables.length, 0)} values)`;\n scopeview.append(scopesummary);\n for (const scope of scopes) {\n const line = document.createElement(\"p\");\n line.textContent = `Scope ${scope.name}${scope.parent !== undefined ? ` (child of ${scope.parent})` : \"\"}: ${scope.variables.length === 0 ? \"no variable\" : scope.variables.map(variable => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(\", \")}]` : String(variable.value)} (${variable.kind})`).join(\" \u00B7 \")}`;\n scopeview.append(line);\n }\n workflowsroot.append(scopeview);\n }\n const provenance = state?.provenance ?? [];\n if (provenance.length > 0) {\n const provenanceview = document.createElement(\"details\");\n provenanceview.className = \"sessiongroup\";\n const provsummary = document.createElement(\"summary\");\n provsummary.textContent = `Provenance (${provenance.length} entries)`;\n provenanceview.append(provsummary);\n for (const entry of provenance.slice(-12)) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.kind} \u00B7 ${entry.name} = ${Array.isArray(entry.value) ? `[${entry.value.join(\", \")}]` : String(entry.value)}`;\n provenanceview.append(line);\n }\n workflowsroot.append(provenanceview);\n }\n }\n}\n\n/** Saves one file from the panel through a local blob download so workflow exports and share bundles leave the browser only by the user's hand. */\nfunction savefile(filename: string, contents: string): void {\n const url = URL.createObjectURL(new Blob([contents], { type: \"application/octet-stream\" }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = filename;\n anchor.click();\n setTimeout(() => URL.revokeObjectURL(url), 10_000);\n}\n\n/** Renders the workflow editor view of the 1.1.53 release: the canvas with draggable nodes, typed binding sockets and block containers, the mini map with viewport navigation, the zoom that keeps labels readable, the undo and redo stacks, the block palette with search, the step library of every reviewed kind grouped by category, the step inspector with options, bindings and nested params, the variable inspector, the run log with breakpoint marks, the run history with filters, the version timeline with diffs and rollbacks, the import review before activation, the export and share buttons, the background run toggle, the watchdog status and the per site policy override editor. */\nfunction renderworkfloweditor(context: { session?: { stoppedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[]; runs: workflowrun[]; templates: steptemplate[]; log: runlogentry[]; scopes: variablescope[] }; editor?: { versions: workflowversion[]; diffs: versiondiff[]; history: runhistoryentry[]; breakpoints: string[]; overrides: siteoverride[]; imports: Array<{ id: string; workflowid: string; name: string; version: number; steps: number; risk: string; importedat: number; filename?: string }>; backgroundruns: Record<string, boolean>; watchdog: { config?: watchdogconfig; events: watchdogrecord[] } } }): void {\n if (!workfloweditorroot) return;\n workfloweditorroot.replaceChildren();\n const editor = context.editor;\n const workflows = context.workflow?.workflows ?? [];\n const title = document.createElement(\"p\");\n title.textContent = `${workflows.length} workflow${workflows.length === 1 ? \"\" : \"s\"} in the library \u00B7 ${editor?.versions.length ?? 0} version${(editor?.versions.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.history.length ?? 0} run history entr${(editor?.history.length ?? 0) === 1 ? \"y\" : \"ies\"} \u00B7 ${editor?.imports.length ?? 0} pending import${(editor?.imports.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.overrides.length ?? 0} site override${(editor?.overrides.length ?? 0) === 1 ? \"\" : \"s\"} \u00B7 ${editor?.watchdog.events.length ?? 0} watchdog event${(editor?.watchdog.events.length ?? 0) === 1 ? \"\" : \"s\"}.`;\n workfloweditorroot.append(title);\n const openrow = document.createElement(\"div\");\n openrow.className = \"actions\";\n for (const record of workflows) {\n openrow.append(button(`${record.name} v${record.version}`, async () => {\n const loaded = await request({ kind: \"editormodel\", workflowid: record.id }) as { model: editormodel };\n editorview.workflowid = record.id;\n editorview.model = loaded.model;\n editorview.selected = [];\n editorview.inspector = \"\";\n status(`Opened ${record.name} v${record.version} on the canvas with ${loaded.model.nodes.length} nodes.`);\n await refresh();\n }), \" \");\n }\n if (editorview.model !== undefined) openrow.append(button(\"Close canvas\", async () => { editorview.workflowid = \"\"; editorview.model = undefined; editorview.selected = []; editorview.inspector = \"\"; editorview.diff = undefined; status(\"Canvas closed; the stored versions survive.\"); await refresh(); }));\n workfloweditorroot.append(openrow);\n const model = editorview.model;\n if (model !== undefined) {\n /** Renders one canvas node element with its typed sockets, breakpoint mark, selection outline and pointer drag wiring. */\n const nodeelement = (node: editornode): HTMLElement => {\n const element = document.createElement(\"div\");\n element.className = \"editornode\";\n element.style.left = `${node.x}px`;\n element.style.top = `${node.y}px`;\n const id = node.id ?? node.step?.id ?? node.invocation?.block ?? \"\";\n element.dataset.selected = editorview.selected.includes(id) ? \"true\" : \"false\";\n element.dataset.breakpoint = node.step?.breakpoint === true ? \"true\" : \"false\";\n element.dataset.invocation = node.invocation !== undefined ? \"true\" : \"false\";\n const kind = document.createElement(\"p\");\n kind.className = \"nodekind\";\n kind.textContent = node.step !== undefined ? node.step.kind : `block ${node.invocation?.block ?? \"\"}`;\n element.append(kind);\n const label = document.createElement(\"p\");\n label.textContent = node.step !== undefined ? node.step.label : (node.invocation?.label ?? \"\");\n element.append(label);\n if (node.invocation !== undefined) {\n const nested = model.blocks.find(block => block.name === node.invocation?.block);\n for (const entry of nested?.steps ?? []) {\n const child = document.createElement(\"p\");\n child.textContent = entry && \"kind\" in entry ? `\u00B7 ${entry.label} (${entry.kind})` : `\u00B7 block ${(entry as { block: string }).block}`;\n element.append(child);\n }\n }\n const sockets = document.createElement(\"p\");\n const targets = node.invocation !== undefined ? [id, ...(model.blocks.find(block => block.name === node.invocation?.block)?.steps ?? []).flatMap(entry => \"id\" in entry ? [entry.id] : [])] : [id];\n for (const edge of model.edges.filter(candidate => targets.includes(candidate.to))) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket in\";\n socket.textContent = `${edge.variable} (${edge.kind})`;\n sockets.append(socket, \" \");\n }\n for (const edge of model.edges.filter(candidate => candidate.from === id)) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket out\";\n socket.textContent = `${edge.variable} \u2192`;\n sockets.append(socket, \" \");\n }\n if (node.invocation?.params !== undefined && node.invocation.params.length > 0) {\n for (const param of node.invocation.params) {\n const socket = document.createElement(\"span\");\n socket.className = \"socket\";\n socket.textContent = `${param.name}: ${param.kind}`;\n sockets.append(socket, \" \");\n }\n }\n element.append(sockets);\n element.addEventListener(\"click\", () => { editorview.selected = [id]; editorview.inspector = id; void refresh(); });\n if (node.step !== undefined) {\n element.addEventListener(\"pointerdown\", event => {\n if (event.button !== 0) return;\n const startx = event.clientX;\n const starty = event.clientY;\n const originx = node.x;\n const originy = node.y;\n element.setPointerCapture(event.pointerId);\n const move = (moveevent: PointerEvent): void => { element.style.left = `${originx + moveevent.clientX - startx}px`; element.style.top = `${originy + moveevent.clientY - starty}px`; };\n const drop = (upevent: PointerEvent): void => {\n element.removeEventListener(\"pointermove\", move);\n element.removeEventListener(\"pointerup\", drop);\n void (async () => {\n if (editorview.model === undefined) return;\n try {\n editorview.model = snapnode(editorview.model, id, originx + upevent.clientX - startx, originy + upevent.clientY - starty);\n status(`Snapped ${id} onto the block grid; drop it near a block column to attach.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n })();\n };\n element.addEventListener(\"pointermove\", move);\n element.addEventListener(\"pointerup\", drop);\n });\n }\n return element;\n };\n const canvascard = document.createElement(\"div\");\n canvascard.className = \"sessionrow\";\n const toolbar = document.createElement(\"div\");\n toolbar.className = \"actions\";\n toolbar.append(button(\"Undo\", async () => { if (editorview.model === undefined) return; editorview.model = undoedit(editorview.model); status(\"Canvas edit undone; the redo stack keeps it.\"); await refresh(); }, (model.undo ?? []).length === 0));\n toolbar.append(\" \", button(\"Redo\", async () => { if (editorview.model === undefined) return; editorview.model = redoedit(editorview.model); status(\"Canvas edit redone.\"); await refresh(); }, (model.redo ?? []).length === 0));\n toolbar.append(\" \", button(\"Toggle breakpoint\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") { status(\"Select a step node first.\", true); return; } editorview.model = markbreakpoint(editorview.model, editorview.inspector); status(`Breakpoint toggled on ${editorview.inspector}; a debug run pauses before it.`); await refresh(); }));\n toolbar.append(\" \", button(\"Remove selected\", async () => { if (editorview.model === undefined || editorview.selected.length === 0) { status(\"Select a node first.\", true); return; } try { for (const id of editorview.selected) editorview.model = removenode(editorview.model, id); editorview.selected = []; editorview.inspector = \"\"; status(\"Node removed with its edges; undo brings it back.\"); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n toolbar.append(\" \", button(\"Move up\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") return; const index = editorview.model.nodes.findIndex(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector); try { if (index > 0) editorview.model = reordersteps(editorview.model, editorview.inspector, index - 1); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n toolbar.append(\" \", button(\"Move down\", async () => { if (editorview.model === undefined || editorview.inspector === \"\") return; const index = editorview.model.nodes.findIndex(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector); try { if (index >= 0 && index < editorview.model.nodes.length - 1) editorview.model = reordersteps(editorview.model, editorview.inspector, index + 1); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n const grouprow = document.createElement(\"div\");\n grouprow.className = \"actions\";\n const groupinput = document.createElement(\"input\");\n groupinput.type = \"text\";\n groupinput.placeholder = \"blockname\";\n grouprow.append(groupinput, \" \", button(\"Group selection into block\", async () => {\n if (editorview.model === undefined || editorview.selected.length === 0) { status(\"Select step nodes first.\", true); return; }\n try { editorview.model = groupselect(editorview.model, editorview.selected, groupinput.value.trim()); editorview.selected = []; status(`Grouped the selection into the block ${groupinput.value.trim()}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n canvascard.append(toolbar, grouprow);\n const canvas = document.createElement(\"div\");\n canvas.className = \"editorcanvas\";\n const layer = document.createElement(\"div\");\n layer.style.position = \"absolute\";\n layer.style.transformOrigin = \"0 0\";\n layer.style.left = \"0\";\n layer.style.top = \"0\";\n layer.style.width = `${model.layout.width}px`;\n layer.style.height = `${model.layout.height}px`;\n const zoom = model.layout.zoom > 0 ? model.layout.zoom : 1;\n layer.style.transform = `translate(${-Math.max(0, model.layout.viewportx)}px, ${-Math.max(0, model.layout.viewporty)}px) scale(${zoom})`;\n for (const block of model.blocks) {\n const members = model.nodes.filter(node => node.invocation?.block === block.name);\n if (members.length === 0) continue;\n const container = document.createElement(\"div\");\n container.className = \"editorblock\";\n const left = Math.min(...members.map(node => node.x)) - 14;\n const top = Math.min(...members.map(node => node.y)) - 14;\n container.style.left = `${left}px`;\n container.style.top = `${top}px`;\n container.style.width = `${Math.max(...members.map(node => node.x)) - left + 234}px`;\n container.style.height = `${Math.max(...members.map(node => node.y)) - top + 110}px`;\n const name = document.createElement(\"span\");\n name.textContent = block.name;\n container.append(name);\n layer.append(container);\n }\n for (const node of model.nodes) layer.append(nodeelement(node));\n canvas.append(layer);\n canvascard.append(canvas);\n const minimap = document.createElement(\"div\");\n minimap.className = \"editorminimap\";\n const projection = renderminimap(model);\n for (const dot of projection.nodes) {\n const point = document.createElement(\"span\");\n point.className = \"dot\";\n point.style.left = `${Math.min(dot.x, model.minimap.width - 5)}px`;\n point.style.top = `${Math.min(dot.y, model.minimap.height - 5)}px`;\n minimap.append(point);\n }\n const rect = document.createElement(\"span\");\n rect.className = \"viewportrect\";\n rect.style.left = `${Math.max(0, model.minimap.viewport.x)}px`;\n rect.style.top = `${Math.max(0, model.minimap.viewport.y)}px`;\n rect.style.width = `${Math.max(8, model.minimap.viewport.width)}px`;\n rect.style.height = `${Math.max(6, model.minimap.viewport.height)}px`;\n minimap.append(rect);\n minimap.addEventListener(\"click\", event => {\n void (async () => {\n if (editorview.model === undefined) return;\n const bounds = minimap.getBoundingClientRect();\n try {\n editorview.model = minimapfocus(editorview.model, event.clientX - bounds.left, event.clientY - bounds.top);\n status(\"Canvas jumped to the mini map region.\");\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n })();\n });\n canvascard.append(minimap);\n const zoomrow = document.createElement(\"div\");\n zoomrow.className = \"actions\";\n const zoominput = document.createElement(\"input\");\n zoominput.type = \"number\";\n zoominput.min = \"0.1\";\n zoominput.step = \"0.1\";\n zoominput.value = String(zoom);\n zoomrow.append(zoominput, \" \", button(\"Apply zoom\", async () => {\n if (editorview.model === undefined) return;\n try { const applied = zoomcanvas(editorview.model, Number(zoominput.value)); editorview.model = applied.model; status(`Canvas zoom ${Number(zoominput.value)} with label scale ${applied.labelscale.toFixed(2)} so every step label stays readable.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n const searchinput = document.createElement(\"input\");\n searchinput.type = \"text\";\n searchinput.placeholder = \"search steps by label, kind or variable\";\n searchinput.value = editorview.stepsearch;\n searchinput.addEventListener(\"input\", () => { editorview.stepsearch = searchinput.value; });\n zoomrow.append(searchinput, \" \", button(\"Search steps\", async () => { await refresh(); }));\n canvascard.append(zoomrow);\n const results = searchsteps(model, editorview.stepsearch);\n if (results.length > 0) {\n const list = document.createElement(\"ul\");\n for (const result of results) {\n const line = document.createElement(\"li\");\n line.textContent = `${result.label} (${result.kind}) matched ${result.matched.join(\", \")}`;\n list.append(line);\n }\n canvascard.append(list);\n }\n workfloweditorroot.append(canvascard);\n const inspector = model.nodes.find(node => (node.id ?? node.step?.id ?? node.invocation?.block ?? \"\") === editorview.inspector);\n if (inspector !== undefined) {\n const card = document.createElement(\"div\");\n card.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = inspector.step !== undefined ? `Step inspector of ${inspector.step.id}` : `Invocation inspector of block ${inspector.invocation?.block ?? \"\"}`;\n card.append(headline);\n if (inspector.step !== undefined) {\n const inspectedstep = inspector.step;\n const grid = document.createElement(\"div\");\n grid.className = \"editorgrid\";\n const labelinput = document.createElement(\"input\");\n labelinput.type = \"text\";\n labelinput.value = inspectedstep.label;\n const targetinput = document.createElement(\"input\");\n targetinput.type = \"text\";\n targetinput.placeholder = \"css target\";\n targetinput.value = inspectedstep.target ?? \"\";\n const valueinput = document.createElement(\"input\");\n valueinput.type = \"text\";\n valueinput.placeholder = \"value\";\n valueinput.value = inspectedstep.value ?? \"\";\n const optionsinput = document.createElement(\"input\");\n optionsinput.type = \"text\";\n optionsinput.placeholder = \"json options\";\n optionsinput.value = inspectedstep.options ?? \"\";\n for (const [labeltext, input] of [[\"label\", labelinput], [\"target\", targetinput], [\"value\", valueinput], [\"options json\", optionsinput]] as Array<[string, HTMLInputElement]>) {\n const fieldlabel = document.createElement(\"label\");\n fieldlabel.textContent = labeltext;\n fieldlabel.append(input);\n grid.append(fieldlabel);\n }\n card.append(grid, button(\"Save step edits\", async () => {\n if (editorview.model === undefined || inspectedstep === undefined) return;\n const options = optionsinput.value.trim() === \"\" ? undefined : optionsinput.value.trim();\n try {\n editorview.model = editstep(editorview.model, { ...inspectedstep, label: labelinput.value.trim(), ...(targetinput.value.trim() !== \"\" ? { target: targetinput.value.trim() } : {}), ...(valueinput.value.trim() !== \"\" ? { value: valueinput.value.trim() } : {}), ...(options !== undefined ? { options } : {}) });\n status(`Saved the edits of ${inspectedstep.id}; undo covers them.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n const bindings = document.createElement(\"details\");\n bindings.className = \"sessiongroup\";\n const bindingssummary = document.createElement(\"summary\");\n bindingssummary.textContent = `Bindings and nested params (${model.edges.filter(edge => edge.to === inspectedstep.id || edge.from === inspectedstep.id).length} edges)`;\n bindings.append(bindingssummary);\n for (const edge of model.edges.filter(candidate => candidate.to === inspectedstep?.id)) {\n const line = document.createElement(\"p\");\n line.textContent = `${edge.variable} (${edge.kind}) from ${edge.from}${edge.path !== undefined ? ` path ${edge.path}` : \"\"}`;\n line.append(\" \", button(\"Remove binding\", async () => { if (editorview.model === undefined) return; try { editorview.model = removeedge(editorview.model, edge.from, edge.to, edge.variable); status(`Removed the binding ${edge.variable}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n bindings.append(line);\n }\n const source = document.createElement(\"select\");\n for (const node of model.nodes) {\n if (node.step === undefined || node.step.id === inspectedstep.id) continue;\n const option = document.createElement(\"option\");\n option.value = node.step.id;\n option.textContent = `${node.step.id} (${node.step.kind})`;\n source.append(option);\n }\n const variableinput = document.createElement(\"input\");\n variableinput.type = \"text\";\n variableinput.placeholder = \"variable\";\n const kindselect = document.createElement(\"select\");\n for (const kind of [\"string\", \"number\", \"boolean\", \"list\", \"element\"] as variablekind[]) {\n const option = document.createElement(\"option\");\n option.value = kind;\n option.textContent = kind;\n kindselect.append(option);\n }\n const pathinput = document.createElement(\"input\");\n pathinput.type = \"text\";\n pathinput.placeholder = \"path into outcome details\";\n bindings.append(source, \" \", variableinput, \" \", kindselect, \" \", pathinput, \" \", button(\"Bind variable\", async () => {\n if (editorview.model === undefined) return;\n try {\n editorview.model = addedge(editorview.model, { from: source.value, to: inspectedstep?.id ?? \"\", variable: variableinput.value.trim(), kind: kindselect.value as variablekind, ...(pathinput.value.trim() !== \"\" ? { path: pathinput.value.trim() } : {}) });\n status(`Bound ${variableinput.value.trim()} from ${source.value}.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n card.append(bindings);\n }\n if (inspector.invocation !== undefined) {\n const paramgrid = document.createElement(\"div\");\n paramgrid.className = \"editorgrid\";\n const paramname = document.createElement(\"input\");\n paramname.type = \"text\";\n paramname.placeholder = \"param name\";\n const paramkind = document.createElement(\"select\");\n for (const kind of [\"string\", \"number\", \"boolean\", \"list\", \"element\"] as variablekind[]) {\n const option = document.createElement(\"option\");\n option.value = kind;\n option.textContent = kind;\n paramkind.append(option);\n }\n const paramdefault = document.createElement(\"input\");\n paramdefault.type = \"text\";\n paramdefault.placeholder = \"default value\";\n paramgrid.append(paramname, paramkind, paramdefault);\n card.append(paramgrid, button(\"Bind nested param\", async () => {\n if (editorview.model === undefined) return;\n try {\n const parseddefault = paramdefault.value.trim() === \"\" ? undefined : paramkind.value === \"number\" ? Number(paramdefault.value) : paramkind.value === \"boolean\" ? paramdefault.value === \"true\" : paramkind.value === \"list\" ? paramdefault.value.split(\",\").map(part => part.trim()) : paramdefault.value;\n editorview.model = bindparam(editorview.model, inspector.invocation?.block ?? \"\", { name: paramname.value.trim(), kind: paramkind.value as variablekind, ...(parseddefault !== undefined ? { default: parseddefault } : {}) });\n status(`Bound the nested param ${paramname.value.trim()} into ${inspector.invocation?.block ?? \"\"}.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n }\n workfloweditorroot.append(card);\n }\n const saverow = document.createElement(\"div\");\n saverow.className = \"sessionrow\";\n const nameinput = document.createElement(\"input\");\n nameinput.type = \"text\";\n nameinput.value = model.name;\n const originsinput = document.createElement(\"input\");\n originsinput.type = \"text\";\n originsinput.value = model.origins.join(\", \");\n const noteinput = document.createElement(\"input\");\n noteinput.type = \"text\";\n noteinput.placeholder = \"change note for the version timeline\";\n const versioninput = document.createElement(\"input\");\n versioninput.type = \"number\";\n versioninput.min = \"1\";\n versioninput.value = String(model.version + 1);\n saverow.append(nameinput, \" \", originsinput, \" \", versioninput, \" \", noteinput, \" \", button(\"Save canvas as new version\", async () => {\n if (editorview.model === undefined) return;\n editorview.model = { ...editorview.model, name: nameinput.value.trim(), origins: originsinput.value.split(\",\").map(origin => origin.trim()).filter(origin => origin !== \"\"), version: Number(versioninput.value) };\n try {\n const saved = await request({ kind: \"editorsave\", model: editorview.model, note: noteinput.value.trim() }) as { workflowid: string; version: number; steps: number; risk: string };\n status(`Saved ${saved.workflowid} as version ${saved.version}: ${saved.steps} expanded steps graded ${saved.risk} through the full grammar.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n workfloweditorroot.append(saverow);\n } else {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No canvas open; open a composed workflow above or import a workflow file below.\";\n workfloweditorroot.append(empty);\n }\n const palettecard = document.createElement(\"details\");\n palettecard.className = \"sessiongroup\";\n const palettesummary = document.createElement(\"summary\");\n palettesummary.textContent = \"Block palette and step library\";\n palettecard.append(palettesummary);\n const paletteactions = document.createElement(\"div\");\n paletteactions.className = \"actions\";\n const paletteinput = document.createElement(\"input\");\n paletteinput.type = \"text\";\n paletteinput.placeholder = \"search the palette by block or category\";\n paletteinput.value = editorview.palettesearch;\n paletteinput.addEventListener(\"input\", () => { editorview.palettesearch = paletteinput.value; });\n const libraryinput = document.createElement(\"input\");\n libraryinput.type = \"text\";\n libraryinput.placeholder = \"search the step library by kind or category\";\n libraryinput.value = editorview.librarysearch;\n libraryinput.addEventListener(\"input\", () => { editorview.librarysearch = libraryinput.value; });\n paletteactions.append(paletteinput, \" \", libraryinput, \" \", button(\"Load palette and library\", async () => {\n const loaded = await request({ kind: \"steplibrarystore\" }) as { categories: string[]; palette: palettenode[]; library: steplibraryentry[] };\n editorview.palette = loaded.palette;\n editorview.library = loaded.library;\n status(`Loaded ${loaded.palette.length} palette blocks and ${loaded.library.length} library kinds.`);\n await refresh();\n }));\n palettecard.append(paletteactions);\n const palettebody = document.createElement(\"div\");\n palettebody.className = \"editorpalette\";\n if (editorview.palette === undefined) {\n const hint = document.createElement(\"p\");\n hint.textContent = \"Load the palette to browse the curated drop blocks and every reviewed action kind grouped by category.\";\n palettebody.append(hint);\n } else {\n for (const category of palettecategories) {\n const blocks = editorview.palette.filter(node => node.category === category && `${node.label} ${node.kind} ${node.category}`.toLowerCase().includes(editorview.palettesearch.toLowerCase()));\n if (blocks.length === 0) continue;\n const head = document.createElement(\"p\");\n head.className = \"palettecategory\";\n head.textContent = category;\n palettebody.append(head);\n for (const block of blocks) {\n palettebody.append(button(block.label, async () => {\n if (editorview.model === undefined) { status(\"Open a canvas first.\", true); return; }\n try { editorview.model = addnode(editorview.model, { id: block.kind, kind: block.kind as actionkind, label: block.label }); status(`Dropped ${block.label} onto the canvas; the step inspector edits its target and options.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \");\n }\n }\n }\n if (editorview.library !== undefined) {\n for (const category of palettecategories) {\n const kinds = editorview.library.filter(entry => entry.category === category && `${entry.kind} ${entry.category}`.toLowerCase().includes(editorview.librarysearch.toLowerCase()));\n if (kinds.length === 0) continue;\n const head = document.createElement(\"p\");\n head.className = \"palettecategory\";\n head.textContent = `${category} library`;\n palettebody.append(head);\n const list = document.createElement(\"ul\");\n for (const entry of kinds) {\n const line = document.createElement(\"li\");\n line.textContent = `${entry.kind}${entry.optionschema.length > 0 ? ` \u00B7 options: ${entry.optionschema.map(option => `${option.name} ${option.kind}${option.required === true ? \" (required)\" : \"\"}`).join(\", \")}` : \"\"}`;\n list.append(line);\n }\n palettebody.append(list);\n }\n }\n palettecard.append(palettebody);\n workfloweditorroot.append(palettecard);\n if (model !== undefined && editor !== undefined) {\n const versioncard = document.createElement(\"details\");\n versioncard.className = \"sessiongroup\";\n const versionopen = editorview.diff !== undefined;\n if (versionopen) versioncard.open = true;\n const versionsummary = document.createElement(\"summary\");\n versionsummary.textContent = `Version timeline (${editor.versions.filter(entry => entry.workflowid === editorview.workflowid).length} versions of this workflow)`;\n versioncard.append(versionsummary);\n for (const version of editor.versions.filter(entry => entry.workflowid === editorview.workflowid)) {\n const line = document.createElement(\"p\");\n line.className = \"diffrow\";\n line.textContent = `v${version.version} \u00B7 ${new Date(version.createdat).toISOString()} \u00B7 ${version.steps} steps \u00B7 ${version.risk ?? \"ungraded\"}${version.rollback === true ? \" \u00B7 rollback\" : \"\"} \u00B7 ${version.note}`;\n line.append(\" \", button(\"Roll back here\", async () => {\n try {\n const rolled = await request({ kind: \"rollbackversion\", workflowid: editorview.workflowid, version: version.version }) as { version: number; reviewstate: string };\n status(`Rolled back to v${version.version}; stored as v${rolled.version} and ${rolled.reviewstate} until the rollback review approves it.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n versioncard.append(line);\n }\n const diffrow = document.createElement(\"div\");\n diffrow.className = \"actions\";\n const frominput = document.createElement(\"input\");\n frominput.type = \"number\";\n frominput.min = \"1\";\n frominput.placeholder = \"from\";\n const toinput = document.createElement(\"input\");\n toinput.type = \"number\";\n toinput.min = \"1\";\n toinput.placeholder = \"to\";\n diffrow.append(frominput, \" \", toinput, \" \", button(\"Diff versions\", async () => {\n try {\n const diff = await request({ kind: \"diffversions\", workflowid: editorview.workflowid, from: Number(frominput.value), to: Number(toinput.value) }) as versiondiff;\n editorview.diff = diff;\n status(`Diffed v${diff.from} into v${diff.to}: ${diff.added.length} added, ${diff.removed.length} removed, ${diff.changed.length} changed.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n versioncard.append(diffrow);\n if (editorview.diff !== undefined) {\n const diff = editorview.diff;\n const card = document.createElement(\"div\");\n card.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Version diff v${diff.from} \u2192 v${diff.to}`;\n card.append(headline);\n for (const added of diff.added) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"added\"; line.textContent = `+ ${added.stepid} (${added.kind}) ${added.label}`; card.append(line); }\n for (const removed of diff.removed) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"removed\"; line.textContent = `- ${removed.stepid} (${removed.kind}) ${removed.label}`; card.append(line); }\n for (const changed of diff.changed) { const line = document.createElement(\"p\"); line.className = \"diffrow\"; line.dataset.class = \"changed\"; line.textContent = `~ ${changed.stepid} (${changed.kind}) ${changed.label}: ${changed.changes.join(\", \")}`; card.append(line); }\n card.append(button(\"Close diff\", async () => { editorview.diff = undefined; await refresh(); }));\n versioncard.append(card);\n }\n workfloweditorroot.append(versioncard);\n const backgroundrow = document.createElement(\"div\");\n backgroundrow.className = \"actions\";\n const backgroundcheck = document.createElement(\"input\");\n backgroundcheck.type = \"checkbox\";\n backgroundcheck.checked = editor.backgroundruns[editorview.workflowid] === true;\n const backgroundlabel = document.createElement(\"label\");\n backgroundlabel.append(backgroundcheck, \" keep runs of this workflow executing with the panel closed (checkpoints restore on every worker wake)\");\n backgroundrow.append(backgroundlabel);\n backgroundrow.append(button(\"Apply background toggle\", async () => {\n const result = await request({ kind: \"setbackgroundrun\", workflowid: editorview.workflowid, enabled: backgroundcheck.checked }) as { enabled: boolean };\n status(result.enabled ? \"Background runs stay alive with the panel closed; every step checkpoints.\" : \"Background runs off; a closed panel pauses the next run at its last checkpoint.\");\n await refresh();\n }));\n workfloweditorroot.append(backgroundrow);\n }\n if (context.workflow !== undefined) {\n const logcard = document.createElement(\"details\");\n logcard.className = \"sessiongroup\";\n const logsummary = document.createElement(\"summary\");\n logsummary.textContent = `Run log and variable inspector of the newest run (${context.workflow.log.length} entries)`;\n logcard.append(logsummary);\n const breakpoints = new Set([...(editor?.breakpoints ?? []), ...(context.workflow.workflows.find(record => record.id === editorview.workflowid)?.steps.flatMap(step => step.breakpoint === true ? [step.id] : []) ?? [])]);\n for (const entry of context.workflow.log) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.state} \u00B7 ${entry.label}${breakpoints.has(entry.stepid) ? \" \u00B7 breakpoint\" : \"\"} \u00B7 ${entry.duration} ms \u00B7 ${entry.summary}`;\n line.dataset.class = entry.state === \"failed\" || entry.state === \"refused\" ? \"changed\" : \"added\";\n logcard.append(line);\n }\n if (context.workflow.log.length === 0) { const empty = document.createElement(\"p\"); empty.textContent = \"No run log entry yet; run the workflow from the workflows view.\"; logcard.append(empty); }\n for (const scope of context.workflow.scopes) {\n const line = document.createElement(\"p\");\n line.textContent = `Scope ${scope.name}: ${scope.variables.length === 0 ? \"no variable\" : scope.variables.map(variable => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(\", \")}]` : String(variable.value)} (${variable.kind})`).join(\" \u00B7 \")}`;\n logcard.append(line);\n }\n workfloweditorroot.append(logcard);\n }\n const historycard = document.createElement(\"details\");\n historycard.className = \"sessiongroup\";\n if (editorview.history !== undefined) historycard.open = true;\n const historysummary = document.createElement(\"summary\");\n historysummary.textContent = `Run history (${editorview.history?.length ?? editor?.history.length ?? 0} entries)`;\n historycard.append(historysummary);\n const historyfilters = document.createElement(\"div\");\n historyfilters.className = \"actions\";\n const workflowselect = document.createElement(\"select\");\n const anyoption = document.createElement(\"option\");\n anyoption.value = \"\";\n anyoption.textContent = \"every workflow\";\n workflowselect.append(anyoption);\n for (const record of workflows) { const option = document.createElement(\"option\"); option.value = record.id; option.textContent = record.name; workflowselect.append(option); }\n workflowselect.value = editorview.historyfilter.workflowid;\n const outcomeinput = document.createElement(\"input\");\n outcomeinput.type = \"text\";\n outcomeinput.placeholder = \"outcome filter\";\n outcomeinput.value = editorview.historyfilter.outcome;\n historyfilters.append(workflowselect, \" \", outcomeinput, \" \", button(\"Apply history filters\", async () => {\n editorview.historyfilter = { workflowid: workflowselect.value, outcome: outcomeinput.value.trim() };\n try {\n const report = await request({ kind: \"runhistory\", ...(workflowselect.value !== \"\" ? { workflowid: workflowselect.value } : {}), ...(outcomeinput.value.trim() !== \"\" ? { outcome: outcomeinput.value.trim() } : {}) }) as { entries: runhistoryentry[] };\n editorview.history = report.entries;\n status(`Run history: ${report.entries.length} entries match the filters.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n historyfilters.append(button(\"Keep every entry\", async () => { await request({ kind: \"setrunhistoryretention\" }); status(\"Run history keeps every entry; no code ceiling applies.\"); await refresh(); }));\n historycard.append(historyfilters);\n const historyentries = editorview.history ?? editor?.history ?? [];\n for (const entry of historyentries.slice(0, 40)) {\n const line = document.createElement(\"div\");\n line.className = \"historyrow\";\n line.dataset.outcome = entry.outcome;\n const detail = document.createElement(\"p\");\n detail.textContent = `${entry.outcome} \u00B7 ${entry.steps}/${entry.total} steps \u00B7 ${entry.duration} ms \u00B7 ${entry.cause}${entry.dryrun === true ? \" \u00B7 dry run\" : \"\"} \u00B7 ${new Date(entry.startedat).toISOString()}`;\n line.append(detail);\n historycard.append(line);\n }\n workfloweditorroot.append(historycard);\n const filecard = document.createElement(\"details\");\n filecard.className = \"sessiongroup\";\n const filesummary = document.createElement(\"summary\");\n filesummary.textContent = \"Import, export and template sharing\";\n filecard.append(filesummary);\n const formatselect = document.createElement(\"select\");\n for (const format of [\"json\", \"yaml\"] as exportformat[]) { const option = document.createElement(\"option\"); option.value = format; option.textContent = format; formatselect.append(option); }\n const contentsinput = document.createElement(\"textarea\");\n contentsinput.rows = 4;\n contentsinput.placeholder = \"paste a workflow file to import\";\n const filenameinput = document.createElement(\"input\");\n filenameinput.type = \"text\";\n filenameinput.placeholder = \"source filename\";\n const importactions = document.createElement(\"div\");\n importactions.className = \"actions\";\n importactions.append(contentsinput, \" \", filenameinput, \" \", formatselect, \" \", button(\"Import workflow file\", async () => {\n if (contentsinput.value.trim() === \"\") { status(\"Paste the workflow file contents first.\", true); return; }\n try {\n const imported = await request({ kind: \"importworkflow\", contents: contentsinput.value, format: formatselect.value, ...(filenameinput.value.trim() !== \"\" ? { filename: filenameinput.value.trim() } : {}) }) as { importid: string; workflowid: string; name: string; version: number; steps: number; risk: string; templates: number };\n const review = await request({ kind: \"workflowreview\", workflowid: imported.workflowid }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> };\n editorview.importreview = { importid: imported.importid, workflowid: imported.workflowid, name: imported.name, version: imported.version, risk: imported.risk, steps: review.steps };\n status(`Imported ${imported.name} v${imported.version} with ${imported.steps} steps and ${imported.templates} templates; review before activation.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(importactions);\n if (editorview.importreview !== undefined) {\n const review = document.createElement(\"div\");\n review.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Import review of ${editorview.importreview.name} v${editorview.importreview.version} (${editorview.importreview.risk} for review): every expanded step shows before activation and nothing runs until approval.`;\n review.append(headline);\n const list = document.createElement(\"ol\");\n for (const step of editorview.importreview.steps) { const line = document.createElement(\"li\"); line.textContent = `${step.label} (${step.kind}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.target !== undefined ? ` \u00B7 ${step.target}` : \"\"})`; list.append(line); }\n review.append(list);\n review.append(button(\"Approve import\", async () => {\n try { const approved = await request({ kind: \"approveimport\", importid: editorview.importreview?.importid }) as { reviewstate: string }; status(`Import approved: ${approved.reviewstate}; the workflow runs behind the same gates.`); editorview.importreview = undefined; } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \", button(\"Reject import\", async () => {\n try { await request({ kind: \"rejectimport\", importid: editorview.importreview?.importid }); status(\"Import rejected; the pending record left the library.\"); editorview.importreview = undefined; } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(review);\n }\n for (const pending of editor?.imports ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `Pending import ${pending.name} v${pending.version} (${pending.steps} steps, ${pending.risk})${pending.filename !== undefined ? ` from ${pending.filename}` : \"\"}`;\n line.append(\" \", button(\"Review steps\", async () => {\n try {\n const steps = await request({ kind: \"workflowreview\", workflowid: pending.workflowid }) as { steps: Array<{ id: string; kind: string; label: string; block?: string; target?: string }> };\n editorview.importreview = { importid: pending.id, workflowid: pending.workflowid, name: pending.name, version: pending.version, risk: pending.risk, steps: steps.steps };\n status(`Import review of ${pending.name}: ${steps.steps.length} expanded steps.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n filecard.append(line);\n }\n const exportrow = document.createElement(\"div\");\n exportrow.className = \"actions\";\n const noteinput = document.createElement(\"input\");\n noteinput.type = \"text\";\n noteinput.placeholder = \"change note inside the file\";\n exportrow.append(noteinput, \" \", button(\"Export open workflow\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n try {\n const exported = await request({ kind: \"exportworkflow\", workflowid: editorview.workflowid, format: formatselect.value, ...(noteinput.value.trim() !== \"\" ? { note: noteinput.value.trim() } : {}) }) as { contents: string; filename: string; format: string };\n savefile(exported.filename, exported.contents);\n status(`Exported ${exported.filename} (${exported.contents.length} characters, ${exported.format}); the export review held every secret back.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n }), \" \", button(\"Share with templates\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n try {\n const shared = await request({ kind: \"shareworkflow\", workflowid: editorview.workflowid, format: formatselect.value, ...(noteinput.value.trim() !== \"\" ? { note: noteinput.value.trim() } : {}) }) as { contents: string; filename: string };\n savefile(shared.filename, shared.contents);\n status(`Packed the share bundle ${shared.filename}; templates travel with the workflow.`);\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n }));\n filecard.append(exportrow);\n workfloweditorroot.append(filecard);\n const watchdogcard = document.createElement(\"details\");\n watchdogcard.className = \"sessiongroup\";\n const watchdogsummary = document.createElement(\"summary\");\n const watchdogconfig = editor?.watchdog.config;\n watchdogsummary.textContent = `Watchdog status (${editor?.watchdog.events.length ?? 0} events)`;\n watchdogcard.append(watchdogsummary);\n const watchdoggrid = document.createElement(\"div\");\n watchdoggrid.className = \"editorgrid\";\n const enabledcheck = document.createElement(\"input\");\n enabledcheck.type = \"checkbox\";\n enabledcheck.checked = watchdogconfig?.enabled === true;\n const thresholdinput = document.createElement(\"input\");\n thresholdinput.type = \"number\";\n thresholdinput.min = \"1\";\n thresholdinput.placeholder = \"stall threshold ms\";\n thresholdinput.value = watchdogconfig !== undefined ? String(watchdogconfig.stallthreshold) : \"\";\n const actionselect = document.createElement(\"select\");\n for (const action of [\"retry\", \"pause\", \"cancel\"]) { const option = document.createElement(\"option\"); option.value = action; option.textContent = action; actionselect.append(option); }\n actionselect.value = watchdogconfig?.action ?? \"pause\";\n const zombieinput = document.createElement(\"input\");\n zombieinput.type = \"number\";\n zombieinput.min = \"1\";\n zombieinput.placeholder = \"zombie window ms\";\n zombieinput.value = watchdogconfig?.zombiewindow !== undefined ? String(watchdogconfig.zombiewindow) : \"\";\n for (const [labeltext, control] of [[\"enabled\", enabledcheck], [\"stall threshold ms\", thresholdinput], [\"recovery action\", actionselect], [\"zombie window ms\", zombieinput]] as Array<[string, HTMLElement]>) { const fieldlabel = document.createElement(\"label\"); fieldlabel.textContent = labeltext; fieldlabel.append(control); watchdoggrid.append(fieldlabel); }\n watchdogcard.append(watchdoggrid);\n const watchdogactions = document.createElement(\"div\");\n watchdogactions.className = \"actions\";\n watchdogactions.append(button(\"Save watchdog config\", async () => {\n try {\n await request({ kind: \"setwatchdog\", config: { enabled: enabledcheck.checked, stallthreshold: Number(thresholdinput.value), action: actionselect.value as \"retry\" | \"pause\" | \"cancel\", ...(zombieinput.value.trim() !== \"\" ? { zombiewindow: Number(zombieinput.value) } : {}) } });\n status(\"Watchdog saved; thresholds stay user values with no code ceiling.\");\n } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }), \" \", button(\"Scan now\", async () => {\n try { const scan = await request({ kind: \"watchdogscan\" }) as { events: watchdogrecord[] }; status(`Watchdog scan: ${scan.events.length} stalled or zombie run${scan.events.length === 1 ? \"\" : \"s\"} recovered.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n watchdogcard.append(watchdogactions);\n for (const event of (editor?.watchdog.events ?? []).slice(0, 15)) {\n const line = document.createElement(\"p\");\n line.textContent = `${event.verdict} \u00B7 ${event.action} \u00B7 ${new Date(event.at).toISOString()} \u00B7 ${event.outcome}`;\n watchdogcard.append(line);\n }\n workfloweditorroot.append(watchdogcard);\n const overridecard = document.createElement(\"details\");\n overridecard.className = \"sessiongroup\";\n const overridesummary = document.createElement(\"summary\");\n overridesummary.textContent = `Per site policy overrides (${editor?.overrides.length ?? 0})`;\n overridecard.append(overridesummary);\n const overridegrid = document.createElement(\"div\");\n overridegrid.className = \"editorgrid\";\n const patterninput = document.createElement(\"input\");\n patterninput.type = \"text\";\n patterninput.placeholder = \"https://origin or https://*.origin\";\n const knobinputs: Array<[string, HTMLInputElement]> = [];\n for (const knob of [\"loopbound\", \"stepms\", \"runms\", \"waitms\", \"delaybase\"]) {\n const input = document.createElement(\"input\");\n input.type = \"number\";\n input.min = \"1\";\n input.placeholder = knob;\n knobinputs.push([knob, input]);\n const fieldlabel = document.createElement(\"label\");\n fieldlabel.textContent = knob;\n fieldlabel.append(input);\n overridegrid.append(fieldlabel);\n }\n const patternlabel = document.createElement(\"label\");\n patternlabel.textContent = \"origin pattern\";\n patternlabel.append(patterninput);\n overridegrid.prepend(patternlabel);\n overridecard.append(overridegrid, button(\"Attach override\", async () => {\n if (editorview.workflowid === \"\") { status(\"Open a workflow on the canvas first.\", true); return; }\n const deltas: Record<string, number> = {};\n for (const [knob, input] of knobinputs) if (input.value.trim() !== \"\" && Number.isFinite(Number(input.value)) && Number(input.value) > 0) deltas[knob] = Number(input.value);\n try { await request({ kind: \"setsiteoverride\", workflowid: editorview.workflowid, pattern: patterninput.value.trim(), deltas }); status(`Attached the override ${patterninput.value.trim()} with ${Object.keys(deltas).length} knob delta${Object.keys(deltas).length === 1 ? \"\" : \"s\"}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); }\n await refresh();\n }));\n for (const override of editor?.overrides ?? []) {\n const line = document.createElement(\"p\");\n line.textContent = `${override.pattern} of ${override.workflowid}: ${Object.entries(override.deltas).map(([knob, delta]) => `${knob} ${delta}`).join(\", \") || \"no delta\"}`;\n line.append(\" \", button(\"Remove override\", async () => { try { await request({ kind: \"removesiteoverride\", id: override.id }); status(`Removed the override ${override.pattern}.`); } catch (error) { status(error instanceof Error ? error.message : String(error), true); } await refresh(); }));\n overridecard.append(line);\n }\n workfloweditorroot.append(overridecard);\n}\n\n\n/** Renders the trigger section: every armed rule grouped per workflow with its enable and disable toggle, the next scheduled fire of cron and interval rules, the fire history, the visit rule creation from the current page, rule duplication to a second workflow, the manual run step preview with approve and cancel, webhook rule status with secret rotation and the fire retention setting. */\nfunction rendertriggers(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number }; plan?: agentplan; workflow?: { workflows: workflowrecord[] }; trigger?: { rules: Array<{ id: string; kind: string; workflowid: string; workflowname?: string; label: string; enabled: boolean; paused?: boolean; cooldown: number; lastfireat?: number; nextfireat?: number; fires: number; launches: number; suppressions: number; summary: Record<string, unknown> }>; queued: number }; triggerretention?: number }): void {\n if (!triggersroot) return;\n triggersroot.replaceChildren();\n const rules = context.trigger?.rules ?? [];\n const queued = context.trigger?.queued ?? 0;\n const workflows = context.workflow?.workflows ?? [];\n const title = document.createElement(\"p\");\n title.textContent = `${rules.length} armed rule${rules.length === 1 ? \"\" : \"s\"} across ${new Set(rules.map(rule => rule.workflowid)).size} workflow${new Set(rules.map(rule => rule.workflowid)).size === 1 ? \"\" : \"s\"} \u00B7 ${queued} queued fire${queued === 1 ? \"\" : \"s\"}${context.session?.pausedat !== undefined ? \" held while the session is paused\" : \"\"}.`;\n triggersroot.append(title);\n const byworkflow = new Map<string, typeof rules>();\n for (const rule of rules) {\n const group = byworkflow.get(rule.workflowid) ?? [];\n group.push(rule);\n byworkflow.set(rule.workflowid, group);\n }\n for (const [workflowid, group] of byworkflow) {\n const workflowname = group[0]?.workflowname ?? workflowid;\n const box = document.createElement(\"details\");\n box.className = \"sessiongroup\";\n box.open = true;\n const summary = document.createElement(\"summary\");\n summary.textContent = `${workflowname} \u00B7 ${group.length} rule${group.length === 1 ? \"\" : \"s\"}`;\n box.append(summary);\n for (const rule of group) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = rule.enabled ? (rule.paused === true ? \"paused\" : \"enabled\") : \"disabled\";\n const match = rule.summary.pattern !== undefined ? String(rule.summary.pattern) : rule.summary.origins !== undefined ? (rule.summary.origins as string[]).join(\", \") : rule.summary.cron !== undefined ? `${String(rule.summary.cron)}${rule.summary.timezone !== undefined ? ` (${String(rule.summary.timezone)})` : \"\"}` : rule.summary.period !== undefined ? `every ${String(rule.summary.period)} ms${rule.summary.jitter !== undefined ? ` \u00B1 ${String(rule.summary.jitter)} ms` : \"\"}` : rule.summary.title !== undefined ? String(rule.summary.title) : rule.summary.command !== undefined ? String(rule.summary.command) : rule.summary.events !== undefined ? (rule.summary.events as string[]).join(\", \") : rule.kind === \"urllist\" ? `${(rule.summary.urls as string[] | undefined)?.length ?? 0} urls` : rule.kind === \"webhook\" ? `webhook with ${String(rule.summary.fields ?? 0)} schema fields` : \"toolbar button\";\n headline.append(`${rule.label} \u00B7 ${rule.kind} \u00B7 ${match} \u00B7 cooldown ${rule.cooldown} ms \u00B7 ${rule.fires} fire${rule.fires === 1 ? \"\" : \"s\"}, ${rule.launches} launch${rule.launches === 1 ? \"\" : \"es\"}, ${rule.suppressions} suppressed${rule.nextfireat !== undefined ? ` \u00B7 next fire ${new Date(rule.nextfireat).toISOString()}` : \"\"}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(rule.enabled ? \"Disable\" : \"Enable\", async () => { await request({ kind: \"toggletrigger\", ruleid: rule.id, enabled: !rule.enabled }); status(`The ${rule.kind} rule is now ${rule.enabled ? \"disabled\" : \"enabled\"}.`); await refresh(); }));\n actions.append(\" \", button(\"Fire history\", async () => { const result = await request({ kind: \"triggerhistory\", ruleid: rule.id }) as { fires: Array<{ id: string; ruleid: string; at: number; cause: string; url?: string; title?: string }> }; triggerview.history = result.fires; status(`Fire history: ${result.fires.length} fire record${result.fires.length === 1 ? \"\" : \"s\"} of the ${rule.kind} rule.`); await refresh(); }));\n actions.append(\" \", button(\"Fire manually\", async () => { const result = await request({ kind: \"firetrigger\", ruleid: rule.id }) as { fired: boolean; queued?: boolean; suppressed?: string }; status(result.fired ? `The ${rule.kind} rule fired${result.queued === true ? \" and queued for the busy run\" : \"\"}.` : `The ${rule.kind} rule suppressed the fire: ${result.suppressed ?? \"review gate\"}.`); await refresh(); }));\n if (rule.kind === \"webhook\") actions.append(\" \", button(\"Rotate secret\", async () => { const result = await request({ kind: \"rotatetriggersecret\", ruleid: rule.id }) as { secret: string }; status(`The webhook secret rotated to ${result.secret}; it was shown once and never leaves the store.`); await refresh(); }));\n if (workflows.length > 1) actions.append(\" \", button(\"Duplicate to second workflow\", async () => { const target = workflows.find(record => record.id !== rule.workflowid); if (!target) { status(\"No second composed workflow exists to duplicate the rule to.\", true); return; } await request({ kind: \"duplicatetrigger\", ruleid: rule.id, workflowid: target.id }); status(`Duplicated the ${rule.kind} rule to ${target.name}.`); await refresh(); }));\n row.append(actions);\n box.append(row);\n }\n const workflowactions = document.createElement(\"div\");\n workflowactions.className = \"actions\";\n workflowactions.append(button(\"Create visit rule from current page\", async () => { await request({ kind: \"createvisitrule\", workflowid }); status(`Armed a visit rule of the current page origin for ${workflowname}.`); await refresh(); }));\n workflowactions.append(\" \", button(\"Manual run preview\", async () => { const result = await request({ kind: \"manualrun\", workflowid }) as { manualrun: { id: string; workflowid: string; preview: Array<{ stepid: string; kind: string; label: string; block?: string; control?: Record<string, unknown> }> }; at: number }; triggerview.manual = { ...result.manualrun, at: Date.now() }; status(`Manual run preview: ${result.manualrun.preview.length} steps of ${workflowname}; nothing runs before the confirmation.`); await refresh(); }));\n box.append(workflowactions);\n triggersroot.append(box);\n }\n if (rules.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No armed trigger rule yet; arm a reviewed rule of any family or create a visit rule from the current page.\";\n triggersroot.append(empty);\n }\n if (triggerview.history !== undefined) {\n const history = document.createElement(\"details\");\n history.className = \"sessiongroup\";\n const summary = document.createElement(\"summary\");\n summary.textContent = `Fire history (${triggerview.history.length} records)`;\n history.append(summary);\n for (const fire of triggerview.history.slice(0, 25)) {\n const line = document.createElement(\"p\");\n line.textContent = `${new Date(fire.at).toISOString()} \u00B7 ${fire.cause}${fire.url !== undefined ? ` \u00B7 ${fire.url}` : \"\"}${fire.title !== undefined ? ` \u00B7 ${fire.title}` : \"\"}`;\n history.append(line);\n }\n triggersroot.append(history);\n }\n if (triggerview.manual !== undefined) {\n const preview = document.createElement(\"div\");\n preview.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n headline.textContent = `Manual run step preview: ${triggerview.manual.preview.length} expanded step${triggerview.manual.preview.length === 1 ? \"\" : \"s\"}; approve or cancel before anything runs.`;\n preview.append(headline);\n for (const step of triggerview.manual.preview) {\n const line = document.createElement(\"p\");\n line.textContent = `${step.stepid} \u00B7 ${step.kind} \u00B7 ${step.label}${step.block !== undefined ? ` \u00B7 block ${step.block}` : \"\"}${step.control !== undefined ? ` \u00B7 ${Object.entries(step.control).map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(\", \") : String(value)}`).join(\" \u00B7 \")}` : \"\"}`;\n preview.append(line);\n }\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve manual run\", async () => { const result = await request({ kind: \"confirmmanualrun\", previewid: triggerview.manual?.id, confirmed: true }) as { confirmed: boolean; runid?: string; state?: string }; status(`Manual run approved and launched${result.runid !== undefined ? ` as run ${result.runid}` : \"\"}; the run ended ${result.state ?? \"running\"}.`); triggerview.manual = undefined; await refresh(); }));\n actions.append(\" \", button(\"Cancel manual run\", async () => { await request({ kind: \"confirmmanualrun\", previewid: triggerview.manual?.id, confirmed: false }); status(\"Manual run cancelled after the step preview; nothing ran.\"); triggerview.manual = undefined; await refresh(); }));\n preview.append(actions);\n triggersroot.append(preview);\n }\n const settings = document.createElement(\"details\");\n settings.className = \"sessiongroup\";\n const settingsummary = document.createElement(\"summary\");\n settingsummary.textContent = \"Trigger settings\";\n settings.append(settingsummary);\n const retention = document.createElement(\"p\");\n retention.textContent = `Fire record retention: ${context.triggerretention === undefined ? \"keep every fire record\" : `${context.triggerretention} record${context.triggerretention === 1 ? \"\" : \"s\"}`}; the rule counters always survive and no code ceiling applies.`;\n settings.append(retention);\n const retentionactions = document.createElement(\"div\");\n retentionactions.className = \"actions\";\n retentionactions.append(button(\"Keep every fire record\", async () => { await request({ kind: \"settriggerretention\" }); status(\"Trigger fire retention keeps every record.\"); await refresh(); }));\n retentionactions.append(\" \", button(\"Keep last 100 fire records\", async () => { await request({ kind: \"settriggerretention\", retention: 100 }); status(\"Trigger fire retention keeps the last 100 records.\"); await refresh(); }));\n settings.append(retentionactions);\n triggersroot.append(settings);\n}\n\n/** Renders the agent protocol view: the mcp server status with start and stop, the localhost bind state and port, the connected clients with their transports, negotiated capabilities and pairing prompt, the disconnect control, the tool catalog grouped by namespace, the stdio bridge status with restart and the recent tool calls with caller and outcome. */\nfunction renderagentprotocol(context: { session?: { stoppedat?: number; pausedat?: number; expiresat: number }; mcp?: { state: string; config: { bind?: string; port: number; transports: string[]; framesize?: number; queuedepth?: number; callretention?: number; enabled: boolean; remote?: boolean; httpstream?: { endpoint: string; streampath: string; tls: { mode: string; certificatefingerprint?: string; verifiedat?: number }; heartbeatms?: number; idlewindowms?: number }; remoteaccess?: { endpoint: string; tls: { mode: string }; maxclients?: number; tokenlifetimems?: number; approvaltimeout?: { windowms: number } } }; bind: string; port: number; localhost: boolean; clients: Array<{ id: string; transport: string; paired: boolean; connectedat: number; capabilities?: { protocolversion: string; toolversion: number; tools: number; transports: string[] }; toolfloor?: number; fingerprint?: string; pairedat?: number }>; bridge?: { id: string; host: string; connected: boolean; restarts: number; received: number; sent: number; startedat: number }; calls: Array<{ id: string; clientid: string; tool: string; origin: string; ok: boolean; code?: string; at: number }>; catalog: { tools: Array<{ name: string; version: number; description: string; risk: string; consentmeta?: { review: string; riskclass: string; approvalrequired: boolean; originscope: string }; inputschema: { type: string; properties: Record<string, { type: string; description: string; required?: boolean }>; required: string[] } }> }; launches: Array<{ id: string; host: string; pid: number; restart: boolean; at: number }>; remote: { endpoint: string; tls: { mode: string; certificaterequired: boolean; verified: boolean }; clients: number; paired: number; channelsopen: number; channelsdead: number; tokenslive: number }; pairing: Array<{ code: string; scopes: string[]; issuedat: number; expiresat: number }>; allowlist: Array<{ fingerprint: string; displayname: string; namespaces: string[]; grantedat: number; history: Array<{ at: number; actor: string; change: string }> }>; tokens: Array<{ id: string; clientid: string; scopes: string[]; issuedat: number; expiresat: number; revokedat?: number }>; identities: Array<{ fingerprint: string; displayname: string }>; handshakes: Array<{ id: string; clientid: string; method: string; outcome: string; at: number }>; channels: Array<{ id: string; clientid: string; openedat: number; lastbeatat: number; closedat?: number }>; approvals: Array<{ id: string; clientid: string; tool: string; reason: string; params: Record<string, unknown>; state: string; raisedat: number; timeoutat?: number; decidedat?: number; secretfields?: string[] }> } }): void {\n if (!agentprotocolroot) return;\n agentprotocolroot.replaceChildren();\n const mcp = context.mcp;\n if (!mcp) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"The agent protocol state is unknown.\";\n agentprotocolroot.append(empty);\n return;\n }\n const running = mcp.state === \"running\";\n const head = document.createElement(\"p\");\n head.textContent = `Server ${mcp.state} \u00B7 ${mcp.bind}:${mcp.port}${mcp.localhost ? \" (localhost bind)\" : \" (remote bind behind the explicit review)\"} \u00B7 transports ${mcp.config.transports.join(\" and \")} \u00B7 ${mcp.catalog.tools.length} tools \u00B7 ${mcp.clients.length} connected client${mcp.clients.length === 1 ? \"\" : \"s\"}.`;\n agentprotocolroot.append(head);\n const controls = document.createElement(\"div\");\n controls.className = \"actions\";\n controls.append(button(running ? \"Stop server\" : \"Start server\", async () => { await request({ kind: running ? \"mcpserverstop\" : \"mcpserverstart\" }); status(running ? \"The mcp server stopped; no tool call passes the gates.\" : \"The mcp server started on the localhost bind; every client waits for the pairing approval.\"); await refresh(); }));\n const bindinput = document.createElement(\"input\");\n bindinput.placeholder = \"bind address (empty keeps localhost)\";\n bindinput.value = mcp.config.bind ?? \"\";\n const portinput = document.createElement(\"input\");\n portinput.placeholder = \"port\";\n portinput.value = String(mcp.config.port);\n controls.append(\" \", bindinput, \" \", portinput, \" \", button(\"Save config\", async () => { await request({ kind: \"mcpserverconfig\", bind: bindinput.value, port: Number(portinput.value), ...(bindinput.value.trim() !== \"\" && bindinput.value.trim() !== \"127.0.0.1\" && bindinput.value.trim() !== \"localhost\" && bindinput.value.trim() !== \"::1\" ? { remote: true } : {}) }); status(`Saved the mcp server config for ${bindinput.value.trim() === \"\" ? \"127.0.0.1\" : bindinput.value.trim()}:${portinput.value}.`); await refresh(); }));\n agentprotocolroot.append(controls);\n if (mcp.bridge !== undefined) {\n const bridge = document.createElement(\"p\");\n bridge.textContent = `Stdio bridge ${mcp.bridge.connected ? \"connected\" : \"disconnected\"} on the ${mcp.bridge.host} host \u00B7 ${mcp.bridge.restarts} restart${mcp.bridge.restarts === 1 ? \"\" : \"s\"} \u00B7 ${mcp.bridge.received} inbound and ${mcp.bridge.sent} outbound frame${mcp.bridge.sent === 1 ? \"\" : \"s\"}${mcp.launches.length > 0 ? ` \u00B7 last launch pid ${mcp.launches[0]?.pid ?? \"unknown\"}` : \" \u00B7 no host launch reported yet\"}.`;\n agentprotocolroot.append(bridge);\n const bridgeactions = document.createElement(\"div\");\n bridgeactions.className = \"actions\";\n bridgeactions.append(button(\"Restart bridge\", async () => { await request({ kind: \"mcpbridge\", action: \"restart\" }); status(\"The stdio bridge restart ran; the browser exposes the native messaging host only under a native messaging permission.\"); await refresh(); }));\n agentprotocolroot.append(bridgeactions);\n }\n const clientsbox = document.createElement(\"details\");\n clientsbox.className = \"sessiongroup\";\n clientsbox.open = true;\n const clientsummary = document.createElement(\"summary\");\n clientsummary.textContent = `Connected clients (${mcp.clients.length})`;\n clientsbox.append(clientsummary);\n for (const client of mcp.clients) {\n const row = document.createElement(\"div\");\n row.className = \"sessionrow\";\n const headline = document.createElement(\"p\");\n const badge = document.createElement(\"span\");\n badge.className = \"sessionbadge\";\n badge.dataset.restored = \"false\";\n badge.textContent = client.paired ? \"paired\" : \"waiting for approval\";\n headline.append(`${client.id} \u00B7 ${client.transport}${client.fingerprint !== undefined ? ` \u00B7 ${client.fingerprint.slice(0, 12)}` : \"\"}${client.capabilities !== undefined ? ` \u00B7 protocol ${client.capabilities.protocolversion} \u00B7 tool floor ${client.toolfloor ?? client.capabilities.toolversion} \u00B7 ${client.capabilities.tools} tools` : \" \u00B7 not negotiated yet\"}`, badge);\n row.append(headline);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n if (!client.paired) {\n actions.append(button(\"Approve pairing\", async () => { await request({ kind: \"mcpclientdecision\", clientid: client.id, approved: true }); status(`Approved the pairing of the client ${client.id}; its tool calls now pass the same consent gates.`); await refresh(); }));\n actions.append(\" \", button(\"Refuse pairing\", async () => { await request({ kind: \"mcpclientdecision\", clientid: client.id, approved: false }); status(`Refused and disconnected the client ${client.id}.`); await refresh(); }));\n }\n actions.append(button(\"Disconnect\", async () => { await request({ kind: \"mcpclientdisconnect\", clientid: client.id }); status(`Disconnected the client ${client.id}; its record stays for the audit trail.`); await refresh(); }));\n const clienttokens = mcp.tokens.filter(token => token.clientid === client.id && token.revokedat === undefined);\n for (const token of clienttokens) {\n const tokenline = document.createElement(\"p\");\n const remaining = Math.max(0, Math.round((token.expiresat - Date.now()) / 1000));\n tokenline.textContent = `Session token ${token.id.slice(0, 8)} \u00B7 scopes ${token.scopes.join(\", \") || \"none\"} \u00B7 expires in ${Math.floor(remaining / 60)}m ${remaining % 60}s${token.revokedat !== undefined ? \" \u00B7 revoked\" : \"\"}.`;\n row.append(tokenline);\n }\n actions.append(\" \", button(\"Revoke client\", async () => { await request({ kind: \"mcprevokeclient\", clientid: client.id }); status(`Revoked the client ${client.id}; its tokens stopped verifying at once.`); await refresh(); }));\n row.append(actions);\n clientsbox.append(row);\n }\n if (mcp.clients.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No connected client yet; a paired client speaks json rpc frames over the stdio bridge or an http post envelope.\";\n clientsbox.append(empty);\n }\n agentprotocolroot.append(clientsbox);\n const approvalsbox = document.createElement(\"details\");\n approvalsbox.className = \"sessiongroup\";\n approvalsbox.open = true;\n const approvalssummary = document.createElement(\"summary\");\n const pendingapprovals = mcp.approvals.filter(request => request.state === \"pending\");\n approvalssummary.textContent = `Approval gates (${pendingapprovals.length} pending, ${mcp.approvals.length - pendingapprovals.length} resolved)`;\n approvalsbox.append(approvalssummary);\n for (const gate of mcp.approvals.slice(0, 10)) {\n const card = document.createElement(\"div\");\n card.className = \"sessionrow\";\n const identity = mcp.identities.find(entry => entry.fingerprint === mcp.clients.find(client => client.id === gate.clientid)?.fingerprint);\n const headline = document.createElement(\"p\");\n const secrets = gate.secretfields ?? [];\n const shown: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(gate.params)) shown[name] = secrets.includes(name) ? \"[redacted]\" : value;\n headline.textContent = `${gate.state === \"pending\" ? \"PENDING\" : gate.state.toUpperCase()} \u00B7 ${identity?.displayname ?? gate.clientid} calls ${gate.tool} \u00B7 ${gate.reason} Arguments: ${JSON.stringify(shown)}${gate.timeoutat !== undefined ? ` \u00B7 refuses by default at ${new Date(gate.timeoutat).toISOString()}` : \"\"}.`;\n card.append(headline);\n if (gate.state === \"pending\") {\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(\"Approve\", async () => { await request({ kind: \"mcpapprovaldecision\", approvalid: gate.id, approved: true }); status(`Approved the ${gate.tool} call of the client ${gate.clientid}; the gate executed the held call.`); await refresh(); }));\n actions.append(\" \", button(\"Refuse\", async () => { await request({ kind: \"mcpapprovaldecision\", approvalid: gate.id, approved: false }); status(`Refused the ${gate.tool} call of the client ${gate.clientid}; the pending call never executes.`); await refresh(); }));\n card.append(actions);\n }\n approvalsbox.append(card);\n }\n if (mcp.approvals.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No approval gate yet; every sensitive call a remote client raises lands here with its full arguments before anything executes.\";\n approvalsbox.append(empty);\n }\n agentprotocolroot.append(approvalsbox);\n const remotebox = document.createElement(\"details\");\n remotebox.className = \"sessiongroup\";\n const remotesummary = document.createElement(\"summary\");\n remotesummary.textContent = `Remote transport (${mcp.remote.channelsopen} live channel${mcp.remote.channelsopen === 1 ? \"\" : \"s\"}, ${mcp.remote.channelsdead} closed)`;\n remotebox.append(remotesummary);\n const remoteline = document.createElement(\"p\");\n remoteline.textContent = `Endpoint ${mcp.remote.endpoint} \u00B7 tls ${mcp.remote.tls.mode}${mcp.remote.tls.certificaterequired ? \" (certificate required)\" : \"\"}${mcp.remote.tls.verified ? \" and verified\" : \" and unverified\"} \u00B7 ${mcp.remote.paired} of ${mcp.remote.clients} client${mcp.remote.clients === 1 ? \"\" : \"s\"} paired \u00B7 ${mcp.remote.tokenslive} live token${mcp.remote.tokenslive === 1 ? \"\" : \"s\"}.`;\n remotebox.append(remoteline);\n for (const channel of mcp.channels.slice(0, 10)) {\n const line = document.createElement(\"p\");\n const beatage = Math.max(0, Math.round((Date.now() - channel.lastbeatat) / 1000));\n line.textContent = `Stream channel ${channel.id.slice(0, 12)} of ${channel.clientid} \u00B7 ${channel.closedat === undefined ? `heartbeat ${beatage}s ago` : `closed at ${new Date(channel.closedat).toISOString()}`}.`;\n remotebox.append(line);\n }\n for (const shake of mcp.handshakes.slice(0, 5)) {\n const line = document.createElement(\"p\");\n line.textContent = `Auth handshake ${shake.method} of ${shake.clientid} \u00B7 ${shake.outcome}${shake.outcome === \"refused\" ? \" (consentrefused error, no pairing state leaked)\" : \"\"} \u00B7 ${new Date(shake.at).toISOString()}.`;\n remotebox.append(line);\n }\n const pairingline = document.createElement(\"p\");\n pairingline.textContent = mcp.pairing.length > 0 ? `Pairing code ${mcp.pairing[0]?.code} for ${mcp.pairing[0]?.scopes.join(\", \") || \"no\"} namespaces \u00B7 expires at ${new Date(mcp.pairing[0]?.expiresat ?? Date.now()).toISOString()} \u00B7 single use.` : \"No pairing code pending; issue one while a session is live to pair a remote client.\";\n remotebox.append(pairingline);\n const pairingactions = document.createElement(\"div\");\n pairingactions.className = \"actions\";\n pairingactions.append(button(\"Issue pairing code\", async () => { await request({ kind: \"mcppairing\", scopes: [\"browser\", \"workflow\", \"memory\", \"system\"] }); status(\"Issued one single use pairing code; copy it to the remote client before its window closes.\"); await refresh(); }));\n pairingactions.append(\" \", button(\"Copy pairing code\", async () => { const code = mcp.pairing[0]?.code ?? \"\"; if (code === \"\") { status(\"No pending pairing code to copy.\", true); return; } await navigator.clipboard.writeText(code).then(() => status(`Copied the pairing code ${code} to the clipboard.`)).catch(() => status(`Pairing code: ${code} (the clipboard permission was refused).`, true)); }));\n remotebox.append(pairingactions);\n const tlsheadline = document.createElement(\"p\");\n tlsheadline.textContent = \"Tls certificate options of the remote transport: the mode and the reviewed sha-256 fingerprint stay user choices with no hardcoded certificate.\";\n remotebox.append(tlsheadline);\n const tlsactions = document.createElement(\"div\");\n tlsactions.className = \"actions\";\n const endpointinput = document.createElement(\"input\");\n endpointinput.placeholder = \"remote endpoint url\";\n endpointinput.value = mcp.config.remoteaccess?.endpoint ?? \"\";\n const tlsmodeinput = document.createElement(\"input\");\n tlsmodeinput.placeholder = \"tls mode: off, on or required\";\n tlsmodeinput.value = mcp.config.remoteaccess?.tls.mode ?? \"off\";\n const certinput = document.createElement(\"input\");\n certinput.placeholder = \"certificate sha-256 fingerprint\";\n certinput.value = mcp.config.httpstream?.tls.certificatefingerprint ?? \"\";\n const maxclientsinput = document.createElement(\"input\");\n maxclientsinput.placeholder = \"max clients (empty: unbounded)\";\n maxclientsinput.value = mcp.config.remoteaccess?.maxclients !== undefined ? String(mcp.config.remoteaccess.maxclients) : \"\";\n const timeoutinput = document.createElement(\"input\");\n timeoutinput.placeholder = \"approval window ms\";\n timeoutinput.value = mcp.config.remoteaccess?.approvaltimeout !== undefined ? String(mcp.config.remoteaccess.approvaltimeout.windowms) : \"\";\n tlsactions.append(endpointinput, \" \", tlsmodeinput, \" \", certinput, \" \", maxclientsinput, \" \", timeoutinput, \" \", button(\"Save remote config\", async () => { await request({ kind: \"mcpremoteconfig\", endpoint: endpointinput.value, tlsmode: tlsmodeinput.value, ...(certinput.value.trim() !== \"\" ? { certificatefingerprint: certinput.value } : {}), ...(maxclientsinput.value.trim() !== \"\" ? { maxclients: Number(maxclientsinput.value) } : {}), ...(timeoutinput.value.trim() !== \"\" ? { approvaltimeoutms: Number(timeoutinput.value) } : {}), reviewed: true }); status(`Saved the remote transport config for ${endpointinput.value} with the ${tlsmodeinput.value} tls mode.`); await refresh(); }));\n remotebox.append(tlsactions);\n agentprotocolroot.append(remotebox);\n const allowlistbox = document.createElement(\"details\");\n allowlistbox.className = \"sessiongroup\";\n const allowlistsummary = document.createElement(\"summary\");\n allowlistsummary.textContent = `Client allowlist (${mcp.allowlist.length} entr${mcp.allowlist.length === 1 ? \"y\" : \"ies\"})`;\n allowlistbox.append(allowlistsummary);\n for (const entry of mcp.allowlist) {\n const line = document.createElement(\"p\");\n line.textContent = `${entry.displayname} \u00B7 ${entry.fingerprint.slice(0, 12)} \u00B7 namespaces ${entry.namespaces.join(\", \") || \"none\"} \u00B7 granted ${new Date(entry.grantedat).toISOString()} \u00B7 ${entry.history.length} grant change${entry.history.length === 1 ? \"\" : \"s\"}.`;\n allowlistbox.append(line);\n const actions = document.createElement(\"div\");\n actions.className = \"actions\";\n actions.append(button(`Rescope to browser+memory`, async () => { await request({ kind: \"mcpallowlist\", fingerprint: entry.fingerprint, displayname: entry.displayname, namespaces: [\"browser\", \"memory\"] }); status(`Rescoped the allowlist entry ${entry.displayname} to the browser and memory namespaces.`); await refresh(); }));\n actions.append(\" \", button(\"Refuse entry\", async () => { await request({ kind: \"mcpallowlist\", fingerprint: entry.fingerprint, remove: true }); status(`Refused the allowlist entry ${entry.displayname}; its fingerprint stops passing the check.`); await refresh(); }));\n allowlistbox.append(actions);\n }\n const allowactions = document.createElement(\"div\");\n allowactions.className = \"actions\";\n const fingerprintinput = document.createElement(\"input\");\n fingerprintinput.placeholder = \"client fingerprint\";\n const displayinput = document.createElement(\"input\");\n displayinput.placeholder = \"display name\";\n const scopesinput = document.createElement(\"input\");\n scopesinput.placeholder = \"namespaces: browser,workflow,memory,system\";\n allowactions.append(fingerprintinput, \" \", displayinput, \" \", scopesinput, \" \", button(\"Allow client\", async () => { const namespaces = scopesinput.value.split(\",\").map(scope => scope.trim()).filter(scope => scope !== \"\"); await request({ kind: \"mcpallowlist\", fingerprint: fingerprintinput.value, ...(displayinput.value.trim() !== \"\" ? { displayname: displayinput.value } : {}), namespaces }); status(`Allowed the client ${displayinput.value || fingerprintinput.value} the ${namespaces.join(\", \") || \"no\"} namespaces.`); await refresh(); }));\n allowlistbox.append(allowactions);\n if (mcp.allowlist.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No allowlist entry yet; a remote client pairs through the one time code or the user allows a known fingerprint with its namespace scopes.\";\n allowlistbox.append(empty);\n }\n agentprotocolroot.append(allowlistbox);\n const catalogbox = document.createElement(\"details\");\n catalogbox.className = \"sessiongroup\";\n const catalogsummary = document.createElement(\"summary\");\n catalogsummary.textContent = `Tool catalog (${mcp.catalog.tools.length} tools by namespace)`;\n catalogbox.append(catalogsummary);\n const bynamespace = new Map<string, typeof mcp.catalog.tools>();\n for (const tool of mcp.catalog.tools) {\n const namespace = tool.name.split(\".\")[0] ?? \"browser\";\n const group = bynamespace.get(namespace) ?? [];\n group.push(tool);\n bynamespace.set(namespace, group);\n }\n for (const [namespace, tools] of bynamespace) {\n const domain = document.createElement(\"details\");\n domain.className = \"sessiongroup\";\n const domainsummary = document.createElement(\"summary\");\n domainsummary.textContent = `${namespace} (${tools.length} tools)`;\n domain.append(domainsummary);\n for (const tool of tools) {\n const line = document.createElement(\"p\");\n line.textContent = `${tool.name} v${tool.version} \u00B7 ${tool.risk} \u00B7 ${tool.description.split(\".\")[0] ?? tool.description}${tool.consentmeta !== undefined ? ` \u00B7 ${tool.consentmeta.riskclass} \u00B7 approval gate ${tool.consentmeta.approvalrequired ? \"required\" : \"off\"} \u00B7 ${tool.consentmeta.originscope} scope \u00B7 review: ${tool.consentmeta.review}` : \"\"}`;\n domain.append(line);\n }\n catalogbox.append(domain);\n }\n agentprotocolroot.append(catalogbox);\n const callsbox = document.createElement(\"details\");\n callsbox.className = \"sessiongroup\";\n const callssummary = document.createElement(\"summary\");\n callssummary.textContent = `Recent tool calls (${mcp.calls.length})`;\n callsbox.append(callssummary);\n for (const call of mcp.calls.slice(0, 25)) {\n const line = document.createElement(\"p\");\n line.textContent = `${new Date(call.at).toISOString()} \u00B7 ${call.clientid} \u00B7 ${call.tool} \u00B7 ${call.origin} \u00B7 ${call.ok ? \"ran behind the gates\" : `refused${call.code !== undefined ? ` (${call.code})` : \"\"}`}`;\n callsbox.append(line);\n }\n if (mcp.calls.length === 0) {\n const empty = document.createElement(\"p\");\n empty.textContent = \"No tool call yet; every call records the client, tool and outcome without payloads.\";\n callsbox.append(empty);\n }\n agentprotocolroot.append(callsbox);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["node", "node", "next", "node", "record", "interrupted", "body", "frames", "actions", "term", "options", "noteinput", "request"]
7
7
  }