@qaick/runner 0.2.0-alpha.5 → 0.2.0-alpha.7
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
|
"name": "@qaick/runner",
|
|
3
3
|
"description": "Reusable QAick Runner module and standalone execution application.",
|
|
4
|
-
"version": "0.2.0-alpha.
|
|
4
|
+
"version": "0.2.0-alpha.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": ["package-dist", "README.md"],
|
|
7
7
|
"main": "./package-dist/src/runner/RunnerModule.js",
|
|
@@ -216,13 +216,13 @@ function RunnerApp({ client, onExit }) {
|
|
|
216
216
|
return undefined; const timer = window.setInterval(() => setClock(Date.now()), 250); return () => window.clearInterval(timer); }, [runState]);
|
|
217
217
|
useEffect(() => { const navigateIssue = (event) => { const target = event.target; const issue = target.closest('.validation-issue'); const stepId = issue?.dataset.stepId; const eventRow = target.closest('.event-row'); const index = stepId ? displaySteps.findIndex(step => step.id === stepId || step.id.endsWith(`.${stepId}`)) : eventRow ? displaySteps.findIndex(step => eventRow.textContent?.includes(step.name)) : -1; if (index >= 0)
|
|
218
218
|
setSelectedStep(index); }; document.addEventListener('click', navigateIssue); return () => document.removeEventListener('click', navigateIssue); }, [displaySteps]);
|
|
219
|
-
return _jsxs("div", { className: "runner-shell", children: [_jsxs("header", { className: "runner-header", children: [_jsxs("div", { className: "runner-brand", children: [_jsx("span", { className: "runner-brand-mark", children: "QAICK" }), _jsx("span", { className: "runner-brand-product", children: "Runner" }), _jsx("span", { className: "alpha-label", children: "Alpha
|
|
219
|
+
return _jsxs("div", { className: "runner-shell", children: [_jsxs("header", { className: "runner-header", children: [_jsxs("div", { className: "runner-brand", children: [_jsx("span", { className: "runner-brand-mark", children: "QAICK" }), _jsx("span", { className: "runner-brand-product", children: "Runner" }), _jsx("span", { className: "alpha-label", children: "Alpha 7" }), onExit && _jsx("button", { className: "about-button", onClick: onExit, children: "Studio" })] }), _jsx("span", { className: "header-spacer" }), _jsx("a", { className: "demo-entry", href: "?demo", children: "View demo" }), _jsx("button", { className: "about-button", onClick: () => setShowAbout(true), children: "About" }), _jsxs("label", { className: "theme-picker", children: ["Theme", _jsxs("select", { value: theme, onChange: event => setTheme(event.target.value), children: [_jsx("option", { value: "light", children: "Light" }), _jsx("option", { value: "dark", children: "Dark" })] })] }), _jsxs("span", { className: `engine-status ${runState === 'failed' ? 'engine-error' : ''}`, children: [_jsx("i", {}), " ", executionMode === 'shared' ? 'Shared Executor' : 'Reference Executor'] })] }), _jsxs("main", { className: "runner-main", children: [_jsxs("nav", { className: "runner-nav", children: [_jsx("p", { className: "nav-label", children: "Workspace" }), _jsx(NavItem, { active: true, icon: "\u25C8", text: "Execution Package" }), _jsx(NavItem, { icon: "\u25A1", text: "Projects" }), _jsx(NavItem, { icon: "\u2318", text: "Flows" }), _jsx(NavItem, { icon: "\u21B6", text: "Run History" }), _jsxs("div", { className: "package-card", children: [_jsx("small", { children: "Loaded package" }), _jsxs("strong", { children: [executionPackage.packageId, ".qaick.json"] }), _jsxs("small", { children: ["Schema ", executionPackage.schemaVersion, " \u00B7 ", executionPackage.definitions.length, " definitions"] })] })] }), _jsxs("section", { className: "runner-workspace", children: [_jsx("div", { className: "eyebrow", children: "EXECUTION PACKAGE" }), _jsx("h1", { children: executionPackage.target.name }), _jsxs("p", { className: "description", children: ["Execute the selected QAick ", executionPackage.target.kind === 'project' ? 'Project' : 'Flow', " and capture structured evidence."] }), _jsxs("div", { className: "run-controls", children: [_jsxs("label", { children: ["Target", _jsx("select", { value: executionPackage.packageId, onChange: event => { const next = packageCatalog.get(event.target.value); setExecutionPackage(next); setBreakpoints(new Set()); breakpointsRef.current = new Set(); setStopAfterStepId(undefined); setLoadError(undefined); setLoadIssues([]); setRuntimeValues(Object.fromEntries((next.runtimeRequirements ?? []).map(name => [name, '']))); setStepStates((next.target.kind === 'project' ? next.flows?.flatMap(flow => flattenDisplaySteps(flow.steps)) ?? [] : flattenDisplaySteps(next.steps)).map(() => 'pending')); setLoopProgress(loopProgressFor(next.target.kind === 'project' ? next.flows?.flatMap(flow => flow.steps) ?? [] : next.steps)); setSelectedStep(0); setResult(undefined); setEvents([]); setRunState('ready'); }, children: packageCatalog.targets().map(item => _jsx("option", { value: item.packageId, children: item.target.name }, item.packageId)) })] }), _jsxs("label", { children: ["Environment", _jsxs("select", { value: environment, onChange: event => setEnvironment(event.target.value), children: [_jsx("option", { children: "test" }), _jsx("option", { children: "local" }), _jsx("option", { children: "staging" })] })] }), _jsxs("label", { children: ["Timeout", _jsxs("select", { value: timeoutMs, onChange: event => setTimeoutMs(event.target.value), children: [_jsx("option", { value: "none", children: "None" }), _jsx("option", { value: "1000", children: "1 second" }), _jsx("option", { value: "3000", children: "3 seconds" }), _jsx("option", { value: "10000", children: "10 seconds" })] })] }), _jsxs("label", { children: ["Run configuration", _jsxs("select", { defaultValue: "Default", children: [_jsx("option", { children: "Default" }), _jsx("option", { children: "Debug" })] })] }), _jsxs("label", { className: "file-button", children: ["Load package", _jsx("input", { type: "file", accept: "application/json,.json", onChange: event => void loadPackage(event.target.files?.[0]) })] }), _jsx("button", { className: "button", onClick: () => setEditingInputs(value => !value), children: editingInputs ? 'Done inputs' : 'Edit inputs' }), _jsx("button", { className: "button primary", onClick: () => void run(), disabled: runState === 'preflighting' || runState === 'running', children: "\u25B6\u00A0 Run" }), _jsx("button", { className: "button dry-run", onClick: () => void run(true), disabled: runState === "preflighting" || runState === "running", children: "\u25CE\u00A0 Pre-run validation" }), _jsx("button", { className: "button stop", onClick: () => void stop(), disabled: runState !== 'preflighting' && runState !== 'running', children: "\u25A0\u00A0 Stop" }), _jsx("button", { className: "button", onClick: () => void pause(), disabled: controlState !== 'running', children: "\u2161\u00A0 Pause" }), _jsx("button", { className: `button ${controlState === 'paused' ? 'resume-highlight' : ''}`, onClick: () => void resume(), disabled: controlState !== 'paused', children: "\u25B6\u00A0 Resume" }), _jsx("button", { className: "button", onClick: () => void stepExecution(), disabled: controlState !== 'paused', children: "\u21A6\u00A0 Step" }), breakpoints.size > 0 && _jsxs("span", { className: "debug-session-badge", children: [breakpoints.size, " breakpoint", breakpoints.size === 1 ? "" : "s", " armed"] })] }), viewingHistoryEntry && _jsxs("div", { className: "history-view-banner", children: ["Viewing stored results \u00B7 ", viewingHistoryEntry] }), loadError && _jsx("p", { className: "load-error", children: loadError }), loadIssues.length > 0 && _jsx(PreRunValidation, { issues: loadIssues, title: "Artifact validation" }), result?.issues !== undefined && _jsx(PreRunValidation, { issues: result.issues }), result?.warnings !== undefined && result.warnings.length > 0 && _jsx(PreRunValidation, { issues: result.warnings, title: "Browser execution warnings" }), editingInputs && _jsxs("section", { className: "inputs-panel panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Invocation Inputs" }), _jsx("span", { className: "panel-spacer" }), _jsx("span", { className: "input-hint", children: "Values are sent with the next run" })] }), _jsxs("div", { className: "input-grid", children: [_jsx(InputField, { label: "customerId", value: String(inputs.customerId ?? ''), onChange: value => setInputs(previous => ({ ...previous, customerId: value })) }), _jsx(InputField, { label: "orderId", value: String(inputs.orderId ?? ''), onChange: value => setInputs(previous => ({ ...previous, orderId: value })) }), _jsx(InputField, { label: "amount", value: String(inputs.amount ?? ''), onChange: value => setInputs(previous => ({ ...previous, amount: value })) }), (executionPackage.requiredInputs ?? []).filter(name => !['customerId', 'orderId', 'amount'].includes(name)).map(name => _jsx(InputField, { label: name, value: String(inputs[name] ?? ''), onChange: value => setInputs(previous => ({ ...previous, [name]: value })) }, name)), (executionPackage.runtimeRequirements ?? []).map(name => _jsx(InputField, { label: `Runtime · ${name}`, value: runtimeValues[name] ?? '', onChange: value => setRuntimeValues(previous => ({ ...previous, [name]: value })) }, name))] })] }), _jsxs("section", { className: "panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Live Execution" }), _jsx("span", { className: "panel-spacer" }), _jsxs("span", { className: "execution-menu-label", children: ["Right-click a row to manage its breakpoint \u00B7 Selected: ", displaySteps[selectedStep]?.name ?? 'None'] }), _jsxs("span", { className: runState === 'running' ? 'running' : runState === 'failed' ? 'stopped' : 'run-status', children: ["\u25CF ", statusLabel] })] }), hasNestedSteps && _jsxs("div", { className: "hierarchy-hint", children: [_jsx("strong", { children: "Nested execution" }), _jsx("span", { children: "Use \u2212 / + to collapse or expand nested Operations, Control Blocks, and loops." }), _jsx("button", { className: "hierarchy-action", onClick: () => setAllCollapsed(true), children: "Collapse all" }), _jsx("button", { className: "hierarchy-action", onClick: () => setAllCollapsed(false), children: "Expand all" })] }), _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "#" }), _jsx("th", { children: "Step hierarchy" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Start time" }), _jsx("th", { children: "Duration" })] }) }), _jsx("tbody", { children: displaySteps.map((step, index) => { const progress = step.loopTotal ? loopProgress[step.id] ?? { current: 0, total: step.loopTotal } : undefined; const percent = progress ? Math.round(progress.current / progress.total * 100) : 0; const isLoop = Boolean(step.loopTotal); const displayState = displayResults[index]?.state ?? stepStates[index] ?? 'pending'; const isLoopContent = Boolean(step.loopId); const isLoopEnd = isLoopContent && displaySteps[index + 1]?.loopId !== step.loopId; const elapsed = step.loopId && loopStartedAt[step.loopId] ? formatElapsed(clock - loopStartedAt[step.loopId]) : undefined; return _jsxs("tr", { className: `${selectedStep === index ? 'selected ' : ''}${isLoop ? 'loop-row ' : ''}${isLoopContent ? 'loop-content ' : ''}${isLoopEnd ? 'loop-end ' : ''}${step.depth > 0 ? 'nested-row' : 'parent-row'}`, tabIndex: 0, onKeyDown: event => { if (event.key === "ArrowDown") {
|
|
220
220
|
event.preventDefault();
|
|
221
221
|
setSelectedStep(Math.min(displaySteps.length - 1, index + 1));
|
|
222
222
|
} if (event.key === "ArrowUp") {
|
|
223
223
|
event.preventDefault();
|
|
224
224
|
setSelectedStep(Math.max(0, index - 1));
|
|
225
|
-
} }, onClick: () => setSelectedStep(index), onContextMenu: event => { event.preventDefault(); setSelectedStep(index); setContextMenu({ x: event.clientX, y: event.clientY, stepId: step.id }); }, children: [_jsx("td", { children: index + 1 }), _jsxs("td", { children: [_jsx("span", { className: `step-icon ${isLoop ? 'loop-icon' : displayState}`, children: isLoop ? '↻' : displayState === 'finished' ? '✓' : displayState === 'waiting' ? '◷' : displayState === 'skipped' ? '–' : '' }), _jsxs("span", { className: "hierarchy-name", style: { paddingLeft: `${step.depth * 18}px` }, children: [step.depth > 0 && _jsx("span", { className: "branch-marker", children: "\u2514" }), step.hasChildren && _jsx("button", { className: "collapse-toggle", "aria-label": `${collapsedSteps.has(step.id) ? 'Expand' : 'Collapse'} ${step.name}`, onClick: event => { event.stopPropagation(); toggleStep(step.id); }, children: collapsedSteps.has(step.id) ? '+' : '−' }), _jsx("span", { children: step.name }), breakpoints.has(step.id) && _jsx("small", { className: "breakpoint-marker", "aria-label": "Breakpoint armed", title: "Breakpoint armed", children: "STOP" }), isLoop && _jsx("small", { className: "kind-label loop-label", children: "LOOP" }), step.depth > 0 ? _jsx("small", { className: "kind-label nested-label", children: "NESTED STEP" }) : !isLoop && _jsx("small", { className: "kind-label", children: step.kind.toUpperCase() })] }), selectedStep === index && _jsx("small", { className: "selected-label", children: "SELECTED" })] }), _jsxs("td", { children: [progress && _jsxs("div", { className: "loop-progress", children: [_jsxs("strong", { children: ["REPEAT LOOP \u00B7 ITERATION ", progress.current, " OF ", progress.total] }), _jsx("span", { className: "loop-bar", children: _jsx("i", { style: { width: `${percent}%` } }) }), _jsx("small", { children: elapsed ? `Elapsed ${elapsed}` : 'Waiting to start' })] }), _jsx("span", { className: `status ${displayState}`, children: isLoop ? 'LOOP' : displayState.toUpperCase() })] }), _jsx("td", { children: displayResults[index] ? new Date(result?.finishedAt ?? '').toLocaleTimeString() : '—' }), _jsx("td", { children: displayResults[index] ? `${displayResults[index].durationMs} ms` : '—' })] }, `${step.id}-${index}`); }) })] }), contextMenu && _jsxs("div", { className: "runner-context-menu", style: { left: contextMenu.x, top: contextMenu.y }, onClick: event => event.stopPropagation(), onContextMenu: event => event.preventDefault(), children: [_jsx("strong", { children: "Breakpoint" }), breakpoints.has(contextMenu.stepId) ? _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Remove breakpoint" }) : _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Add breakpoint" })] })] }), _jsxs("section", { className: "panel event-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Event Log" }), _jsx("span", { className: "panel-spacer" }), _jsx("input", { className: "event-search", "aria-label": "Search event log", placeholder: "Search events", value: eventSearch, onChange: event => setEventSearch(event.target.value) }), _jsxs("select", { className: "event-filter", value: eventFilter, onChange: event => setEventFilter(event.target.value), children: [_jsx("option", { value: "all", children: "All events" }), _jsx("option", { value: "steps", children: "Step events" }), _jsx("option", { value: "parallel", children: "Parallel groups" }), _jsx("option", { value: "lifecycle", children: "Lifecycle" }), _jsx("option", { value: "failures", children: "Failures" })] })] }), _jsx("table", { children: _jsx("tbody", { children: visibleEvents.map(event => _jsxs("tr", { className: "event-row", children: [_jsx("td", { children: new Date(event.timestamp).toLocaleTimeString() }), _jsx("td", { children: event.state.toUpperCase() }), _jsx("td", { children: _jsx("code", { children: event.type.toUpperCase() }) }), _jsxs("td", { children: [event.message, event.parallel && _jsxs("small", { className: "parallel-event", children: [" \u00B7 Parallel ", event.parallel.completed, "/", event.parallel.total, " (", event.parallel.join, ")"] })] })] }, event.sequence)) }) }), events.length > 0 && visibleEvents.length === 0 && _jsx("p", { className: "empty-state", children: "No events match the current filter." })] }), _jsx(HistoryPanel, { entries: runHistory, onReload: reloadHistoryEntry, retention: historyRetention, onRetentionChange: changeHistoryRetention, onClear: clearHistory, onDelete: deleteHistoryEntry, onExport: exportResult })] }), _jsxs("aside", { className: "inspector", children: [_jsx("h2", { children: "Selected execution" }), _jsx("p", { className: "selected-detail-name", children: _jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }) }), _jsxs("p", { className: "run-id", children: ["Run ID: ", requestId ?? 'No run started'] }), _jsx(InspectorSection, { title: "Artifact summary", children: _jsx(KeyValues, { values: ["Target", executionPackage.target.name, "Type", executionPackage.target.kind, "Package", executionPackage.packageId, "Artifact schema", String(executionPackage.schemaVersion), "Definitions", String(executionPackage.definitions.length), "Required inputs", (executionPackage.requiredInputs ?? []).join(", ") || "None", "Runtime values", (executionPackage.runtimeRequirements ?? []).join(", ") || "None"] }) }), _jsx(InspectorSection, { title: "Run outcome", children: _jsxs("div", { className: "notice", children: [_jsx("strong", { children: result?.terminalReason?.toUpperCase() ?? 'NOT STARTED' }), _jsx("br", {}), result ? `${result.environment} · ${result.state}` : 'Run the package to inspect its terminal outcome.'] }) }), _jsx(InspectorSection, { title: "Selected step inputs", children: _jsx(KeyValues, { values: Object.entries(displayResults[selectedStep]?.inputs ?? inputs).flatMap(([key, value]) => [key, String(value)]) }) }), _jsx(InspectorSection, { title: "Selected step outputs", children: _jsx(KeyValues, { values: displayResults[selectedStep]?.outputs ? Object.entries(displayResults[selectedStep]?.outputs ?? {}).flatMap(([key, value]) => [key, String(value)]) : ['—', 'Available after execution'] }) }), (result?.error || displayResults[selectedStep]?.error) && _jsx(InspectorSection, { title: "Error", children: _jsxs("div", { className: "error-notice", children: [_jsx("strong", { children: displayResults[selectedStep]?.error?.code ?? result?.error?.code }), _jsx("br", {}), displayResults[selectedStep]?.error?.message ?? result?.error?.message] }) }), result?.issues !== undefined && _jsx(InspectorSection, { title: "Pre-run validation", children: _jsx(PreRunValidation, { issues: result.issues }) }), _jsx(InspectorSection, { title: "Invocation path", children: _jsx("div", { className: "notice", children: displayResults[selectedStep]?.invocationPath?.join(" › ") ?? "No invocation path available." }) }), _jsx(InspectorSection, { title: "Iteration history", children: _jsx(IterationHistory, { result: displayResults[selectedStep] }) }), _jsx(InspectorSection, { title: "Execution timing", children: _jsxs("div", { className: "timing-details", children: [_jsxs("span", { children: ["Wall ", result?.executionTiming?.wallDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Active ", result?.executionTiming?.activeDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Paused ", result?.executionTiming?.pausedDurationMs ?? "—", " ms"] })] }) }), _jsx(InspectorSection, { title: "Selected step attempts", children: _jsx("div", { className: "attempt-history", children: displayResults[selectedStep]?.attempts?.map(attempt => _jsxs("div", { className: "iteration-entry", children: [_jsxs("strong", { children: ["Attempt ", attempt.attempt] }), _jsxs("span", { children: [attempt.kind.toUpperCase(), " \u00B7 ", attempt.state.toUpperCase(), " \u00B7 ", attempt.durationMs, " ms"] })] }, `${attempt.attempt}-${attempt.kind}`)) ?? _jsx("div", { className: "notice", children: "No retry attempts recorded." }) }) }), _jsxs(InspectorSection, { title: "Selected step", children: [_jsxs("div", { className: "notice", children: [_jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }), _jsx("br", {}), displayResults[selectedStep] ? displayResults[selectedStep].error ? 'This step failed. See the error details above.' : `Completed in ${displayResults[selectedStep].durationMs} ms.` : 'Run the package to inspect execution details.', _jsxs("div", { className: "inspector-actions", children: [_jsx("button", { className: "button", onClick: () => void retrySelected(), disabled: !displayResults[selectedStep] || (!displayResults[selectedStep]?.error && runState !== "completed"), children: "Retry Action" }), _jsx("button", { className: `button ${stopAfterStepId === displaySteps[selectedStep]?.id ? "active" : ""}`, onClick: () => displaySteps[selectedStep] && toggleStopAfter(displaySteps[selectedStep].id), disabled: !displaySteps[selectedStep], children: "Stop After" }), _jsx("button", { className: "button", onClick: () => void runFromSelected(), disabled: !displayResults[selectedStep] || runState === "running", children: "Run From Here" })] })] }), _jsxs("div", { className: "selection-nav", children: [_jsx("button", { className: "button", disabled: selectedStep <= 0, onClick: () => setSelectedStep(index => Math.max(0, index - 1)), children: "\u2039 Previous" }), _jsx("span", { children: displaySteps.length ? `${selectedStep + 1} / ${displaySteps.length}` : '0 / 0' }), _jsx("button", { className: "button", disabled: selectedStep >= displaySteps.length - 1, onClick: () => setSelectedStep(index => Math.min(displaySteps.length - 1, index + 1)), children: "Next \u203A" })] })] })] })] }), showAbout && _jsx("div", { className: "about-backdrop", onClick: () => setShowAbout(false), children: _jsxs("section", { className: "about-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "about-title", onClick: event => event.stopPropagation(), children: [_jsx("button", { className: "about-close", onClick: () => setShowAbout(false), "aria-label": "Close About", children: "\u00D7" }), _jsx("div", { className: "runner-logo", children: "\u25B6" }), _jsx("h2", { id: "about-title", children: "QAick Runner" }), _jsx("p", { children: "Standalone execution and evidence viewer for QAick packages." }), _jsxs("small", { children: ["Alpha 5 \u00B7 ", RUNNER_BUILD_LABEL, " \u00B7 QAick contract"] }), _jsx("footer", { children: "\u00A9 2006\u20132026 QAick. All rights reserved." })] }) }), _jsx("div", { className: "draft-badge", children: "SHARED EXECUTOR \u00B7 ALPHA 5" })] });
|
|
225
|
+
} }, onClick: () => setSelectedStep(index), onContextMenu: event => { event.preventDefault(); setSelectedStep(index); setContextMenu({ x: event.clientX, y: event.clientY, stepId: step.id }); }, children: [_jsx("td", { children: index + 1 }), _jsxs("td", { children: [_jsx("span", { className: `step-icon ${isLoop ? 'loop-icon' : displayState}`, children: isLoop ? '↻' : displayState === 'finished' ? '✓' : displayState === 'waiting' ? '◷' : displayState === 'skipped' ? '–' : '' }), _jsxs("span", { className: "hierarchy-name", style: { paddingLeft: `${step.depth * 18}px` }, children: [step.depth > 0 && _jsx("span", { className: "branch-marker", children: "\u2514" }), step.hasChildren && _jsx("button", { className: "collapse-toggle", "aria-label": `${collapsedSteps.has(step.id) ? 'Expand' : 'Collapse'} ${step.name}`, onClick: event => { event.stopPropagation(); toggleStep(step.id); }, children: collapsedSteps.has(step.id) ? '+' : '−' }), _jsx("span", { children: step.name }), breakpoints.has(step.id) && _jsx("small", { className: "breakpoint-marker", "aria-label": "Breakpoint armed", title: "Breakpoint armed", children: "STOP" }), isLoop && _jsx("small", { className: "kind-label loop-label", children: "LOOP" }), step.depth > 0 ? _jsx("small", { className: "kind-label nested-label", children: "NESTED STEP" }) : !isLoop && _jsx("small", { className: "kind-label", children: step.kind.toUpperCase() })] }), selectedStep === index && _jsx("small", { className: "selected-label", children: "SELECTED" })] }), _jsxs("td", { children: [progress && _jsxs("div", { className: "loop-progress", children: [_jsxs("strong", { children: ["REPEAT LOOP \u00B7 ITERATION ", progress.current, " OF ", progress.total] }), _jsx("span", { className: "loop-bar", children: _jsx("i", { style: { width: `${percent}%` } }) }), _jsx("small", { children: elapsed ? `Elapsed ${elapsed}` : 'Waiting to start' })] }), _jsx("span", { className: `status ${displayState}`, children: isLoop ? 'LOOP' : displayState.toUpperCase() })] }), _jsx("td", { children: displayResults[index] ? new Date(result?.finishedAt ?? '').toLocaleTimeString() : '—' }), _jsx("td", { children: displayResults[index] ? `${displayResults[index].durationMs} ms` : '—' })] }, `${step.id}-${index}`); }) })] }), contextMenu && _jsxs("div", { className: "runner-context-menu", style: { left: contextMenu.x, top: contextMenu.y }, onClick: event => event.stopPropagation(), onContextMenu: event => event.preventDefault(), children: [_jsx("strong", { children: "Breakpoint" }), breakpoints.has(contextMenu.stepId) ? _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Remove breakpoint" }) : _jsx("button", { onClick: () => { toggleBreakpoint(contextMenu.stepId); setContextMenu(undefined); }, children: "Add breakpoint" })] })] }), _jsxs("section", { className: "panel event-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Event Log" }), _jsx("span", { className: "panel-spacer" }), _jsx("input", { className: "event-search", "aria-label": "Search event log", placeholder: "Search events", value: eventSearch, onChange: event => setEventSearch(event.target.value) }), _jsxs("select", { className: "event-filter", value: eventFilter, onChange: event => setEventFilter(event.target.value), children: [_jsx("option", { value: "all", children: "All events" }), _jsx("option", { value: "steps", children: "Step events" }), _jsx("option", { value: "parallel", children: "Parallel groups" }), _jsx("option", { value: "lifecycle", children: "Lifecycle" }), _jsx("option", { value: "failures", children: "Failures" })] })] }), _jsx("table", { children: _jsx("tbody", { children: visibleEvents.map(event => _jsxs("tr", { className: "event-row", children: [_jsx("td", { children: new Date(event.timestamp).toLocaleTimeString() }), _jsx("td", { children: event.state.toUpperCase() }), _jsx("td", { children: _jsx("code", { children: event.type.toUpperCase() }) }), _jsxs("td", { children: [event.message, event.parallel && _jsxs("small", { className: "parallel-event", children: [" \u00B7 Parallel ", event.parallel.completed, "/", event.parallel.total, " (", event.parallel.join, ")"] })] })] }, event.sequence)) }) }), events.length > 0 && visibleEvents.length === 0 && _jsx("p", { className: "empty-state", children: "No events match the current filter." })] }), _jsx(HistoryPanel, { entries: runHistory, onReload: reloadHistoryEntry, retention: historyRetention, onRetentionChange: changeHistoryRetention, onClear: clearHistory, onDelete: deleteHistoryEntry, onExport: exportResult })] }), _jsxs("aside", { className: "inspector", children: [_jsx("h2", { children: "Selected execution" }), _jsx("p", { className: "selected-detail-name", children: _jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }) }), _jsxs("p", { className: "run-id", children: ["Run ID: ", requestId ?? 'No run started'] }), _jsx(InspectorSection, { title: "Artifact summary", children: _jsx(KeyValues, { values: ["Target", executionPackage.target.name, "Type", executionPackage.target.kind, "Package", executionPackage.packageId, "Artifact schema", String(executionPackage.schemaVersion), "Definitions", String(executionPackage.definitions.length), "Required inputs", (executionPackage.requiredInputs ?? []).join(", ") || "None", "Runtime values", (executionPackage.runtimeRequirements ?? []).join(", ") || "None"] }) }), _jsx(InspectorSection, { title: "Run outcome", children: _jsxs("div", { className: "notice", children: [_jsx("strong", { children: result?.terminalReason?.toUpperCase() ?? 'NOT STARTED' }), _jsx("br", {}), result ? `${result.environment} · ${result.state}` : 'Run the package to inspect its terminal outcome.'] }) }), _jsx(InspectorSection, { title: "Selected step inputs", children: _jsx(KeyValues, { values: Object.entries(displayResults[selectedStep]?.inputs ?? inputs).flatMap(([key, value]) => [key, String(value)]) }) }), _jsx(InspectorSection, { title: "Selected step outputs", children: _jsx(KeyValues, { values: displayResults[selectedStep]?.outputs ? Object.entries(displayResults[selectedStep]?.outputs ?? {}).flatMap(([key, value]) => [key, String(value)]) : ['—', 'Available after execution'] }) }), (result?.error || displayResults[selectedStep]?.error) && _jsx(InspectorSection, { title: "Error", children: _jsxs("div", { className: "error-notice", children: [_jsx("strong", { children: displayResults[selectedStep]?.error?.code ?? result?.error?.code }), _jsx("br", {}), displayResults[selectedStep]?.error?.message ?? result?.error?.message] }) }), result?.issues !== undefined && _jsx(InspectorSection, { title: "Pre-run validation", children: _jsx(PreRunValidation, { issues: result.issues }) }), _jsx(InspectorSection, { title: "Invocation path", children: _jsx("div", { className: "notice", children: displayResults[selectedStep]?.invocationPath?.join(" › ") ?? "No invocation path available." }) }), _jsx(InspectorSection, { title: "Iteration history", children: _jsx(IterationHistory, { result: displayResults[selectedStep] }) }), _jsx(InspectorSection, { title: "Execution timing", children: _jsxs("div", { className: "timing-details", children: [_jsxs("span", { children: ["Wall ", result?.executionTiming?.wallDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Active ", result?.executionTiming?.activeDurationMs ?? "—", " ms"] }), _jsxs("span", { children: ["Paused ", result?.executionTiming?.pausedDurationMs ?? "—", " ms"] })] }) }), _jsx(InspectorSection, { title: "Selected step attempts", children: _jsx("div", { className: "attempt-history", children: displayResults[selectedStep]?.attempts?.map(attempt => _jsxs("div", { className: "iteration-entry", children: [_jsxs("strong", { children: ["Attempt ", attempt.attempt] }), _jsxs("span", { children: [attempt.kind.toUpperCase(), " \u00B7 ", attempt.state.toUpperCase(), " \u00B7 ", attempt.durationMs, " ms"] })] }, `${attempt.attempt}-${attempt.kind}`)) ?? _jsx("div", { className: "notice", children: "No retry attempts recorded." }) }) }), _jsxs(InspectorSection, { title: "Selected step", children: [_jsxs("div", { className: "notice", children: [_jsx("strong", { children: displaySteps[selectedStep]?.name ?? 'No step selected' }), _jsx("br", {}), displayResults[selectedStep] ? displayResults[selectedStep].error ? 'This step failed. See the error details above.' : `Completed in ${displayResults[selectedStep].durationMs} ms.` : 'Run the package to inspect execution details.', _jsxs("div", { className: "inspector-actions", children: [_jsx("button", { className: "button", onClick: () => void retrySelected(), disabled: !displayResults[selectedStep] || (!displayResults[selectedStep]?.error && runState !== "completed"), children: "Retry Action" }), _jsx("button", { className: `button ${stopAfterStepId === displaySteps[selectedStep]?.id ? "active" : ""}`, onClick: () => displaySteps[selectedStep] && toggleStopAfter(displaySteps[selectedStep].id), disabled: !displaySteps[selectedStep], children: "Stop After" }), _jsx("button", { className: "button", onClick: () => void runFromSelected(), disabled: !displayResults[selectedStep] || runState === "running", children: "Run From Here" })] })] }), _jsxs("div", { className: "selection-nav", children: [_jsx("button", { className: "button", disabled: selectedStep <= 0, onClick: () => setSelectedStep(index => Math.max(0, index - 1)), children: "\u2039 Previous" }), _jsx("span", { children: displaySteps.length ? `${selectedStep + 1} / ${displaySteps.length}` : '0 / 0' }), _jsx("button", { className: "button", disabled: selectedStep >= displaySteps.length - 1, onClick: () => setSelectedStep(index => Math.min(displaySteps.length - 1, index + 1)), children: "Next \u203A" })] })] })] })] }), showAbout && _jsx("div", { className: "about-backdrop", onClick: () => setShowAbout(false), children: _jsxs("section", { className: "about-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "about-title", onClick: event => event.stopPropagation(), children: [_jsx("button", { className: "about-close", onClick: () => setShowAbout(false), "aria-label": "Close About", children: "\u00D7" }), _jsx("div", { className: "runner-logo", children: "\u25B6" }), _jsx("h2", { id: "about-title", children: "QAick Runner" }), _jsx("p", { children: "Standalone execution and evidence viewer for QAick packages." }), _jsxs("small", { children: ["Alpha 7 \u00B7 ", RUNNER_BUILD_LABEL, " \u00B7 QAick contract"] }), _jsx("footer", { children: "\u00A9 2006\u20132026 QAick. All rights reserved." })] }) }), _jsx("div", { className: "draft-badge", children: "SHARED EXECUTOR \u00B7 ALPHA 7" })] });
|
|
226
226
|
}
|
|
227
227
|
function NavItem({ icon, text, active = false }) { const scrollTarget = text === 'Run History' ? '.history-panel' : text === 'Flows' ? '.runner-workspace table' : '.runner-workspace'; return _jsxs("a", { className: `nav-item ${active ? 'active' : ''}`, href: `#${text.toLowerCase().replaceAll(' ', '-')}`, onClick: event => { event.preventDefault(); document.querySelector(scrollTarget)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, children: [_jsx("span", { children: icon }), text] }); }
|
|
228
228
|
function HistoryPanel({ entries, retention, onRetentionChange, onClear, onDelete, onExport, onReload }) { return _jsxs("section", { className: "panel history-panel", children: [_jsxs("div", { className: "panel-heading", children: [_jsx("h2", { children: "Run History" }), _jsx("span", { className: "panel-spacer" }), _jsxs("label", { className: "history-retention", children: ["Keep", _jsxs("select", { "aria-label": "Run history retention", value: retention, onChange: event => onRetentionChange(Number(event.target.value)), children: [_jsx("option", { value: "10", children: "10 runs" }), _jsx("option", { value: "20", children: "20 runs" }), _jsx("option", { value: "50", children: "50 runs" }), _jsx("option", { value: "100", children: "100 runs" })] })] }), _jsx("button", { className: "button", onClick: onClear, disabled: !entries.length, children: "Clear history" })] }), entries.length ? _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Target" }), _jsx("th", { children: "Started" }), _jsx("th", { children: "State" }), _jsx("th", { children: "Duration" }), _jsx("th", { children: "Result" })] }) }), _jsx("tbody", { children: entries.map(entry => _jsxs("tr", { children: [_jsxs("td", { children: [entry.target, _jsxs("small", { className: "history-meta", children: [entry.result.provenance ? 'Run From Here' : entry.result.steps.some(step => step.attempts?.some(attempt => attempt.kind === 'interactive')) ? 'Interactive retry' : 'Normal run', " \u00B7 ", entry.packageId ?? 'legacy result', " \u00B7 schema ", entry.artifactSchemaVersion ?? '—', _jsx("br", {}), "hash ", entry.result.artifactHash ?? 'legacy result'] })] }), _jsx("td", { children: new Date(entry.startedAt).toLocaleString() }), _jsx("td", { children: _jsx("span", { className: `status ${entry.state}`, children: entry.state.toUpperCase() }) }), _jsxs("td", { children: [entry.durationMs, " ms"] }), _jsxs("td", { children: [_jsx("button", { className: "button", onClick: () => onReload(entry), children: "View results" }), _jsx("button", { className: "button", onClick: () => onExport(entry.result, entry.packageId, entry.artifactSchemaVersion), children: "Export JSON" }), _jsx("button", { className: "button history-delete", onClick: () => onDelete(entry.requestId), children: "Delete" })] })] }, entry.requestId)) })] }) : _jsx("p", { className: "empty-state", children: "Completed and failed runs will be kept here in this browser." })] }); }
|
package/package-dist/styles.css
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
:root { font-family: Inter, ui-sans-serif, system-ui, sans-serif; color: #182234; background: #f7f9fc; font-size: 13px; color-scheme: light; }
|
|
2
2
|
:root[data-theme='dark'] { color: #e6edf7; background: #111827; color-scheme: dark; }
|
|
3
3
|
* { box-sizing: border-box; } body { margin: 0; min-width: 1120px; } button, select { font: inherit; }
|
|
4
|
-
.runner-shell { min-height: 100vh; display: grid; grid-template-rows: 58px 1fr; } .runner-header { display: flex; align-items: center; gap: 18px; padding: 0 12px 0 16px; border-bottom: 1px solid #dfe4ec; background: #fff; font-size: 13px; }
|
|
4
|
+
.runner-shell { height: 100vh; min-height: 100vh; display: grid; grid-template-rows: 58px minmax(0, 1fr); } .runner-header { display: flex; align-items: center; gap: 18px; padding: 0 12px 0 16px; border-bottom: 1px solid #dfe4ec; background: #fff; font-size: 13px; }
|
|
5
5
|
.runner-brand { display: flex; align-items: baseline; gap: 6px; flex: none; } .runner-brand-mark { color: #3569d4; font-size: 13px; font-weight: 700; letter-spacing: .04em; } .runner-brand-product { color: #182234; font-size: 13px; font-weight: 500; } .runner-brand .about-button { height: 25px; margin-left: 6px; padding: 0 9px; border: 0; border-radius: 4px; background: transparent; color: #40516c; font-size: 12px; font-weight: 650; } .runner-brand .about-button:hover { background: #f0f3f8; color: #182234; } .runner-logo { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 8px; color: white; background: #3569d4; font-size: 13px; } .alpha-label { color: #70809a; font-size: 13px; } .header-spacer, .panel-spacer { flex: 1; }
|
|
6
6
|
.engine-status { display: flex; align-items: center; gap: 7px; color: #14804a; font-size: 12px; font-weight: 700; } .engine-status i { width: 8px; height: 8px; border-radius: 50%; background: #19a463; }
|
|
7
7
|
.theme-picker { display: flex; align-items: center; gap: 7px; color: #596a82; font-size: 12px; font-weight: 700; } .theme-picker select { min-width: 82px; height: 30px; padding: 0 8px; border: 1px solid #cdd7e5; border-radius: 6px; background: white; color: #182234; }
|
|
8
|
-
.runner-main { display: grid; grid-template-columns: 218px minmax(560px, 1fr) 350px; min-height: 0; } .runner-nav, .inspector { background: #fff; } .runner-nav { padding: 18px 12px; border-right: 1px solid #dfe4ec; }
|
|
8
|
+
.runner-main { display: grid; grid-template-columns: 218px minmax(560px, 1fr) 350px; min-height: 0; overflow: hidden; } .runner-nav, .inspector { min-height: 0; overflow-y: auto; background: #fff; } .runner-nav { padding: 18px 12px; border-right: 1px solid #dfe4ec; }
|
|
9
9
|
.nav-label, .eyebrow { color: #8794a8; font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; } .nav-label { margin: 4px 12px 10px; }
|
|
10
10
|
.nav-item { display: flex; align-items: center; gap: 10px; padding: 11px 12px; border-radius: 7px; color: #40516c; font-size: 14px; text-decoration: none; cursor: pointer; } .nav-item span { width: 20px; text-align: center; } .nav-item.active { color: #2458c4; background: #e9f0ff; font-weight: 700; }
|
|
11
11
|
.package-card { margin: 24px 8px 0; padding: 12px; border: 1px solid #dce4f0; border-radius: 8px; background: #f8faff; } .package-card small { display: block; color: #77869b; } .package-card strong { display: block; margin: 5px 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
12
|
-
.runner-workspace { padding: 26px 30px; background: #f7f9fc; } .eyebrow { color: #687a95; } h1 { margin: 5px 0 4px; font-size: 25px; letter-spacing: -.02em; } .description { margin: 0; color: #66758c; }
|
|
12
|
+
.runner-workspace { min-height: 0; overflow-y: auto; padding: 26px 30px; background: #f7f9fc; } .eyebrow { color: #687a95; } h1 { margin: 5px 0 4px; font-size: 25px; letter-spacing: -.02em; } .description { margin: 0; color: #66758c; }
|
|
13
13
|
.run-controls { display: flex; align-items: end; flex-wrap: wrap; gap: 10px 14px; margin-top: 25px; } label { display: grid; gap: 6px; color: #596a82; font-size: 12px; font-weight: 700; } select { min-width: 145px; height: 36px; padding: 0 10px; border: 1px solid #cdd7e5; border-radius: 6px; background: white; color: #182234; }
|
|
14
14
|
.button { height: 36px; padding: 0 15px; border: 1px solid #cdd7e5; border-radius: 6px; background: white; color: #334560; font-weight: 700; cursor: pointer; } .button.primary { border-color: #3569d4; background: #3569d4; color: white; } .button.dry-run { border-color: #8a9fc4; color: #315da9; background: #eef3fc; } .button.stop { color: #b33a30; }
|
|
15
15
|
.file-button { position: relative; display: inline-grid; height: 36px; padding: 0 15px; place-items: center; border: 1px solid #cdd7e5; border-radius: 6px; background: white; color: #334560; cursor: pointer; } .file-button input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; } .load-error { margin: 12px 0 -8px; color: #b33a30; font-size: 12px; font-weight: 700; }
|
|
@@ -88,3 +88,161 @@ table { width: 100%; border-collapse: collapse; font-size: 13px; } th { padding:
|
|
|
88
88
|
.breakpoint-marker { display: inline-grid; width: 22px; height: 22px; place-items: center; color: #fff; background: #b93645; clip-path: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%); filter: drop-shadow(0 1px 1px rgba(62, 20, 27, .25)); font-family: Arial, sans-serif; font-size: 4.5px; font-weight: 900; letter-spacing: .06em; line-height: 1; }
|
|
89
89
|
|
|
90
90
|
.button.resume-highlight { border-color: #3569d4; background: #3569d4; color: #fff; box-shadow: 0 0 0 3px rgba(53, 105, 212, .18); }
|
|
91
|
+
|
|
92
|
+
/* Keep Runner aligned with the shared QAICK Studio design tokens. These are
|
|
93
|
+
Runner-scoped names so the integrated stylesheet does not overwrite Studio's
|
|
94
|
+
own variables. Execution statuses retain their semantic colours below. */
|
|
95
|
+
:root {
|
|
96
|
+
--runner-blue: #4f46d8;
|
|
97
|
+
--runner-blue-strong: #3f37b8;
|
|
98
|
+
--runner-blue-soft: #e8eeff;
|
|
99
|
+
--runner-blue-line: #c8d5fa;
|
|
100
|
+
--runner-ink: #182234;
|
|
101
|
+
--runner-ink-2: #34435b;
|
|
102
|
+
--runner-muted: #617089;
|
|
103
|
+
--runner-faint: #7c8aa0;
|
|
104
|
+
--runner-surface: #fff;
|
|
105
|
+
--runner-surface-2: #f7f8fc;
|
|
106
|
+
--runner-surface-3: #edf0f7;
|
|
107
|
+
--runner-pane: #eef0f2;
|
|
108
|
+
--runner-heading: #e1e4e8;
|
|
109
|
+
--runner-divider: #cbd1d8;
|
|
110
|
+
--runner-line: #e5e7eb;
|
|
111
|
+
--runner-line-strong: #cfd5dd;
|
|
112
|
+
--runner-ok: #14804a;
|
|
113
|
+
--runner-ok-soft: #e6f5ec;
|
|
114
|
+
--runner-warn: #92620a;
|
|
115
|
+
--runner-warn-soft: #fdf3e2;
|
|
116
|
+
--runner-fail: #bc3327;
|
|
117
|
+
--runner-fail-soft: #fdecea;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
:root[data-theme='dark'] {
|
|
121
|
+
--runner-blue: #8b9cff;
|
|
122
|
+
--runner-blue-strong: #aab5ff;
|
|
123
|
+
--runner-blue-soft: #252c4b;
|
|
124
|
+
--runner-blue-line: #4a5684;
|
|
125
|
+
--runner-ink: #edf1f8;
|
|
126
|
+
--runner-ink-2: #c8d1e2;
|
|
127
|
+
--runner-muted: #9da9bd;
|
|
128
|
+
--runner-faint: #7d899e;
|
|
129
|
+
--runner-surface: #171b24;
|
|
130
|
+
--runner-surface-2: #1d2230;
|
|
131
|
+
--runner-surface-3: #282f3e;
|
|
132
|
+
--runner-pane: #1b202a;
|
|
133
|
+
--runner-heading: #252c37;
|
|
134
|
+
--runner-divider: #3b4555;
|
|
135
|
+
--runner-line: #303949;
|
|
136
|
+
--runner-line-strong: #465267;
|
|
137
|
+
--runner-ok: #67d39a;
|
|
138
|
+
--runner-ok-soft: #1b382b;
|
|
139
|
+
--runner-warn: #e8bd66;
|
|
140
|
+
--runner-warn-soft: #3a301d;
|
|
141
|
+
--runner-fail: #ff8d83;
|
|
142
|
+
--runner-fail-soft: #402522;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:root,
|
|
146
|
+
:root[data-theme='dark'] {
|
|
147
|
+
color: var(--runner-ink);
|
|
148
|
+
background: var(--runner-surface);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
body { background: var(--runner-surface-2); }
|
|
152
|
+
.runner-header,
|
|
153
|
+
.runner-nav,
|
|
154
|
+
.inspector,
|
|
155
|
+
.panel,
|
|
156
|
+
.button,
|
|
157
|
+
.file-button,
|
|
158
|
+
select,
|
|
159
|
+
.input-field input,
|
|
160
|
+
.about-button,
|
|
161
|
+
.about-dialog,
|
|
162
|
+
.hierarchy-action,
|
|
163
|
+
.runner-context-menu { border-color: var(--runner-line-strong); background: var(--runner-surface); color: var(--runner-ink-2); }
|
|
164
|
+
.runner-header { border-color: var(--runner-divider); }
|
|
165
|
+
.runner-brand-mark,
|
|
166
|
+
.runner-logo,
|
|
167
|
+
.button.primary,
|
|
168
|
+
.button.resume-highlight { background: var(--runner-blue); color: #fff; }
|
|
169
|
+
.runner-brand-mark { background: transparent; color: var(--runner-blue); }
|
|
170
|
+
.runner-brand-product,
|
|
171
|
+
.runner-header strong,
|
|
172
|
+
h1,
|
|
173
|
+
h2,
|
|
174
|
+
h3,
|
|
175
|
+
td,
|
|
176
|
+
.package-card strong,
|
|
177
|
+
.about-dialog h2 { color: var(--runner-ink); }
|
|
178
|
+
.alpha-label,
|
|
179
|
+
.nav-label,
|
|
180
|
+
.eyebrow,
|
|
181
|
+
.package-card small,
|
|
182
|
+
.run-id,
|
|
183
|
+
.input-hint,
|
|
184
|
+
.theme-picker,
|
|
185
|
+
label { color: var(--runner-muted); }
|
|
186
|
+
.runner-workspace { background: var(--runner-surface-2); }
|
|
187
|
+
.runner-nav { border-color: var(--runner-divider); }
|
|
188
|
+
.inspector { border-color: var(--runner-divider); }
|
|
189
|
+
.nav-item { color: var(--runner-muted); }
|
|
190
|
+
.nav-item.active { color: var(--runner-blue-strong); background: var(--runner-blue-soft); }
|
|
191
|
+
.package-card,
|
|
192
|
+
.notice { border-color: var(--runner-line); background: var(--runner-surface-3); color: var(--runner-muted); }
|
|
193
|
+
.button:hover,
|
|
194
|
+
.file-button:hover,
|
|
195
|
+
.about-button:hover { border-color: var(--runner-blue-line); background: var(--runner-blue-soft); }
|
|
196
|
+
.button.primary:hover,
|
|
197
|
+
.button.resume-highlight:hover { border-color: var(--runner-blue-strong); background: var(--runner-blue-strong); }
|
|
198
|
+
.panel-heading,
|
|
199
|
+
.inspector-section { border-color: var(--runner-line); }
|
|
200
|
+
th { color: var(--runner-faint); background: var(--runner-surface-2); }
|
|
201
|
+
td { border-color: var(--runner-line); }
|
|
202
|
+
tr.parent-row td,
|
|
203
|
+
.loop-content td { background: var(--runner-surface); }
|
|
204
|
+
tr.nested-row td { background: var(--runner-surface-3); }
|
|
205
|
+
tr.selected td { background: var(--runner-blue-soft) !important; border-top-color: var(--runner-blue-line); }
|
|
206
|
+
tr.selected td:first-child { border-left-color: var(--runner-blue); }
|
|
207
|
+
tr.selected .hierarchy-name,
|
|
208
|
+
.selected-detail-name,
|
|
209
|
+
code { color: var(--runner-blue-strong); }
|
|
210
|
+
.hierarchy-hint { border-color: var(--runner-blue-line); color: var(--runner-blue-strong); background: var(--runner-blue-soft); }
|
|
211
|
+
.hierarchy-hint span,
|
|
212
|
+
.parallel-details { color: var(--runner-muted); }
|
|
213
|
+
.hierarchy-action,
|
|
214
|
+
.collapse-toggle { border-color: var(--runner-blue-line); color: var(--runner-blue-strong); background: var(--runner-surface); }
|
|
215
|
+
.kind-label { color: var(--runner-muted); background: var(--runner-surface-3); }
|
|
216
|
+
.nested-label,
|
|
217
|
+
.loop-label { color: var(--runner-blue-strong); background: var(--runner-blue-soft); }
|
|
218
|
+
.key-values,
|
|
219
|
+
.iteration-entry,
|
|
220
|
+
.timing-details,
|
|
221
|
+
.branch-path,
|
|
222
|
+
.result-summary { border-color: var(--runner-line); background: var(--runner-surface); }
|
|
223
|
+
.key-values span:nth-child(odd) { color: var(--runner-muted); background: var(--runner-surface-2); }
|
|
224
|
+
.iteration-entry span,
|
|
225
|
+
.iteration-entry small,
|
|
226
|
+
.timing-details,
|
|
227
|
+
.branch-path-row small,
|
|
228
|
+
.result-summary { color: var(--runner-muted); }
|
|
229
|
+
.status.finished,
|
|
230
|
+
.validation-pass { color: var(--runner-ok); background: var(--runner-ok-soft); }
|
|
231
|
+
.status.waiting { color: var(--runner-warn); background: var(--runner-warn-soft); }
|
|
232
|
+
.status.failed,
|
|
233
|
+
.status.cancelled,
|
|
234
|
+
.validation-failed { color: var(--runner-fail); background: var(--runner-fail-soft); }
|
|
235
|
+
.error-notice { border-color: color-mix(in srgb, var(--runner-fail) 35%, var(--runner-surface)); color: var(--runner-fail); background: var(--runner-fail-soft); }
|
|
236
|
+
:root[data-theme='dark'] .runner-header,
|
|
237
|
+
:root[data-theme='dark'] .runner-nav,
|
|
238
|
+
:root[data-theme='dark'] .inspector,
|
|
239
|
+
:root[data-theme='dark'] .panel,
|
|
240
|
+
:root[data-theme='dark'] .button,
|
|
241
|
+
:root[data-theme='dark'] select,
|
|
242
|
+
:root[data-theme='dark'] .input-field input,
|
|
243
|
+
:root[data-theme='dark'] .about-button,
|
|
244
|
+
:root[data-theme='dark'] .about-dialog { background: var(--runner-surface); color: var(--runner-ink); }
|
|
245
|
+
:root[data-theme='dark'] .runner-workspace { background: var(--runner-surface-2); }
|
|
246
|
+
:root[data-theme='dark'] .package-card,
|
|
247
|
+
:root[data-theme='dark'] .notice,
|
|
248
|
+
:root[data-theme='dark'] .kind-label { background: var(--runner-surface-3); color: var(--runner-ink-2); }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qaick/runner",
|
|
3
3
|
"description": "Reusable QAick Runner module and standalone execution application.",
|
|
4
|
-
"version": "0.2.0-alpha.
|
|
4
|
+
"version": "0.2.0-alpha.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": ["package-dist", "README.md"],
|
|
7
7
|
"main": "./package-dist/src/runner/RunnerModule.js",
|