@resolveio/server-lib 22.3.44 → 22.3.46
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.
package/package.json
CHANGED
|
@@ -192,7 +192,7 @@ function buildResolveIORunnerLocalQaScript() {
|
|
|
192
192
|
' done',
|
|
193
193
|
' for pass in 1 2 3; do',
|
|
194
194
|
' for port in "$CLIENT_PORT" "$SERVER_PORT" "$MONGO_PORT" "$INSPECT_PORT"; do kill_port_listeners "$port"; done',
|
|
195
|
-
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
195
|
+
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\.sh|stop-local-qa\\.sh|bugfix-comparison-qa\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
196
196
|
' skip_cleanup_pid "$pid" && continue',
|
|
197
197
|
' kill_tree "$pid"',
|
|
198
198
|
' done',
|
|
@@ -215,7 +215,7 @@ function buildResolveIORunnerLocalQaScript() {
|
|
|
215
215
|
' for port in "$CLIENT_PORT" "$SERVER_PORT" "$MONGO_PORT" "$INSPECT_PORT"; do',
|
|
216
216
|
' if command -v lsof >/dev/null 2>&1 && [ -n "$(lsof -ti tcp:"$port" 2>/dev/null || true)" ]; then found=1; fi',
|
|
217
217
|
' done',
|
|
218
|
-
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
218
|
+
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\.sh|stop-local-qa\\.sh|bugfix-comparison-qa\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
219
219
|
' skip_cleanup_pid "$pid" && continue',
|
|
220
220
|
' found=1',
|
|
221
221
|
' done',
|
|
@@ -291,12 +291,16 @@ function buildResolveIORunnerLocalQaScript() {
|
|
|
291
291
|
' local end=$((SECONDS + STARTUP_TIMEOUT))',
|
|
292
292
|
' while [ "$SECONDS" -lt "$end" ]; do',
|
|
293
293
|
' if log_has_fatal "$ARTIFACT_DIR/server.log"; then return 4; fi',
|
|
294
|
-
' if [ -n "$SERVER_PID" ] && ! kill -0 "$SERVER_PID" >/dev/null 2>&1; then return 4; fi',
|
|
295
294
|
' if server_has_started; then',
|
|
296
295
|
' local stable_until=$((SECONDS + SERVER_STABLE_SECONDS))',
|
|
297
296
|
' while [ "$SECONDS" -lt "$stable_until" ]; do if log_has_fatal "$ARTIFACT_DIR/server.log"; then return 4; fi; sleep 2; done',
|
|
298
297
|
' return 0',
|
|
299
298
|
' fi',
|
|
299
|
+
' if probe_url "$SERVER_URL"; then',
|
|
300
|
+
' local stable_until=$((SECONDS + SERVER_STABLE_SECONDS))',
|
|
301
|
+
' while [ "$SECONDS" -lt "$stable_until" ]; do if log_has_fatal "$ARTIFACT_DIR/server.log"; then return 4; fi; sleep 2; done',
|
|
302
|
+
' return 0',
|
|
303
|
+
' fi',
|
|
300
304
|
' sleep 5',
|
|
301
305
|
' done',
|
|
302
306
|
' return 4',
|
|
@@ -415,7 +419,7 @@ function buildResolveIORunnerLocalQaStopperScript() {
|
|
|
415
419
|
'done',
|
|
416
420
|
'for pass in 1 2 3; do',
|
|
417
421
|
' for port in "$CLIENT_PORT" "$SERVER_PORT" "$MONGO_PORT" "$INSPECT_PORT"; do kill_port_listeners "$port"; done',
|
|
418
|
-
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
422
|
+
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\.sh|stop-local-qa\\.sh|bugfix-comparison-qa\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
419
423
|
' skip_cleanup_pid "$pid" && continue',
|
|
420
424
|
' kill_tree "$pid"',
|
|
421
425
|
' done',
|
|
@@ -438,7 +442,7 @@ function buildResolveIORunnerLocalQaStopperScript() {
|
|
|
438
442
|
' for port in "$CLIENT_PORT" "$SERVER_PORT" "$MONGO_PORT" "$INSPECT_PORT"; do',
|
|
439
443
|
' if command -v lsof >/dev/null 2>&1 && [ -n "$(lsof -ti tcp:"$port" 2>/dev/null || true)" ]; then found=1; fi',
|
|
440
444
|
' done',
|
|
441
|
-
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
445
|
+
' for pid in $(ps -eo pid=,args= | awk -v root="$PROJECT_ROOT" \'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\.sh|stop-local-qa\\.sh|bugfix-comparison-qa\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\/\\.bin\\/ng|esbuild|npm run client|start_client\\.sh|npm run server|start_server\\.sh|nodemon|node .*tmp\\/index\\.js|mongod|mongodb-binaries\\/mongod)/ {print $1}\' 2>/dev/null || true); do',
|
|
442
446
|
' skip_cleanup_pid "$pid" && continue',
|
|
443
447
|
' found=1',
|
|
444
448
|
' done',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/ai-runner-qa-tools.ts"],"names":[],"mappings":"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","file":"ai-runner-qa-tools.js","sourcesContent":["export interface ResolveIORunnerQaToolBundleOptions {\n\tmode?: 'support' | 'runner';\n\tqaClientPort?: number | string;\n\tdefaultUsername?: string;\n\tdefaultPassword?: string;\n\ttoolsBinPath?: string;\n\tbrowserslistPath?: string;\n\tmongodbBinaryCachePath?: string;\n\ttmpRoot?: string;\n\thomeRoot?: string;\n}\n\nfunction shellDoubleQuote(value: string): string {\n\treturn String(value || '').replace(/[\"\\\\$`]/g, '\\\\$&');\n}\n\nfunction normalizePort(value: number | string | undefined, fallback: string): string {\n\tconst parsed = Number.parseInt(String(value || ''), 10);\n\treturn Number.isFinite(parsed) && parsed > 0 ? String(parsed) : fallback;\n}\n\nfunction envVar(mode: 'support' | 'runner', suffix: string): string {\n\treturn mode === 'support' ? `RESOLVEIO_SUPPORT_QA_${suffix}` : `RESOLVEIO_RUNNER_QA_${suffix}`;\n}\n\nexport function buildResolveIORunnerQaEnvScript(options: ResolveIORunnerQaToolBundleOptions = {}): string {\n\tconst mode = options.mode || 'runner';\n\tconst altMode = mode === 'support' ? 'runner' : 'support';\n\tconst tmpRoot = options.tmpRoot || (mode === 'support' ? '/tmp/resolveio-support-qa' : '/tmp/resolveio-ai-runner-qa');\n\tconst homeRoot = options.homeRoot || `${tmpRoot}/home`;\n\tconst defaultPort = normalizePort(options.qaClientPort, '4200');\n\tconst username = shellDoubleQuote(options.defaultUsername || 'admin');\n\tconst password = shellDoubleQuote(options.defaultPassword || '');\n\tconst toolsBinPath = options.toolsBinPath || '';\n\tconst browserslistPath = options.browserslistPath || '';\n\tconst mongodbBinaryCachePath = options.mongodbBinaryCachePath || '';\n\tconst clientPortVar = envVar(mode, 'CLIENT_PORT');\n\tconst altClientPortVar = envVar(altMode, 'CLIENT_PORT');\n\tconst clientUrlVar = envVar(mode, 'CLIENT_URL');\n\tconst altClientUrlVar = envVar(altMode, 'CLIENT_URL');\n\tconst serverUrlVar = envVar(mode, 'SERVER_URL');\n\tconst altServerUrlVar = envVar(altMode, 'SERVER_URL');\n\tconst usernameVar = envVar(mode, 'USERNAME');\n\tconst altUsernameVar = envVar(altMode, 'USERNAME');\n\tconst passwordVar = envVar(mode, 'PASSWORD');\n\tconst altPasswordVar = envVar(altMode, 'PASSWORD');\n\tconst viewportWidthVar = envVar(mode, 'VIEWPORT_WIDTH');\n\tconst altViewportWidthVar = envVar(altMode, 'VIEWPORT_WIDTH');\n\tconst viewportHeightVar = envVar(mode, 'VIEWPORT_HEIGHT');\n\tconst altViewportHeightVar = envVar(altMode, 'VIEWPORT_HEIGHT');\n\tconst timeoutVar = envVar(mode, 'ANGULAR_STARTUP_TIMEOUT_SECONDS');\n\tconst altTimeoutVar = envVar(altMode, 'ANGULAR_STARTUP_TIMEOUT_SECONDS');\n\tconst prebundleVar = envVar(mode, 'ANGULAR_PREBUNDLE');\n\tconst altPrebundleVar = envVar(altMode, 'ANGULAR_PREBUNDLE');\n\tconst reuseVar = envVar(mode, 'REUSE_RUNNING');\n\tconst altReuseVar = envVar(altMode, 'REUSE_RUNNING');\n\tconst keepaliveVar = envVar(mode, 'KEEPALIVE');\n\tconst altKeepaliveVar = envVar(altMode, 'KEEPALIVE');\n\tconst browserLoopVar = mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_BROWSER' : 'RESOLVEIO_RUNNER_QA_BROWSER';\n\treturn [\n\t\t`export ${mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP'}=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP') + ':-' + tmpRoot + '}'}\"`,\n\t\t`export ${mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME'}=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME') + ':-' + homeRoot + '}'}\"`,\n\t\t`RESOLVEIO_QA_TMP=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP') + '}'}\"`,\n\t\t`RESOLVEIO_QA_HOME=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME') + '}'}\"`,\n\t\t'mkdir -p \"$RESOLVEIO_QA_HOME/.nvm\" \"$RESOLVEIO_QA_TMP/npm-cache\" \"$RESOLVEIO_QA_TMP/mongodb-binaries\" \"$RESOLVEIO_QA_TMP/mongodb-memory-server-core\"',\n\t\t'if [ ! -f \"$RESOLVEIO_QA_HOME/.nvm/nvm.sh\" ]; then',\n\t\t' cat > \"$RESOLVEIO_QA_HOME/.nvm/nvm.sh\" <<\\'RESOLVEIO_NVM_SHIM\\'',\n\t\t'nvm() {',\n\t\t' case \"$1\" in',\n\t\t' use|install|alias) return 0 ;;',\n\t\t' current) node -v 2>/dev/null || true; return 0 ;;',\n\t\t' *) return 0 ;;',\n\t\t' esac',\n\t\t'}',\n\t\t'RESOLVEIO_NVM_SHIM',\n\t\t'fi',\n\t\t'export HOME=\"$RESOLVEIO_QA_HOME\"',\n\t\t'export NVM_DIR=\"$RESOLVEIO_QA_HOME/.nvm\"',\n\t\ttoolsBinPath ? `export PATH=\"${toolsBinPath}:$PATH\"` : '',\n\t\t'export NODE_ENV=development',\n\t\tbrowserslistPath ? `export BROWSERSLIST_CONFIG=\"${browserslistPath}\"` : '',\n\t\t`export ${clientPortVar}=\"${'${' + clientPortVar + ':-${' + altClientPortVar + ':-' + defaultPort + '}}'}\"`,\n\t\t`export ${altClientPortVar}=\"${'${' + altClientPortVar + ':-${' + clientPortVar + '}}'}\"`,\n\t\t`export ${clientUrlVar}=\"${'${' + clientUrlVar + ':-${' + altClientUrlVar + ':-http://localhost:${' + clientPortVar + '}}}'}\"`,\n\t\t`export ${altClientUrlVar}=\"${'${' + altClientUrlVar + ':-${' + clientUrlVar + '}}'}\"`,\n\t\t`export ${serverUrlVar}=\"${'${' + serverUrlVar + ':-${' + altServerUrlVar + ':-http://localhost:8080}}'}\"`,\n\t\t`export ${altServerUrlVar}=\"${'${' + altServerUrlVar + ':-${' + serverUrlVar + '}}'}\"`,\n\t\t'export ADDITIONAL_ALLOWED_ORIGINS=\"${ADDITIONAL_ALLOWED_ORIGINS:-$' + clientUrlVar + '}\"',\n\t\t`export ${viewportWidthVar}=\"${'${' + viewportWidthVar + ':-${' + altViewportWidthVar + ':-1920}}'}\"`,\n\t\t`export ${altViewportWidthVar}=\"${'${' + altViewportWidthVar + ':-${' + viewportWidthVar + '}}'}\"`,\n\t\t`export ${viewportHeightVar}=\"${'${' + viewportHeightVar + ':-${' + altViewportHeightVar + ':-1080}}'}\"`,\n\t\t`export ${altViewportHeightVar}=\"${'${' + altViewportHeightVar + ':-${' + viewportHeightVar + '}}'}\"`,\n\t\t`export ${timeoutVar}=\"${'${' + timeoutVar + ':-${' + altTimeoutVar + ':-900}}'}\"`,\n\t\t`export ${altTimeoutVar}=\"${'${' + altTimeoutVar + ':-${' + timeoutVar + '}}'}\"`,\n\t\t`export ${prebundleVar}=\"${'${' + prebundleVar + ':-${' + altPrebundleVar + ':-false}}'}\"`,\n\t\t`export ${altPrebundleVar}=\"${'${' + altPrebundleVar + ':-${' + prebundleVar + '}}'}\"`,\n\t\t`export ${reuseVar}=\"${'${' + reuseVar + ':-${' + altReuseVar + ':-true}}'}\"`,\n\t\t`export ${altReuseVar}=\"${'${' + altReuseVar + ':-${' + reuseVar + '}}'}\"`,\n\t\t`export ${keepaliveVar}=\"${'${' + keepaliveVar + ':-${' + altKeepaliveVar + ':-false}}'}\"`,\n\t\t`export ${altKeepaliveVar}=\"${'${' + altKeepaliveVar + ':-${' + keepaliveVar + '}}'}\"`,\n\t\t`export ${usernameVar}=\"${'${' + usernameVar + ':-${' + altUsernameVar + ':-' + username + '}}'}\"`,\n\t\t`export ${altUsernameVar}=\"${'${' + altUsernameVar + ':-${' + usernameVar + '}}'}\"`,\n\t\t`export ${passwordVar}=\"${'${' + passwordVar + ':-${' + altPasswordVar + ':-' + password + '}}'}\"`,\n\t\t`export ${altPasswordVar}=\"${'${' + altPasswordVar + ':-${' + passwordVar + '}}'}\"`,\n\t\t'export PUPPETEER_CACHE_DIR=\"${PUPPETEER_CACHE_DIR:-/var/lib/resolveio/puppeteer}\"',\n\t\t'if [ ! -d \"$PUPPETEER_CACHE_DIR\" ] || [ ! -w \"$PUPPETEER_CACHE_DIR\" ]; then',\n\t\t' export PUPPETEER_CACHE_DIR=\"$RESOLVEIO_QA_TMP/puppeteer\"',\n\t\t' mkdir -p \"$PUPPETEER_CACHE_DIR\"',\n\t\t'fi',\n\t\t`for ${browserLoopVar} in \"$PUPPETEER_CACHE_DIR\"/chrome-headless-shell/linux-*/chrome-headless-shell-linux64/chrome-headless-shell \"$PUPPETEER_CACHE_DIR\"/chrome/linux-*/chrome-linux64/chrome; do`,\n\t\t` if [ -x \"$${browserLoopVar}\" ]; then`,\n\t\t` export PUPPETEER_EXECUTABLE_PATH=\"$${browserLoopVar}\"`,\n\t\t` export CHROME_BIN=\"$${browserLoopVar}\"`,\n\t\t' break',\n\t\t' fi',\n\t\t'done',\n\t\t`unset ${browserLoopVar}`,\n\t\t'export NPM_CONFIG_CACHE=\"$RESOLVEIO_QA_TMP/npm-cache\"',\n\t\t'export NPM_CONFIG_PREFER_OFFLINE=true',\n\t\t'export NPM_CONFIG_PRODUCTION=false',\n\t\t'export npm_config_production=false',\n\t\t'export RESOLVEIO_SUPPORT_MONGOMS_PACKAGE_ROOT=\"$RESOLVEIO_QA_TMP/mongodb-memory-server-core\"',\n\t\t'export MONGOMS_DOWNLOAD_DIR=\"$RESOLVEIO_QA_TMP/mongodb-binaries\"',\n\t\tmongodbBinaryCachePath ? `export RESOLVEIO_SUPPORT_SHARED_MONGOMS_DOWNLOAD_DIR=\"${mongodbBinaryCachePath}\"` : '',\n\t\t'export MONGOMS_VERSION=\"${MONGOMS_VERSION:-7.0.14}\"',\n\t\t''\n\t].filter((line) => line !== '').join('\\n');\n}\n\nexport function buildResolveIORunnerLocalQaScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-$(pwd)}\"',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'mkdir -p \"$ARTIFACT_DIR\"',\n\t\t'CLIENT_URL=\"${RESOLVEIO_RUNNER_QA_CLIENT_URL:-${RESOLVEIO_SUPPORT_QA_CLIENT_URL:-http://localhost:${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}}}\"',\n\t\t'SERVER_URL=\"${RESOLVEIO_RUNNER_QA_SERVER_URL:-${RESOLVEIO_SUPPORT_QA_SERVER_URL:-http://localhost:8080}}\"',\n\t\t'CLIENT_PORT=\"${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}\"',\n\t\t'SERVER_PORT=\"${RESOLVEIO_RUNNER_QA_SERVER_PORT:-${RESOLVEIO_SUPPORT_QA_SERVER_PORT:-8080}}\"',\n\t\t'MONGO_PORT=\"${RESOLVEIO_RUNNER_QA_MONGO_PORT:-${RESOLVEIO_SUPPORT_QA_MONGO_PORT:-3001}}\"',\n\t\t'INSPECT_PORT=\"${RESOLVEIO_RUNNER_QA_INSPECT_PORT:-${RESOLVEIO_SUPPORT_QA_INSPECT_PORT:-9229}}\"',\n\t\t'STARTUP_TIMEOUT=\"${RESOLVEIO_RUNNER_QA_ANGULAR_STARTUP_TIMEOUT_SECONDS:-${RESOLVEIO_SUPPORT_QA_ANGULAR_STARTUP_TIMEOUT_SECONDS:-900}}\"',\n\t\t'ANGULAR_PREBUNDLE=\"${RESOLVEIO_RUNNER_QA_ANGULAR_PREBUNDLE:-${RESOLVEIO_SUPPORT_QA_ANGULAR_PREBUNDLE:-false}}\"',\n\t\t'REUSE_RUNNING=\"${RESOLVEIO_RUNNER_QA_REUSE_RUNNING:-${RESOLVEIO_SUPPORT_QA_REUSE_RUNNING:-true}}\"',\n\t\t'if [[ \"$(basename \"$TOOLS_DIR\")\" == *support* ]]; then',\n\t\t' KEEPALIVE=\"${RESOLVEIO_SUPPORT_QA_KEEPALIVE:-${RESOLVEIO_RUNNER_QA_KEEPALIVE:-false}}\"',\n\t\t'else',\n\t\t' KEEPALIVE=\"${RESOLVEIO_RUNNER_QA_KEEPALIVE:-${RESOLVEIO_SUPPORT_QA_KEEPALIVE:-false}}\"',\n\t\t'fi',\n\t\t'SERVER_STABLE_SECONDS=\"${RESOLVEIO_RUNNER_QA_SERVER_STABLE_SECONDS:-${RESOLVEIO_SUPPORT_QA_SERVER_STABLE_SECONDS:-20}}\"',\n\t\t'LOCK_DIR=\"$ARTIFACT_DIR/.qa.lock\"',\n\t\t'SERVER_PID=\"\"',\n\t\t'CLIENT_PID=\"\"',\n\t\t'SERVER_REQUIRED=0',\n\t\t'ANGULAR_PREBUNDLE_ARGS=()',\n\t\t'case \"${ANGULAR_PREBUNDLE,,}\" in',\n\t\t' false|0|no|off) ANGULAR_PREBUNDLE_ARGS=(--prebundle=false) ;;',\n\t\t'esac',\n\t\t'kill_tree() {',\n\t\t' local pid=\"$1\"',\n\t\t' [ -n \"$pid\" ] || return 0',\n\t\t' for child in $(pgrep -P \"$pid\" 2>/dev/null || true); do kill_tree \"$child\"; done',\n\t\t' kill \"$pid\" >/dev/null 2>&1 || true',\n\t\t' sleep 1',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 && kill -9 \"$pid\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'kill_port_listeners() {',\n\t\t' local port=\"$1\"',\n\t\t' [ -n \"$port\" ] || return 0',\n\t\t' local pids=\"\"',\n\t\t' if command -v lsof >/dev/null 2>&1; then pids=\"$pids $(lsof -ti tcp:\"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v fuser >/dev/null 2>&1; then pids=\"$pids $(fuser -n tcp \"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v ss >/dev/null 2>&1; then pids=\"$pids $(ss -ltnp \"sport = :$port\" 2>/dev/null | sed -n \\'s/.*pid=\\\\([0-9][0-9]*\\\\).*/\\\\1/p\\' || true)\"; fi',\n\t\t' for pid in $pids; do',\n\t\t' [ \"$pid\" = \"$$\" ] && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' sleep 1',\n\t\t'}',\n\t\t'RUNNER_ANCESTOR_PIDS=\" $$ ${PPID:-} \"',\n\t\t'ancestor_pid=\"${PPID:-}\"',\n\t\t'while [ -n \"$ancestor_pid\" ] && [ \"$ancestor_pid\" != \"0\" ] && [ \"$ancestor_pid\" != \"1\" ]; do',\n\t\t' ancestor_pid=\"$(ps -o ppid= -p \"$ancestor_pid\" 2>/dev/null | tr -d \" \" || true)\"',\n\t\t' [ -n \"$ancestor_pid\" ] && RUNNER_ANCESTOR_PIDS=\"$RUNNER_ANCESTOR_PIDS $ancestor_pid \"',\n\t\t'done',\n\t\t'skip_cleanup_pid() {',\n\t\t' case \"$RUNNER_ANCESTOR_PIDS\" in *\" $1 \"*) return 0 ;; esac',\n\t\t' return 1',\n\t\t'}',\n\t\t'cleanup_project_processes() {',\n\t\t' for pid_file in \"$ARTIFACT_DIR/server.pid\" \"$ARTIFACT_DIR/client.pid\"; do',\n\t\t' [ -f \"$pid_file\" ] || continue',\n\t\t' pid=\"$(cat \"$pid_file\" 2>/dev/null || true)\"',\n\t\t' kill_tree \"$pid\"',\n\t\t' rm -f \"$pid_file\"',\n\t\t' done',\n\t\t' for pass in 1 2 3; do',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do kill_port_listeners \"$port\"; done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' if [ -d /proc ]; then',\n\t\t' for proc_cwd in /proc/[0-9]*/cwd; do',\n\t\t' pid=\"${proc_cwd#/proc/}\"',\n\t\t' pid=\"${pid%/cwd}\"',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' cwd=\"$(readlink -f \"$proc_cwd\" 2>/dev/null || true)\"',\n\t\t' case \"$cwd\" in',\n\t\t' \"$PROJECT_ROOT\"|\"$PROJECT_ROOT\"/*) kill_tree \"$pid\" ;;',\n\t\t' esac',\n\t\t' done',\n\t\t' fi',\n\t\t' sleep 1',\n\t\t' done',\n\t\t' local wait_until=$((SECONDS + 60))',\n\t\t' while [ \"$SECONDS\" -lt \"$wait_until\" ]; do',\n\t\t' local found=0',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do',\n\t\t' if command -v lsof >/dev/null 2>&1 && [ -n \"$(lsof -ti tcp:\"$port\" 2>/dev/null || true)\" ]; then found=1; fi',\n\t\t' done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' found=1',\n\t\t' done',\n\t\t' [ \"$found\" = \"0\" ] && break',\n\t\t' sleep 2',\n\t\t' done',\n\t\t'}',\n\t\t'cleanup() {',\n\t\t' kill_tree \"$SERVER_PID\"',\n\t\t' kill_tree \"$CLIENT_PID\"',\n\t\t' cleanup_project_processes',\n\t\t' rmdir \"$LOCK_DIR\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'trap cleanup EXIT',\n\t\t'probe_url() { node - \"$1\" <<\\'RESOLVEIO_PROBE\\'',\n\t\t'const http = require(\"http\");',\n\t\t'const https = require(\"https\");',\n\t\t'const url = process.argv[2];',\n\t\t'const mod = /^https:/i.test(url) ? https : http;',\n\t\t'const req = mod.get(url, { timeout: 2500 }, (res) => { res.resume(); process.exit(res.statusCode && res.statusCode < 500 ? 0 : 1); });',\n\t\t'req.on(\"timeout\", () => req.destroy(new Error(\"timeout\")));',\n\t\t'req.on(\"error\", () => process.exit(1));',\n\t\t'RESOLVEIO_PROBE',\n\t\t'}',\n\t\t'truthy() { case \"${1,,}\" in true|1|yes|on) return 0 ;; *) return 1 ;; esac; }',\n\t\t'reuse_running_app_if_ready() {',\n\t\t' truthy \"$REUSE_RUNNING\" || return 1',\n\t\t' [ -d \"$PROJECT_ROOT/server\" ] && SERVER_REQUIRED=1 || SERVER_REQUIRED=0',\n\t\t' probe_url \"$CLIENT_URL\" || return 1',\n\t\t' if [ \"$SERVER_REQUIRED\" = \"1\" ] && ! probe_url \"$SERVER_URL\"; then return 1; fi',\n\t\t' echo \"ResolveIO AI runner QA reusing already-ready local app at $CLIENT_URL\"',\n\t\t' return 0',\n\t\t'}',\n\t\t'log_has_fatal() {',\n\t\t' local file=\"$1\"',\n\t\t' [ -f \"$file\" ] || return 1',\n\t\t' grep -Eiq \"Unhandled Rejection|Cannot read properties of undefined|TypeError|ReferenceError|EADDRINUSE|app crashed|Failed to compile|Error: Cannot find module|NG[0-9]{4}|TS[0-9]{4}\" \"$file\"',\n\t\t'}',\n\t\t'prepare_angular_cache_dirs() {',\n\t\t' [ -d \"$PROJECT_ROOT\" ] || return 0',\n\t\t' mkdir -p \"$PROJECT_ROOT/.angular/cache\" 2>/dev/null || true',\n\t\t' local version=\"\"',\n\t\t' for pkg in \"$PROJECT_ROOT/node_modules/@angular/build/package.json\" \"$PROJECT_ROOT/node_modules/@angular/cli/package.json\" \"$PROJECT_ROOT/node_modules/@angular-devkit/build-angular/package.json\"; do',\n\t\t' if [ -f \"$pkg\" ]; then',\n\t\t' version=\"$(node -e \"try{console.log(require(process.argv[1]).version||\\\\\\\"\\\\\\\")}catch(e){}\" \"$pkg\" 2>/dev/null | head -1)\"',\n\t\t' [ -n \"$version\" ] && break',\n\t\t' fi',\n\t\t' done',\n\t\t' [ -n \"$version\" ] || return 0',\n\t\t' node - \"$PROJECT_ROOT/angular.json\" \"$(basename \"$PROJECT_ROOT\")\" <<\\'RESOLVEIO_ANGULAR_CACHE_PROJECTS\\' | while IFS= read -r project; do',\n\t\t'const fs = require(\"fs\");',\n\t\t'const path = process.argv[2];',\n\t\t'const fallback = process.argv[3];',\n\t\t'const names = new Set([fallback].filter(Boolean));',\n\t\t'try {',\n\t\t' const parsed = JSON.parse(fs.readFileSync(path, \"utf8\"));',\n\t\t' if (parsed.defaultProject) names.add(String(parsed.defaultProject));',\n\t\t' if (parsed.projects && typeof parsed.projects === \"object\") Object.keys(parsed.projects).forEach((name) => names.add(String(name)));',\n\t\t'} catch (error) {}',\n\t\t'for (const name of names) console.log(name.replace(/[^A-Za-z0-9._-]/g, \"_\"));',\n\t\t'RESOLVEIO_ANGULAR_CACHE_PROJECTS',\n\t\t' [ -n \"$project\" ] || continue',\n\t\t' mkdir -p \"$PROJECT_ROOT/.angular/cache/$version/$project/vite\" 2>/dev/null || true',\n\t\t' done',\n\t\t'}',\n\t\t'server_has_started() {',\n\t\t' local file=\"$ARTIFACT_DIR/server.log\"',\n\t\t' [ -f \"$file\" ] || return 1',\n\t\t' grep -Eiq \"nodemon.*starting|node .*tmp/index\\\\.js|Running as Worker|Standalone Node Reaper|listening on|server listening|Server listening|app listening|App listening|Finished .default.\" \"$file\"',\n\t\t'}',\n\t\t'wait_for_server_ready() {',\n\t\t' [ \"$SERVER_REQUIRED\" = \"1\" ] || return 0',\n\t\t' local end=$((SECONDS + STARTUP_TIMEOUT))',\n\t\t' while [ \"$SECONDS\" -lt \"$end\" ]; do',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi',\n\t\t' if [ -n \"$SERVER_PID\" ] && ! kill -0 \"$SERVER_PID\" >/dev/null 2>&1; then return 4; fi',\n\t\t' if server_has_started; then',\n\t\t' local stable_until=$((SECONDS + SERVER_STABLE_SECONDS))',\n\t\t' while [ \"$SECONDS\" -lt \"$stable_until\" ]; do if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi; sleep 2; done',\n\t\t' return 0',\n\t\t' fi',\n\t\t' sleep 5',\n\t\t' done',\n\t\t' return 4',\n\t\t'}',\n\t\t'wait_for_client() {',\n\t\t' local end=$((SECONDS + STARTUP_TIMEOUT))',\n\t\t' while [ \"$SECONDS\" -lt \"$end\" ]; do',\n\t\t' if [ -n \"$CLIENT_PID\" ] && ! kill -0 \"$CLIENT_PID\" >/dev/null 2>&1; then return 2; fi',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/client.log\"; then return 3; fi',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi',\n\t\t' if probe_url \"$CLIENT_URL\"; then wait_for_server_ready || return $?; return 0; fi',\n\t\t' sleep 5',\n\t\t' done',\n\t\t' return 1',\n\t\t'}',\n\t\t'if reuse_running_app_if_ready; then exit 0; fi',\n\t\t'if ! mkdir \"$LOCK_DIR\" 2>/dev/null; then',\n\t\t' echo \"ResolveIO AI runner QA lock is already held for $PROJECT_ROOT; cleaning stale local QA processes before retrying.\" | tee \"$ARTIFACT_DIR/runner.log\"',\n\t\t' cleanup_project_processes',\n\t\t' rmdir \"$LOCK_DIR\" >/dev/null 2>&1 || true',\n\t\t' if ! mkdir \"$LOCK_DIR\" 2>/dev/null; then',\n\t\t' echo \"ResolveIO AI runner QA lock is still held for $PROJECT_ROOT after cleanup. Stop the existing QA runner before starting another.\" | tee -a \"$ARTIFACT_DIR/runner.log\"',\n\t\t' exit 6',\n\t\t' fi',\n\t\t'fi',\n\t\t'cleanup_project_processes',\n\t\t'if [ -d \"$PROJECT_ROOT/server\" ]; then',\n\t\t' SERVER_REQUIRED=1',\n\t\t' (cd \"$PROJECT_ROOT/server\" && source \"$TOOLS_DIR/env.sh\" && { npm run server || ./start_server.sh; } 2>&1 | tee \"$ARTIFACT_DIR/server.log\") &',\n\t\t' SERVER_PID=$!',\n\t\t' wait_for_server_ready',\n\t\t' SERVER_RESULT=$?',\n\t\t' if [ \"$SERVER_RESULT\" != \"0\" ]; then echo \"ResolveIO AI runner QA server startup fatal error. See $ARTIFACT_DIR/server.log\"; exit \"$SERVER_RESULT\"; fi',\n\t\t'fi',\n\t\t'CLIENT_HOST=\"${RESOLVEIO_RUNNER_QA_CLIENT_HOST:-${RESOLVEIO_SUPPORT_QA_CLIENT_HOST:-0.0.0.0}}\"',\n\t\t'if [ -x \"$PROJECT_ROOT/node_modules/.bin/ng\" ]; then',\n\t\t' prepare_angular_cache_dirs',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && node --max_old_space_size=8048 ./node_modules/.bin/ng serve --watch --configuration local --host \"$CLIENT_HOST\" --port \"$CLIENT_PORT\" \"${ANGULAR_PREBUNDLE_ARGS[@]}\" 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'elif [ -x \"$PROJECT_ROOT/start_client.sh\" ]; then',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && ./start_client.sh 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'elif node -e \"const p=require(process.argv[1]); process.exit(p.scripts&&p.scripts.client?0:1)\" \"$PROJECT_ROOT/package.json\" >/dev/null 2>&1; then',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && npm run client 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'else',\n\t\t' echo \"ResolveIO AI runner QA cannot find Angular CLI, start_client.sh, or npm client script for $PROJECT_ROOT\" | tee \"$ARTIFACT_DIR/client.log\"',\n\t\t' exit 5',\n\t\t'fi',\n\t\t'CLIENT_PID=$!',\n\t\t'wait_for_client',\n\t\t'RESULT=$?',\n\t\t'case \"$RESULT\" in',\n\t\t' 0)',\n\t\t' echo \"ResolveIO AI runner QA local app ready at $CLIENT_URL\";',\n\t\t' echo \"$SERVER_PID\" > \"$ARTIFACT_DIR/server.pid\";',\n\t\t' echo \"$CLIENT_PID\" > \"$ARTIFACT_DIR/client.pid\";',\n\t\t' if truthy \"$KEEPALIVE\"; then echo \"ResolveIO AI runner QA keepalive enabled; server/client remain running until this process is stopped.\"; wait; fi;',\n\t\t' exit 0',\n\t\t' ;;',\n\t\t' 2) echo \"ResolveIO AI runner QA client process exited before $CLIENT_URL became ready. See $ARTIFACT_DIR/client.log\"; exit 2 ;;',\n\t\t' 3) echo \"ResolveIO AI runner QA client startup fatal error. See $ARTIFACT_DIR/client.log\"; exit 3 ;;',\n\t\t' 4) echo \"ResolveIO AI runner QA server startup fatal error. See $ARTIFACT_DIR/server.log\"; exit 4 ;;',\n\t\t' *) echo \"ResolveIO AI runner QA local app did not become ready at $CLIENT_URL within ${STARTUP_TIMEOUT}s. See $ARTIFACT_DIR/client.log and $ARTIFACT_DIR/server.log\"; exit 1 ;;',\n\t\t'esac',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerLocalQaStopperScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-$(pwd)}\"',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'CLIENT_PORT=\"${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}\"',\n\t\t'SERVER_PORT=\"${RESOLVEIO_RUNNER_QA_SERVER_PORT:-${RESOLVEIO_SUPPORT_QA_SERVER_PORT:-8080}}\"',\n\t\t'MONGO_PORT=\"${RESOLVEIO_RUNNER_QA_MONGO_PORT:-${RESOLVEIO_SUPPORT_QA_MONGO_PORT:-3001}}\"',\n\t\t'INSPECT_PORT=\"${RESOLVEIO_RUNNER_QA_INSPECT_PORT:-${RESOLVEIO_SUPPORT_QA_INSPECT_PORT:-9229}}\"',\n\t\t'kill_tree() {',\n\t\t' local pid=\"$1\"',\n\t\t' [ -n \"$pid\" ] || return 0',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 || return 0',\n\t\t' for child in $(pgrep -P \"$pid\" 2>/dev/null || true); do kill_tree \"$child\"; done',\n\t\t' kill \"$pid\" >/dev/null 2>&1 || true',\n\t\t' sleep 1',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 && kill -9 \"$pid\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'kill_port_listeners() {',\n\t\t' local port=\"$1\"',\n\t\t' [ -n \"$port\" ] || return 0',\n\t\t' local pids=\"\"',\n\t\t' if command -v lsof >/dev/null 2>&1; then pids=\"$pids $(lsof -ti tcp:\"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v fuser >/dev/null 2>&1; then pids=\"$pids $(fuser -n tcp \"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v ss >/dev/null 2>&1; then pids=\"$pids $(ss -ltnp \"sport = :$port\" 2>/dev/null | sed -n \\'s/.*pid=\\\\([0-9][0-9]*\\\\).*/\\\\1/p\\' || true)\"; fi',\n\t\t' for pid in $pids; do',\n\t\t' [ \"$pid\" = \"$$\" ] && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' sleep 1',\n\t\t'}',\n\t\t'RUNNER_ANCESTOR_PIDS=\" $$ ${PPID:-} \"',\n\t\t'ancestor_pid=\"${PPID:-}\"',\n\t\t'while [ -n \"$ancestor_pid\" ] && [ \"$ancestor_pid\" != \"0\" ] && [ \"$ancestor_pid\" != \"1\" ]; do',\n\t\t' ancestor_pid=\"$(ps -o ppid= -p \"$ancestor_pid\" 2>/dev/null | tr -d \" \" || true)\"',\n\t\t' [ -n \"$ancestor_pid\" ] && RUNNER_ANCESTOR_PIDS=\"$RUNNER_ANCESTOR_PIDS $ancestor_pid \"',\n\t\t'done',\n\t\t'skip_cleanup_pid() {',\n\t\t' case \"$RUNNER_ANCESTOR_PIDS\" in *\" $1 \"*) return 0 ;; esac',\n\t\t' return 1',\n\t\t'}',\n\t\t'for pid_file in \"$ARTIFACT_DIR/server.pid\" \"$ARTIFACT_DIR/client.pid\"; do',\n\t\t' [ -f \"$pid_file\" ] || continue',\n\t\t' pid=\"$(cat \"$pid_file\" 2>/dev/null || true)\"',\n\t\t' kill_tree \"$pid\"',\n\t\t' rm -f \"$pid_file\"',\n\t\t'done',\n\t\t'for pass in 1 2 3; do',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do kill_port_listeners \"$port\"; done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' if [ -d /proc ]; then',\n\t\t' for proc_cwd in /proc/[0-9]*/cwd; do',\n\t\t' pid=\"${proc_cwd#/proc/}\"',\n\t\t' pid=\"${pid%/cwd}\"',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' cwd=\"$(readlink -f \"$proc_cwd\" 2>/dev/null || true)\"',\n\t\t' case \"$cwd\" in',\n\t\t' \"$PROJECT_ROOT\"|\"$PROJECT_ROOT\"/*) kill_tree \"$pid\" ;;',\n\t\t' esac',\n\t\t' done',\n\t\t' fi',\n\t\t' sleep 1',\n\t\t'done',\n\t\t'wait_until=$((SECONDS + 60))',\n\t\t'while [ \"$SECONDS\" -lt \"$wait_until\" ]; do',\n\t\t' found=0',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do',\n\t\t' if command -v lsof >/dev/null 2>&1 && [ -n \"$(lsof -ti tcp:\"$port\" 2>/dev/null || true)\" ]; then found=1; fi',\n\t\t' done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' found=1',\n\t\t' done',\n\t\t' [ \"$found\" = \"0\" ] && break',\n\t\t' sleep 2',\n\t\t'done',\n\t\t'rmdir \"$ARTIFACT_DIR/.qa.lock\" >/dev/null 2>&1 || true',\n\t\t'echo \"ResolveIO AI runner QA local app stopped for $PROJECT_ROOT\"',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerBugfixComparisonQaScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-}\"',\n\t\t'if [ -z \"$PROJECT_ROOT\" ]; then',\n\t\t' echo \"Usage: $0 <project-root> [baseline-ref] -- <qa-command...>\" >&2',\n\t\t' exit 2',\n\t\t'fi',\n\t\t'shift || true',\n\t\t'DEFAULT_BASELINE_REF=\"${RESOLVEIO_RUNNER_QA_BASELINE_REF:-${RESOLVEIO_SUPPORT_QA_BASELINE_REF:-origin/master}}\"',\n\t\t'if [ \"${1:-}\" = \"--\" ]; then',\n\t\t' BASELINE_REF=\"$DEFAULT_BASELINE_REF\"',\n\t\t'else',\n\t\t' BASELINE_REF=\"${1:-$DEFAULT_BASELINE_REF}\"',\n\t\t' if [ \"$#\" -gt 0 ]; then shift || true; fi',\n\t\t'fi',\n\t\t'if [ \"${1:-}\" = \"--\" ]; then shift; fi',\n\t\t'if [ \"$#\" -eq 0 ]; then',\n\t\t' echo \"Usage: $0 <project-root> [baseline-ref] -- <qa-command...>\" >&2',\n\t\t' exit 2',\n\t\t'fi',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'REPO_ROOT=\"$(git -C \"$PROJECT_ROOT\" rev-parse --show-toplevel)\"',\n\t\t'PROJECT_REL=\"$(git -C \"$REPO_ROOT\" ls-files --full-name \"$PROJECT_ROOT\" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || true)\"',\n\t\t'if [ -z \"$PROJECT_REL\" ] || [ \"$PROJECT_REL\" = \".\" ]; then',\n\t\t' PROJECT_REL=\"$(node - \"$REPO_ROOT\" \"$PROJECT_ROOT\" <<\\'RESOLVEIO_REL\\'',\n\t\t'const path = require(\"path\");',\n\t\t'console.log(path.relative(process.argv[2], process.argv[3]) || \".\");',\n\t\t'RESOLVEIO_REL',\n\t\t' )\"',\n\t\t'fi',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'mkdir -p \"$ARTIFACT_DIR/baseline\" \"$ARTIFACT_DIR/candidate\"',\n\t\t'RESULT_JSON=\"$ARTIFACT_DIR/bugfix-comparison-result.json\"',\n\t\t'CANDIDATE_PATCH=\"$ARTIFACT_DIR/bugfix-candidate.patch\"',\n\t\t'ORIGINAL_HEAD=\"$(git -C \"$REPO_ROOT\" rev-parse HEAD)\"',\n\t\t'ORIGINAL_BRANCH=\"$(git -C \"$REPO_ROOT\" symbolic-ref --short HEAD 2>/dev/null || true)\"',\n\t\t'QA_COMMAND=(\"$@\")',\n\t\t'STOPPER=\"$TOOLS_DIR/stop-local-qa.sh\"',\n\t\t'CURRENT_PHASE=\"\"',\n\t\t'stop_local_qa() {',\n\t\t' \"$STOPPER\" \"$PROJECT_ROOT\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'write_json() {',\n\t\t' node - \"$RESULT_JSON\" \"$@\" <<\\'RESOLVEIO_WRITE_JSON\\'',\n\t\t'const fs = require(\"fs\");',\n\t\t'const [path, status, baselineExit, candidateExit, baselineRef, originalHead, projectRel, note] = process.argv.slice(2);',\n\t\t'const payload = {',\n\t\t' status,',\n\t\t' baseline_ref: baselineRef,',\n\t\t' original_head: originalHead,',\n\t\t' project: projectRel,',\n\t\t' baseline_exit_code: Number(baselineExit),',\n\t\t' candidate_exit_code: Number(candidateExit),',\n\t\t' code_switch_proven: Number(baselineExit) !== 0 && Number(candidateExit) === 0,',\n\t\t' candidate_passed: Number(candidateExit) === 0,',\n\t\t' baseline_failed: Number(baselineExit) !== 0,',\n\t\t' note,',\n\t\t' artifact_dirs: { baseline: \"qa-artifacts/baseline\", candidate: \"qa-artifacts/candidate\" },',\n\t\t' created_at: new Date().toISOString()',\n\t\t'};',\n\t\t'fs.writeFileSync(path, JSON.stringify(payload, null, 2));',\n\t\t'console.log(JSON.stringify(payload, null, 2));',\n\t\t'RESOLVEIO_WRITE_JSON',\n\t\t'}',\n\t\t'snapshot_phase_artifacts() {',\n\t\t' local phase=\"$1\"',\n\t\t' mkdir -p \"$ARTIFACT_DIR/$phase\"',\n\t\t' find \"$ARTIFACT_DIR\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*.json\" -o -name \"*.txt\" -o -name \"*.log\" -o -name \"*.zip\" \\\\) -print0 2>/dev/null | while IFS= read -r -d \"\" file; do',\n\t\t' cp \"$file\" \"$ARTIFACT_DIR/$phase/$(basename \"$file\")\" 2>/dev/null || true',\n\t\t' done',\n\t\t'}',\n\t\t'capture_candidate_patch() {',\n\t\t' : > \"$CANDIDATE_PATCH\"',\n\t\t' git -C \"$REPO_ROOT\" diff --binary -- \"$PROJECT_REL\" >> \"$CANDIDATE_PATCH\" || true',\n\t\t' git -C \"$REPO_ROOT\" diff --binary --cached -- \"$PROJECT_REL\" >> \"$CANDIDATE_PATCH\" || true',\n\t\t'}',\n\t\t'checkout_project_from_ref() {',\n\t\t' local ref=\"$1\"',\n\t\t' git -C \"$REPO_ROOT\" checkout \"$ref\" -- \"$PROJECT_REL\"',\n\t\t'}',\n\t\t'restore_candidate() {',\n\t\t' stop_local_qa',\n\t\t' checkout_project_from_ref \"$ORIGINAL_HEAD\" || true',\n\t\t' if [ -s \"$CANDIDATE_PATCH\" ]; then',\n\t\t' git -C \"$REPO_ROOT\" apply --whitespace=nowarn \"$CANDIDATE_PATCH\" || true',\n\t\t' fi',\n\t\t'}',\n\t\t'trap restore_candidate EXIT',\n\t\t'run_phase() {',\n\t\t' local phase=\"$1\"',\n\t\t' CURRENT_PHASE=\"$phase\"',\n\t\t' stop_local_qa',\n\t\t' export RESOLVEIO_RUNNER_QA_PHASE=\"$phase\"',\n\t\t' export RESOLVEIO_SUPPORT_QA_PHASE=\"$phase\"',\n\t\t' export RESOLVEIO_RUNNER_QA_ARTIFACT_DIR=\"$ARTIFACT_DIR/$phase\"',\n\t\t' export RESOLVEIO_SUPPORT_QA_ARTIFACT_DIR=\"$ARTIFACT_DIR/$phase\"',\n\t\t' mkdir -p \"$ARTIFACT_DIR/$phase\"',\n\t\t' find \"$ARTIFACT_DIR/$phase\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*.json\" -o -name \"*.txt\" -o -name \"*.log\" -o -name \"*.zip\" \\\\) -delete 2>/dev/null || true',\n\t\t' find \"$ARTIFACT_DIR\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*proof.json\" -o -name \"auth-bootstrap-result.json\" \\\\) -delete 2>/dev/null || true',\n\t\t' set +e',\n\t\t' (cd \"$REPO_ROOT\" && \"${QA_COMMAND[@]}\") 2>&1 | tee \"$ARTIFACT_DIR/$phase/qa-command.log\"',\n\t\t' local rc=\"${PIPESTATUS[0]}\"',\n\t\t' set +e',\n\t\t' snapshot_phase_artifacts \"$phase\"',\n\t\t' stop_local_qa',\n\t\t' return \"$rc\"',\n\t\t'}',\n\t\t'echo \"ResolveIO bugfix comparison QA preserving candidate diff for $PROJECT_REL\"',\n\t\t'capture_candidate_patch',\n\t\t'stop_local_qa',\n\t\t'echo \"ResolveIO bugfix comparison QA baseline phase: $BASELINE_REF\"',\n\t\t'checkout_project_from_ref \"$BASELINE_REF\"',\n\t\t'run_phase baseline',\n\t\t'BASELINE_EXIT=\"$?\"',\n\t\t'echo \"ResolveIO bugfix comparison QA candidate phase: restored workspace candidate\"',\n\t\t'restore_candidate',\n\t\t'run_phase candidate',\n\t\t'CANDIDATE_EXIT=\"$?\"',\n\t\t'if [ \"$CANDIDATE_EXIT\" = \"0\" ] && [ \"$BASELINE_EXIT\" != \"0\" ]; then',\n\t\t' STATUS=\"pass\"',\n\t\t' NOTE=\"Baseline failed and candidate passed for the same QA command.\"',\n\t\t'elif [ \"$CANDIDATE_EXIT\" = \"0\" ]; then',\n\t\t' STATUS=\"inconclusive_baseline_also_passed\"',\n\t\t' NOTE=\"Candidate passed, but baseline also passed; the code switch did not prove the bug fix.\"',\n\t\t'else',\n\t\t' STATUS=\"fail_candidate_failed\"',\n\t\t' NOTE=\"Candidate failed the QA command.\"',\n\t\t'fi',\n\t\t'write_json \"$STATUS\" \"$BASELINE_EXIT\" \"$CANDIDATE_EXIT\" \"$BASELINE_REF\" \"$ORIGINAL_HEAD\" \"$PROJECT_REL\" \"$NOTE\"',\n\t\t'[ \"$CANDIDATE_EXIT\" = \"0\" ] || exit \"$CANDIDATE_EXIT\"',\n\t\t'[ \"$STATUS\" = \"pass\" ] || exit 8',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerQaToolsReadme(options: ResolveIORunnerQaToolBundleOptions = {}): string {\n\tconst mode = options.mode || 'runner';\n\tconst toolsDir = mode === 'support' ? '.resolveio-support-tools' : '.resolveio-ai-runner-tools';\n\tconst port = normalizePort(options.qaClientPort, '4200');\n\tconst clientUrlVar = envVar(mode, 'CLIENT_URL');\n\tconst keepaliveVar = envVar(mode, 'KEEPALIVE');\n\tconst usernameVar = envVar(mode, 'USERNAME');\n\tconst passwordVar = envVar(mode, 'PASSWORD');\n\treturn [\n\t\t`# ResolveIO ${mode === 'support' ? 'Support' : 'AI Runner'} Local QA Tools`,\n\t\t'',\n\t\t'These scripts are generated by `@resolveio/server-lib` and are shared by support tickets, AICoder app-builder runs, and AI-terminal runs.',\n\t\t'',\n\t\t'```bash',\n\t\t`source ${toolsDir}/env.sh`,\n\t\t`${toolsDir}/run-local-qa.sh <project-root>`,\n\t\t`node ${toolsDir}/qa-auth-bootstrap.js <project-root> /target-route`,\n\t\t`${toolsDir}/bugfix-comparison-qa.sh <project-root> origin/master -- bash -lc '<same QA command>'`,\n\t\t'```',\n\t\t'',\n\t\t`This workspace reserves Angular QA client port ${port}; use \\`$${clientUrlVar}\\` instead of assuming 4200 is free.`,\n\t\t'The local QA runner starts server/client, polls the reserved client URL, writes `qa-artifacts/server.log` and `qa-artifacts/client.log`, and fails fast on fatal startup/runtime errors.',\n\t\t'The shared auth bootstrap calls `/login`, then `/accessToken`, clears service workers/cache/IndexedDB/local storage for the exact localhost client origin, seeds `refreshToken`, `accessToken`, `user`, and `lastURL`, and writes `qa-artifacts/auth-bootstrap-result.json` plus a ready/failure screenshot.',\n\t\t`For browser clickthrough work, start the runner once with \\`${keepaliveVar}=true ${toolsDir}/run-local-qa.sh <project-root> &\\` and reuse \\`$${clientUrlVar}\\` for all login/upload/screenshot retries. Do not restart Angular for auth failures.`,\n\t\t'Use desktop screenshots at 1920x1080 by default unless the task is explicitly mobile/responsive. Every screenshot must have a customer-facing caption.',\n\t\t'For import/export/form-submit/data workflows, prove before/action/after with representative data and a concrete row/count/value assertion.',\n\t\t'For bug fixes, use `bugfix-comparison-qa.sh` so baseline/master runs the exact same repro before the candidate/PR run. A passing candidate is not enough unless the comparison result shows baseline failed or the report explicitly explains why the baseline failure could not be reproduced.',\n\t\t`Use \\`$${usernameVar}\\` and \\`$${passwordVar}\\` for the local fixture admin account unless ticket/app-specific credentials are provided.`,\n\t\t'The env file reuses `/var/lib/resolveio/puppeteer`, npm cache, worker-safe Browserslist settings, and Angular cache prep so QA should not download a browser or rebuild cold caches unnecessarily.',\n\t\tmode === 'support'\n\t\t\t? 'Support workspaces also stage local `mongod` and `mongosh` wrappers so app server scripts can start MongoDB when the worker image does not have MongoDB installed.'\n\t\t\t: '',\n\t\t''\n\t].filter((line) => line !== '').join('\\n');\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/util/ai-runner-qa-tools.ts"],"names":[],"mappings":";;AAyBA,0EAsGC;AAED,8EAsPC;AAED,4FAuFC;AAED,oGAyIC;AAED,8EAkCC;AAnnBD,SAAS,gBAAgB,CAAC,KAAa;IACtC,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,KAAkC,EAAE,QAAgB;IAC1E,IAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1E,CAAC;AAED,SAAS,MAAM,CAAC,IAA0B,EAAE,MAAc;IACzD,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,+BAAwB,MAAM,CAAE,CAAC,CAAC,CAAC,8BAAuB,MAAM,CAAE,CAAC;AAChG,CAAC;AAED,SAAgB,+BAA+B,CAAC,OAAgD;IAAhD,wBAAA,EAAA,YAAgD;IAC/F,IAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC;IACtC,IAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC;IACtH,IAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,UAAG,OAAO,UAAO,CAAC;IACvD,IAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAChE,IAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,CAAC;IACtE,IAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IACjE,IAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAChD,IAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;IACxD,IAAM,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,IAAI,EAAE,CAAC;IACpE,IAAM,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAClD,IAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACxD,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChD,IAAM,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACtD,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChD,IAAM,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACtD,IAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,IAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,IAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACxD,IAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC9D,IAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAC1D,IAAM,oBAAoB,GAAG,MAAM,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAChE,IAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC;IACnE,IAAM,aAAa,GAAG,MAAM,CAAC,OAAO,EAAE,iCAAiC,CAAC,CAAC;IACzE,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACvD,IAAM,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC7D,IAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC/C,IAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACrD,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC/C,IAAM,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACrD,IAAM,cAAc,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,6BAA6B,CAAC;IAC3G,OAAO;QACN,iBAAU,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,yBAAyB,gBAAK,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,IAAI,GAAG,OAAO,GAAG,GAAG,OAAG;QACxM,iBAAU,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,0BAA0B,gBAAK,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,0BAA0B,CAAC,GAAG,IAAI,GAAG,QAAQ,GAAG,GAAG,OAAG;QAC7M,6BAAqB,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,GAAG,OAAG;QAClH,8BAAsB,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,0BAA0B,CAAC,GAAG,GAAG,OAAG;QACrH,sJAAsJ;QACtJ,oDAAoD;QACpD,mEAAmE;QACnE,SAAS;QACT,gBAAgB;QAChB,oCAAoC;QACpC,uDAAuD;QACvD,oBAAoB;QACpB,QAAQ;QACR,GAAG;QACH,oBAAoB;QACpB,IAAI;QACJ,kCAAkC;QAClC,0CAA0C;QAC1C,YAAY,CAAC,CAAC,CAAC,wBAAgB,YAAY,aAAS,CAAC,CAAC,CAAC,EAAE;QACzD,6BAA6B;QAC7B,gBAAgB,CAAC,CAAC,CAAC,uCAA+B,gBAAgB,OAAG,CAAC,CAAC,CAAC,EAAE;QAC1E,iBAAU,aAAa,gBAAK,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,gBAAgB,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,OAAG;QAC3G,iBAAU,gBAAgB,gBAAK,IAAI,GAAG,gBAAgB,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI,OAAG;QACzF,iBAAU,YAAY,gBAAK,IAAI,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,uBAAuB,GAAG,aAAa,GAAG,KAAK,OAAG;QAC9H,iBAAU,eAAe,gBAAK,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,OAAG;QACtF,iBAAU,YAAY,gBAAK,IAAI,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,2BAA2B,OAAG;QAC1G,iBAAU,eAAe,gBAAK,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,OAAG;QACtF,oEAAoE,GAAG,YAAY,GAAG,IAAI;QAC1F,iBAAU,gBAAgB,gBAAK,IAAI,GAAG,gBAAgB,GAAG,MAAM,GAAG,mBAAmB,GAAG,UAAU,OAAG;QACrG,iBAAU,mBAAmB,gBAAK,IAAI,GAAG,mBAAmB,GAAG,MAAM,GAAG,gBAAgB,GAAG,IAAI,OAAG;QAClG,iBAAU,iBAAiB,gBAAK,IAAI,GAAG,iBAAiB,GAAG,MAAM,GAAG,oBAAoB,GAAG,UAAU,OAAG;QACxG,iBAAU,oBAAoB,gBAAK,IAAI,GAAG,oBAAoB,GAAG,MAAM,GAAG,iBAAiB,GAAG,IAAI,OAAG;QACrG,iBAAU,UAAU,gBAAK,IAAI,GAAG,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,SAAS,OAAG;QAClF,iBAAU,aAAa,gBAAK,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,OAAG;QAChF,iBAAU,YAAY,gBAAK,IAAI,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,WAAW,OAAG;QAC1F,iBAAU,eAAe,gBAAK,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,OAAG;QACtF,iBAAU,QAAQ,gBAAK,IAAI,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,OAAG;QAC7E,iBAAU,WAAW,gBAAK,IAAI,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,OAAG;QAC1E,iBAAU,YAAY,gBAAK,IAAI,GAAG,YAAY,GAAG,MAAM,GAAG,eAAe,GAAG,WAAW,OAAG;QAC1F,iBAAU,eAAe,gBAAK,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,OAAG;QACtF,iBAAU,WAAW,gBAAK,IAAI,GAAG,WAAW,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,OAAG;QAClG,iBAAU,cAAc,gBAAK,IAAI,GAAG,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,OAAG;QACnF,iBAAU,WAAW,gBAAK,IAAI,GAAG,WAAW,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,OAAG;QAClG,iBAAU,cAAc,gBAAK,IAAI,GAAG,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,OAAG;QACnF,mFAAmF;QACnF,6EAA6E;QAC7E,4DAA4D;QAC5D,mCAAmC;QACnC,IAAI;QACJ,cAAO,cAAc,qLAA8K;QACnM,uBAAe,cAAc,eAAW;QACxC,kDAA0C,cAAc,OAAG;QAC3D,mCAA2B,cAAc,OAAG;QAC5C,WAAW;QACX,MAAM;QACN,MAAM;QACN,gBAAS,cAAc,CAAE;QACzB,uDAAuD;QACvD,uCAAuC;QACvC,oCAAoC;QACpC,oCAAoC;QACpC,8FAA8F;QAC9F,kEAAkE;QAClE,sBAAsB,CAAC,CAAC,CAAC,iEAAyD,sBAAsB,OAAG,CAAC,CAAC,CAAC,EAAE;QAChH,qDAAqD;QACrD,EAAE;KACF,CAAC,MAAM,CAAC,UAAC,IAAI,IAAK,OAAA,IAAI,KAAK,EAAE,EAAX,CAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,SAAgB,iCAAiC;IAChD,OAAO;QACN,qBAAqB;QACrB,QAAQ;QACR,2DAA2D;QAC3D,4BAA4B;QAC5B,6BAA6B;QAC7B,6CAA6C;QAC7C,2CAA2C;QAC3C,0BAA0B;QAC1B,oLAAoL;QACpL,2GAA2G;QAC3G,6FAA6F;QAC7F,6FAA6F;QAC7F,0FAA0F;QAC1F,gGAAgG;QAChG,wIAAwI;QACxI,gHAAgH;QAChH,mGAAmG;QACnG,wDAAwD;QACxD,0FAA0F;QAC1F,MAAM;QACN,0FAA0F;QAC1F,IAAI;QACJ,yHAAyH;QACzH,mCAAmC;QACnC,eAAe;QACf,eAAe;QACf,mBAAmB;QACnB,2BAA2B;QAC3B,kCAAkC;QAClC,iEAAiE;QACjE,MAAM;QACN,eAAe;QACf,kBAAkB;QAClB,6BAA6B;QAC7B,oFAAoF;QACpF,uCAAuC;QACvC,WAAW;QACX,4EAA4E;QAC5E,GAAG;QACH,yBAAyB;QACzB,mBAAmB;QACnB,8BAA8B;QAC9B,iBAAiB;QACjB,yGAAyG;QACzG,0GAA0G;QAC1G,2JAA2J;QAC3J,wBAAwB;QACxB,mCAAmC;QACnC,sBAAsB;QACtB,QAAQ;QACR,WAAW;QACX,GAAG;QACH,uCAAuC;QACvC,0BAA0B;QAC1B,8FAA8F;QAC9F,oFAAoF;QACpF,yFAAyF;QACzF,MAAM;QACN,sBAAsB;QACtB,8DAA8D;QAC9D,YAAY;QACZ,GAAG;QACH,+BAA+B;QAC/B,6EAA6E;QAC7E,oCAAoC;QACpC,kDAAkD;QAClD,sBAAsB;QACtB,uBAAuB;QACvB,QAAQ;QACR,yBAAyB;QACzB,mHAAmH;QACnH,2bAA2b;QAC3b,2CAA2C;QAC3C,wBAAwB;QACxB,UAAU;QACV,2BAA2B;QAC3B,4CAA4C;QAC5C,kCAAkC;QAClC,2BAA2B;QAC3B,6CAA6C;QAC7C,8DAA8D;QAC9D,wBAAwB;QACxB,kEAAkE;QAClE,cAAc;QACd,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,QAAQ;QACR,sCAAsC;QACtC,8CAA8C;QAC9C,mBAAmB;QACnB,iFAAiF;QACjF,oHAAoH;QACpH,UAAU;QACV,2bAA2b;QAC3b,2CAA2C;QAC3C,eAAe;QACf,UAAU;QACV,iCAAiC;QACjC,aAAa;QACb,QAAQ;QACR,GAAG;QACH,aAAa;QACb,2BAA2B;QAC3B,2BAA2B;QAC3B,6BAA6B;QAC7B,6CAA6C;QAC7C,GAAG;QACH,mBAAmB;QACnB,iDAAiD;QACjD,+BAA+B;QAC/B,iCAAiC;QACjC,8BAA8B;QAC9B,kDAAkD;QAClD,wIAAwI;QACxI,6DAA6D;QAC7D,yCAAyC;QACzC,iBAAiB;QACjB,GAAG;QACH,+EAA+E;QAC/E,gCAAgC;QAChC,uCAAuC;QACvC,2EAA2E;QAC3E,uCAAuC;QACvC,mFAAmF;QACnF,gFAAgF;QAChF,YAAY;QACZ,GAAG;QACH,mBAAmB;QACnB,mBAAmB;QACnB,8BAA8B;QAC9B,iMAAiM;QACjM,GAAG;QACH,gCAAgC;QAChC,sCAAsC;QACtC,+DAA+D;QAC/D,oBAAoB;QACpB,0MAA0M;QAC1M,4BAA4B;QAC5B,kIAAkI;QAClI,kCAAkC;QAClC,QAAQ;QACR,QAAQ;QACR,iCAAiC;QACjC,6IAA6I;QAC7I,2BAA2B;QAC3B,+BAA+B;QAC/B,mCAAmC;QACnC,oDAAoD;QACpD,OAAO;QACP,6DAA6D;QAC7D,wEAAwE;QACxE,wIAAwI;QACxI,oBAAoB;QACpB,+EAA+E;QAC/E,kCAAkC;QAClC,mCAAmC;QACnC,wFAAwF;QACxF,QAAQ;QACR,GAAG;QACH,wBAAwB;QACxB,yCAAyC;QACzC,8BAA8B;QAC9B,sMAAsM;QACtM,GAAG;QACH,2BAA2B;QAC3B,4CAA4C;QAC5C,4CAA4C;QAC5C,uCAAuC;QACvC,oEAAoE;QACpE,iCAAiC;QACjC,+DAA+D;QAC/D,kIAAkI;QAClI,gBAAgB;QAChB,QAAQ;QACR,sCAAsC;QACtC,+DAA+D;QAC/D,kIAAkI;QAClI,gBAAgB;QAChB,QAAQ;QACR,aAAa;QACb,QAAQ;QACR,YAAY;QACZ,GAAG;QACH,qBAAqB;QACrB,4CAA4C;QAC5C,uCAAuC;QACvC,2FAA2F;QAC3F,oEAAoE;QACpE,oEAAoE;QACpE,uFAAuF;QACvF,aAAa;QACb,QAAQ;QACR,YAAY;QACZ,GAAG;QACH,gDAAgD;QAChD,0CAA0C;QAC1C,6JAA6J;QAC7J,6BAA6B;QAC7B,6CAA6C;QAC7C,4CAA4C;QAC5C,gLAAgL;QAChL,YAAY;QACZ,MAAM;QACN,IAAI;QACJ,2BAA2B;QAC3B,wCAAwC;QACxC,qBAAqB;QACrB,iJAAiJ;QACjJ,iBAAiB;QACjB,yBAAyB;QACzB,oBAAoB;QACpB,0JAA0J;QAC1J,IAAI;QACJ,gGAAgG;QAChG,sDAAsD;QACtD,8BAA8B;QAC9B,sQAAsQ;QACtQ,mDAAmD;QACnD,mHAAmH;QACnH,mJAAmJ;QACnJ,gHAAgH;QAChH,MAAM;QACN,mJAAmJ;QACnJ,UAAU;QACV,IAAI;QACJ,eAAe;QACf,iBAAiB;QACjB,WAAW;QACX,mBAAmB;QACnB,MAAM;QACN,mEAAmE;QACnE,sDAAsD;QACtD,sDAAsD;QACtD,0JAA0J;QAC1J,YAAY;QACZ,QAAQ;QACR,mIAAmI;QACnI,wGAAwG;QACxG,wGAAwG;QACxG,mLAAmL;QACnL,MAAM;QACN,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAgB,wCAAwC;IACvD,OAAO;QACN,qBAAqB;QACrB,QAAQ;QACR,2DAA2D;QAC3D,4BAA4B;QAC5B,6BAA6B;QAC7B,6CAA6C;QAC7C,2CAA2C;QAC3C,6FAA6F;QAC7F,6FAA6F;QAC7F,0FAA0F;QAC1F,gGAAgG;QAChG,eAAe;QACf,kBAAkB;QAClB,6BAA6B;QAC7B,8CAA8C;QAC9C,oFAAoF;QACpF,uCAAuC;QACvC,WAAW;QACX,4EAA4E;QAC5E,GAAG;QACH,yBAAyB;QACzB,mBAAmB;QACnB,8BAA8B;QAC9B,iBAAiB;QACjB,yGAAyG;QACzG,0GAA0G;QAC1G,2JAA2J;QAC3J,wBAAwB;QACxB,mCAAmC;QACnC,sBAAsB;QACtB,QAAQ;QACR,WAAW;QACX,GAAG;QACH,uCAAuC;QACvC,0BAA0B;QAC1B,8FAA8F;QAC9F,oFAAoF;QACpF,yFAAyF;QACzF,MAAM;QACN,sBAAsB;QACtB,8DAA8D;QAC9D,YAAY;QACZ,GAAG;QACH,2EAA2E;QAC3E,kCAAkC;QAClC,gDAAgD;QAChD,oBAAoB;QACpB,qBAAqB;QACrB,MAAM;QACN,uBAAuB;QACvB,iHAAiH;QACjH,ybAAyb;QACzb,yCAAyC;QACzC,sBAAsB;QACtB,QAAQ;QACR,yBAAyB;QACzB,0CAA0C;QAC1C,gCAAgC;QAChC,yBAAyB;QACzB,2CAA2C;QAC3C,4DAA4D;QAC5D,sBAAsB;QACtB,gEAAgE;QAChE,YAAY;QACZ,UAAU;QACV,MAAM;QACN,WAAW;QACX,MAAM;QACN,8BAA8B;QAC9B,4CAA4C;QAC5C,WAAW;QACX,+EAA+E;QAC/E,kHAAkH;QAClH,QAAQ;QACR,ybAAyb;QACzb,yCAAyC;QACzC,aAAa;QACb,QAAQ;QACR,+BAA+B;QAC/B,WAAW;QACX,MAAM;QACN,wDAAwD;QACxD,mEAAmE;QACnE,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAgB,4CAA4C;IAC3D,OAAO;QACN,qBAAqB;QACrB,QAAQ;QACR,2DAA2D;QAC3D,4BAA4B;QAC5B,uBAAuB;QACvB,iCAAiC;QACjC,yEAAyE;QACzE,UAAU;QACV,IAAI;QACJ,eAAe;QACf,iHAAiH;QACjH,8BAA8B;QAC9B,wCAAwC;QACxC,MAAM;QACN,8CAA8C;QAC9C,6CAA6C;QAC7C,IAAI;QACJ,wCAAwC;QACxC,yBAAyB;QACzB,yEAAyE;QACzE,UAAU;QACV,IAAI;QACJ,6CAA6C;QAC7C,iEAAiE;QACjE,qIAAqI;QACrI,4DAA4D;QAC5D,0EAA0E;QAC1E,+BAA+B;QAC/B,sEAAsE;QACtE,eAAe;QACf,MAAM;QACN,IAAI;QACJ,2CAA2C;QAC3C,6DAA6D;QAC7D,2DAA2D;QAC3D,wDAAwD;QACxD,uDAAuD;QACvD,wFAAwF;QACxF,mBAAmB;QACnB,uCAAuC;QACvC,kBAAkB;QAClB,mBAAmB;QACnB,sDAAsD;QACtD,GAAG;QACH,gBAAgB;QAChB,yDAAyD;QACzD,2BAA2B;QAC3B,yHAAyH;QACzH,mBAAmB;QACnB,WAAW;QACX,8BAA8B;QAC9B,gCAAgC;QAChC,wBAAwB;QACxB,6CAA6C;QAC7C,+CAA+C;QAC/C,kFAAkF;QAClF,kDAAkD;QAClD,gDAAgD;QAChD,SAAS;QACT,8FAA8F;QAC9F,wCAAwC;QACxC,IAAI;QACJ,2DAA2D;QAC3D,gDAAgD;QAChD,sBAAsB;QACtB,GAAG;QACH,8BAA8B;QAC9B,oBAAoB;QACpB,mCAAmC;QACnC,oPAAoP;QACpP,+EAA+E;QAC/E,QAAQ;QACR,GAAG;QACH,6BAA6B;QAC7B,0BAA0B;QAC1B,qFAAqF;QACrF,8FAA8F;QAC9F,GAAG;QACH,+BAA+B;QAC/B,kBAAkB;QAClB,yDAAyD;QACzD,GAAG;QACH,uBAAuB;QACvB,iBAAiB;QACjB,sDAAsD;QACtD,sCAAsC;QACtC,8EAA8E;QAC9E,MAAM;QACN,GAAG;QACH,6BAA6B;QAC7B,eAAe;QACf,oBAAoB;QACpB,0BAA0B;QAC1B,iBAAiB;QACjB,6CAA6C;QAC7C,8CAA8C;QAC9C,kEAAkE;QAClE,mEAAmE;QACnE,mCAAmC;QACnC,+NAA+N;QAC/N,gNAAgN;QAChN,UAAU;QACV,4FAA4F;QAC5F,+BAA+B;QAC/B,UAAU;QACV,qCAAqC;QACrC,iBAAiB;QACjB,gBAAgB;QAChB,GAAG;QACH,kFAAkF;QAClF,yBAAyB;QACzB,eAAe;QACf,qEAAqE;QACrE,2CAA2C;QAC3C,oBAAoB;QACpB,oBAAoB;QACpB,qFAAqF;QACrF,mBAAmB;QACnB,qBAAqB;QACrB,qBAAqB;QACrB,qEAAqE;QACrE,iBAAiB;QACjB,wEAAwE;QACxE,wCAAwC;QACxC,8CAA8C;QAC9C,iGAAiG;QACjG,MAAM;QACN,kCAAkC;QAClC,2CAA2C;QAC3C,IAAI;QACJ,iHAAiH;QACjH,uDAAuD;QACvD,kCAAkC;QAClC,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAgB,iCAAiC,CAAC,OAAgD;IAAhD,wBAAA,EAAA,YAAgD;IACjG,IAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC;IACtC,IAAM,QAAQ,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,4BAA4B,CAAC;IAChG,IAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACzD,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChD,IAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC/C,IAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,OAAO;QACN,sBAAe,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,oBAAiB;QAC5E,EAAE;QACF,2IAA2I;QAC3I,EAAE;QACF,SAAS;QACT,iBAAU,QAAQ,YAAS;QAC3B,UAAG,QAAQ,oCAAiC;QAC5C,eAAQ,QAAQ,uDAAoD;QACpE,UAAG,QAAQ,0FAAuF;QAClG,KAAK;QACL,EAAE;QACF,yDAAkD,IAAI,qBAAY,YAAY,wCAAsC;QACpH,0LAA0L;QAC1L,8SAA8S;QAC9S,qEAA+D,YAAY,mBAAS,QAAQ,4DAAoD,YAAY,yFAAuF;QACnP,wJAAwJ;QACxJ,4IAA4I;QAC5I,iSAAiS;QACjS,gBAAU,WAAW,qBAAa,WAAW,+FAA6F;QAC1I,oMAAoM;QACpM,IAAI,KAAK,SAAS;YACjB,CAAC,CAAC,oKAAoK;YACtK,CAAC,CAAC,EAAE;QACL,EAAE;KACF,CAAC,MAAM,CAAC,UAAC,IAAI,IAAK,OAAA,IAAI,KAAK,EAAE,EAAX,CAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC","file":"ai-runner-qa-tools.js","sourcesContent":["export interface ResolveIORunnerQaToolBundleOptions {\n\tmode?: 'support' | 'runner';\n\tqaClientPort?: number | string;\n\tdefaultUsername?: string;\n\tdefaultPassword?: string;\n\ttoolsBinPath?: string;\n\tbrowserslistPath?: string;\n\tmongodbBinaryCachePath?: string;\n\ttmpRoot?: string;\n\thomeRoot?: string;\n}\n\nfunction shellDoubleQuote(value: string): string {\n\treturn String(value || '').replace(/[\"\\\\$`]/g, '\\\\$&');\n}\n\nfunction normalizePort(value: number | string | undefined, fallback: string): string {\n\tconst parsed = Number.parseInt(String(value || ''), 10);\n\treturn Number.isFinite(parsed) && parsed > 0 ? String(parsed) : fallback;\n}\n\nfunction envVar(mode: 'support' | 'runner', suffix: string): string {\n\treturn mode === 'support' ? `RESOLVEIO_SUPPORT_QA_${suffix}` : `RESOLVEIO_RUNNER_QA_${suffix}`;\n}\n\nexport function buildResolveIORunnerQaEnvScript(options: ResolveIORunnerQaToolBundleOptions = {}): string {\n\tconst mode = options.mode || 'runner';\n\tconst altMode = mode === 'support' ? 'runner' : 'support';\n\tconst tmpRoot = options.tmpRoot || (mode === 'support' ? '/tmp/resolveio-support-qa' : '/tmp/resolveio-ai-runner-qa');\n\tconst homeRoot = options.homeRoot || `${tmpRoot}/home`;\n\tconst defaultPort = normalizePort(options.qaClientPort, '4200');\n\tconst username = shellDoubleQuote(options.defaultUsername || 'admin');\n\tconst password = shellDoubleQuote(options.defaultPassword || '');\n\tconst toolsBinPath = options.toolsBinPath || '';\n\tconst browserslistPath = options.browserslistPath || '';\n\tconst mongodbBinaryCachePath = options.mongodbBinaryCachePath || '';\n\tconst clientPortVar = envVar(mode, 'CLIENT_PORT');\n\tconst altClientPortVar = envVar(altMode, 'CLIENT_PORT');\n\tconst clientUrlVar = envVar(mode, 'CLIENT_URL');\n\tconst altClientUrlVar = envVar(altMode, 'CLIENT_URL');\n\tconst serverUrlVar = envVar(mode, 'SERVER_URL');\n\tconst altServerUrlVar = envVar(altMode, 'SERVER_URL');\n\tconst usernameVar = envVar(mode, 'USERNAME');\n\tconst altUsernameVar = envVar(altMode, 'USERNAME');\n\tconst passwordVar = envVar(mode, 'PASSWORD');\n\tconst altPasswordVar = envVar(altMode, 'PASSWORD');\n\tconst viewportWidthVar = envVar(mode, 'VIEWPORT_WIDTH');\n\tconst altViewportWidthVar = envVar(altMode, 'VIEWPORT_WIDTH');\n\tconst viewportHeightVar = envVar(mode, 'VIEWPORT_HEIGHT');\n\tconst altViewportHeightVar = envVar(altMode, 'VIEWPORT_HEIGHT');\n\tconst timeoutVar = envVar(mode, 'ANGULAR_STARTUP_TIMEOUT_SECONDS');\n\tconst altTimeoutVar = envVar(altMode, 'ANGULAR_STARTUP_TIMEOUT_SECONDS');\n\tconst prebundleVar = envVar(mode, 'ANGULAR_PREBUNDLE');\n\tconst altPrebundleVar = envVar(altMode, 'ANGULAR_PREBUNDLE');\n\tconst reuseVar = envVar(mode, 'REUSE_RUNNING');\n\tconst altReuseVar = envVar(altMode, 'REUSE_RUNNING');\n\tconst keepaliveVar = envVar(mode, 'KEEPALIVE');\n\tconst altKeepaliveVar = envVar(altMode, 'KEEPALIVE');\n\tconst browserLoopVar = mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_BROWSER' : 'RESOLVEIO_RUNNER_QA_BROWSER';\n\treturn [\n\t\t`export ${mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP'}=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP') + ':-' + tmpRoot + '}'}\"`,\n\t\t`export ${mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME'}=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME') + ':-' + homeRoot + '}'}\"`,\n\t\t`RESOLVEIO_QA_TMP=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_TMP' : 'RESOLVEIO_RUNNER_QA_TMP') + '}'}\"`,\n\t\t`RESOLVEIO_QA_HOME=\"${'${' + (mode === 'support' ? 'RESOLVEIO_SUPPORT_QA_HOME' : 'RESOLVEIO_RUNNER_QA_HOME') + '}'}\"`,\n\t\t'mkdir -p \"$RESOLVEIO_QA_HOME/.nvm\" \"$RESOLVEIO_QA_TMP/npm-cache\" \"$RESOLVEIO_QA_TMP/mongodb-binaries\" \"$RESOLVEIO_QA_TMP/mongodb-memory-server-core\"',\n\t\t'if [ ! -f \"$RESOLVEIO_QA_HOME/.nvm/nvm.sh\" ]; then',\n\t\t' cat > \"$RESOLVEIO_QA_HOME/.nvm/nvm.sh\" <<\\'RESOLVEIO_NVM_SHIM\\'',\n\t\t'nvm() {',\n\t\t' case \"$1\" in',\n\t\t' use|install|alias) return 0 ;;',\n\t\t' current) node -v 2>/dev/null || true; return 0 ;;',\n\t\t' *) return 0 ;;',\n\t\t' esac',\n\t\t'}',\n\t\t'RESOLVEIO_NVM_SHIM',\n\t\t'fi',\n\t\t'export HOME=\"$RESOLVEIO_QA_HOME\"',\n\t\t'export NVM_DIR=\"$RESOLVEIO_QA_HOME/.nvm\"',\n\t\ttoolsBinPath ? `export PATH=\"${toolsBinPath}:$PATH\"` : '',\n\t\t'export NODE_ENV=development',\n\t\tbrowserslistPath ? `export BROWSERSLIST_CONFIG=\"${browserslistPath}\"` : '',\n\t\t`export ${clientPortVar}=\"${'${' + clientPortVar + ':-${' + altClientPortVar + ':-' + defaultPort + '}}'}\"`,\n\t\t`export ${altClientPortVar}=\"${'${' + altClientPortVar + ':-${' + clientPortVar + '}}'}\"`,\n\t\t`export ${clientUrlVar}=\"${'${' + clientUrlVar + ':-${' + altClientUrlVar + ':-http://localhost:${' + clientPortVar + '}}}'}\"`,\n\t\t`export ${altClientUrlVar}=\"${'${' + altClientUrlVar + ':-${' + clientUrlVar + '}}'}\"`,\n\t\t`export ${serverUrlVar}=\"${'${' + serverUrlVar + ':-${' + altServerUrlVar + ':-http://localhost:8080}}'}\"`,\n\t\t`export ${altServerUrlVar}=\"${'${' + altServerUrlVar + ':-${' + serverUrlVar + '}}'}\"`,\n\t\t'export ADDITIONAL_ALLOWED_ORIGINS=\"${ADDITIONAL_ALLOWED_ORIGINS:-$' + clientUrlVar + '}\"',\n\t\t`export ${viewportWidthVar}=\"${'${' + viewportWidthVar + ':-${' + altViewportWidthVar + ':-1920}}'}\"`,\n\t\t`export ${altViewportWidthVar}=\"${'${' + altViewportWidthVar + ':-${' + viewportWidthVar + '}}'}\"`,\n\t\t`export ${viewportHeightVar}=\"${'${' + viewportHeightVar + ':-${' + altViewportHeightVar + ':-1080}}'}\"`,\n\t\t`export ${altViewportHeightVar}=\"${'${' + altViewportHeightVar + ':-${' + viewportHeightVar + '}}'}\"`,\n\t\t`export ${timeoutVar}=\"${'${' + timeoutVar + ':-${' + altTimeoutVar + ':-900}}'}\"`,\n\t\t`export ${altTimeoutVar}=\"${'${' + altTimeoutVar + ':-${' + timeoutVar + '}}'}\"`,\n\t\t`export ${prebundleVar}=\"${'${' + prebundleVar + ':-${' + altPrebundleVar + ':-false}}'}\"`,\n\t\t`export ${altPrebundleVar}=\"${'${' + altPrebundleVar + ':-${' + prebundleVar + '}}'}\"`,\n\t\t`export ${reuseVar}=\"${'${' + reuseVar + ':-${' + altReuseVar + ':-true}}'}\"`,\n\t\t`export ${altReuseVar}=\"${'${' + altReuseVar + ':-${' + reuseVar + '}}'}\"`,\n\t\t`export ${keepaliveVar}=\"${'${' + keepaliveVar + ':-${' + altKeepaliveVar + ':-false}}'}\"`,\n\t\t`export ${altKeepaliveVar}=\"${'${' + altKeepaliveVar + ':-${' + keepaliveVar + '}}'}\"`,\n\t\t`export ${usernameVar}=\"${'${' + usernameVar + ':-${' + altUsernameVar + ':-' + username + '}}'}\"`,\n\t\t`export ${altUsernameVar}=\"${'${' + altUsernameVar + ':-${' + usernameVar + '}}'}\"`,\n\t\t`export ${passwordVar}=\"${'${' + passwordVar + ':-${' + altPasswordVar + ':-' + password + '}}'}\"`,\n\t\t`export ${altPasswordVar}=\"${'${' + altPasswordVar + ':-${' + passwordVar + '}}'}\"`,\n\t\t'export PUPPETEER_CACHE_DIR=\"${PUPPETEER_CACHE_DIR:-/var/lib/resolveio/puppeteer}\"',\n\t\t'if [ ! -d \"$PUPPETEER_CACHE_DIR\" ] || [ ! -w \"$PUPPETEER_CACHE_DIR\" ]; then',\n\t\t' export PUPPETEER_CACHE_DIR=\"$RESOLVEIO_QA_TMP/puppeteer\"',\n\t\t' mkdir -p \"$PUPPETEER_CACHE_DIR\"',\n\t\t'fi',\n\t\t`for ${browserLoopVar} in \"$PUPPETEER_CACHE_DIR\"/chrome-headless-shell/linux-*/chrome-headless-shell-linux64/chrome-headless-shell \"$PUPPETEER_CACHE_DIR\"/chrome/linux-*/chrome-linux64/chrome; do`,\n\t\t` if [ -x \"$${browserLoopVar}\" ]; then`,\n\t\t` export PUPPETEER_EXECUTABLE_PATH=\"$${browserLoopVar}\"`,\n\t\t` export CHROME_BIN=\"$${browserLoopVar}\"`,\n\t\t' break',\n\t\t' fi',\n\t\t'done',\n\t\t`unset ${browserLoopVar}`,\n\t\t'export NPM_CONFIG_CACHE=\"$RESOLVEIO_QA_TMP/npm-cache\"',\n\t\t'export NPM_CONFIG_PREFER_OFFLINE=true',\n\t\t'export NPM_CONFIG_PRODUCTION=false',\n\t\t'export npm_config_production=false',\n\t\t'export RESOLVEIO_SUPPORT_MONGOMS_PACKAGE_ROOT=\"$RESOLVEIO_QA_TMP/mongodb-memory-server-core\"',\n\t\t'export MONGOMS_DOWNLOAD_DIR=\"$RESOLVEIO_QA_TMP/mongodb-binaries\"',\n\t\tmongodbBinaryCachePath ? `export RESOLVEIO_SUPPORT_SHARED_MONGOMS_DOWNLOAD_DIR=\"${mongodbBinaryCachePath}\"` : '',\n\t\t'export MONGOMS_VERSION=\"${MONGOMS_VERSION:-7.0.14}\"',\n\t\t''\n\t].filter((line) => line !== '').join('\\n');\n}\n\nexport function buildResolveIORunnerLocalQaScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-$(pwd)}\"',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'mkdir -p \"$ARTIFACT_DIR\"',\n\t\t'CLIENT_URL=\"${RESOLVEIO_RUNNER_QA_CLIENT_URL:-${RESOLVEIO_SUPPORT_QA_CLIENT_URL:-http://localhost:${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}}}\"',\n\t\t'SERVER_URL=\"${RESOLVEIO_RUNNER_QA_SERVER_URL:-${RESOLVEIO_SUPPORT_QA_SERVER_URL:-http://localhost:8080}}\"',\n\t\t'CLIENT_PORT=\"${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}\"',\n\t\t'SERVER_PORT=\"${RESOLVEIO_RUNNER_QA_SERVER_PORT:-${RESOLVEIO_SUPPORT_QA_SERVER_PORT:-8080}}\"',\n\t\t'MONGO_PORT=\"${RESOLVEIO_RUNNER_QA_MONGO_PORT:-${RESOLVEIO_SUPPORT_QA_MONGO_PORT:-3001}}\"',\n\t\t'INSPECT_PORT=\"${RESOLVEIO_RUNNER_QA_INSPECT_PORT:-${RESOLVEIO_SUPPORT_QA_INSPECT_PORT:-9229}}\"',\n\t\t'STARTUP_TIMEOUT=\"${RESOLVEIO_RUNNER_QA_ANGULAR_STARTUP_TIMEOUT_SECONDS:-${RESOLVEIO_SUPPORT_QA_ANGULAR_STARTUP_TIMEOUT_SECONDS:-900}}\"',\n\t\t'ANGULAR_PREBUNDLE=\"${RESOLVEIO_RUNNER_QA_ANGULAR_PREBUNDLE:-${RESOLVEIO_SUPPORT_QA_ANGULAR_PREBUNDLE:-false}}\"',\n\t\t'REUSE_RUNNING=\"${RESOLVEIO_RUNNER_QA_REUSE_RUNNING:-${RESOLVEIO_SUPPORT_QA_REUSE_RUNNING:-true}}\"',\n\t\t'if [[ \"$(basename \"$TOOLS_DIR\")\" == *support* ]]; then',\n\t\t' KEEPALIVE=\"${RESOLVEIO_SUPPORT_QA_KEEPALIVE:-${RESOLVEIO_RUNNER_QA_KEEPALIVE:-false}}\"',\n\t\t'else',\n\t\t' KEEPALIVE=\"${RESOLVEIO_RUNNER_QA_KEEPALIVE:-${RESOLVEIO_SUPPORT_QA_KEEPALIVE:-false}}\"',\n\t\t'fi',\n\t\t'SERVER_STABLE_SECONDS=\"${RESOLVEIO_RUNNER_QA_SERVER_STABLE_SECONDS:-${RESOLVEIO_SUPPORT_QA_SERVER_STABLE_SECONDS:-20}}\"',\n\t\t'LOCK_DIR=\"$ARTIFACT_DIR/.qa.lock\"',\n\t\t'SERVER_PID=\"\"',\n\t\t'CLIENT_PID=\"\"',\n\t\t'SERVER_REQUIRED=0',\n\t\t'ANGULAR_PREBUNDLE_ARGS=()',\n\t\t'case \"${ANGULAR_PREBUNDLE,,}\" in',\n\t\t' false|0|no|off) ANGULAR_PREBUNDLE_ARGS=(--prebundle=false) ;;',\n\t\t'esac',\n\t\t'kill_tree() {',\n\t\t' local pid=\"$1\"',\n\t\t' [ -n \"$pid\" ] || return 0',\n\t\t' for child in $(pgrep -P \"$pid\" 2>/dev/null || true); do kill_tree \"$child\"; done',\n\t\t' kill \"$pid\" >/dev/null 2>&1 || true',\n\t\t' sleep 1',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 && kill -9 \"$pid\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'kill_port_listeners() {',\n\t\t' local port=\"$1\"',\n\t\t' [ -n \"$port\" ] || return 0',\n\t\t' local pids=\"\"',\n\t\t' if command -v lsof >/dev/null 2>&1; then pids=\"$pids $(lsof -ti tcp:\"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v fuser >/dev/null 2>&1; then pids=\"$pids $(fuser -n tcp \"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v ss >/dev/null 2>&1; then pids=\"$pids $(ss -ltnp \"sport = :$port\" 2>/dev/null | sed -n \\'s/.*pid=\\\\([0-9][0-9]*\\\\).*/\\\\1/p\\' || true)\"; fi',\n\t\t' for pid in $pids; do',\n\t\t' [ \"$pid\" = \"$$\" ] && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' sleep 1',\n\t\t'}',\n\t\t'RUNNER_ANCESTOR_PIDS=\" $$ ${PPID:-} \"',\n\t\t'ancestor_pid=\"${PPID:-}\"',\n\t\t'while [ -n \"$ancestor_pid\" ] && [ \"$ancestor_pid\" != \"0\" ] && [ \"$ancestor_pid\" != \"1\" ]; do',\n\t\t' ancestor_pid=\"$(ps -o ppid= -p \"$ancestor_pid\" 2>/dev/null | tr -d \" \" || true)\"',\n\t\t' [ -n \"$ancestor_pid\" ] && RUNNER_ANCESTOR_PIDS=\"$RUNNER_ANCESTOR_PIDS $ancestor_pid \"',\n\t\t'done',\n\t\t'skip_cleanup_pid() {',\n\t\t' case \"$RUNNER_ANCESTOR_PIDS\" in *\" $1 \"*) return 0 ;; esac',\n\t\t' return 1',\n\t\t'}',\n\t\t'cleanup_project_processes() {',\n\t\t' for pid_file in \"$ARTIFACT_DIR/server.pid\" \"$ARTIFACT_DIR/client.pid\"; do',\n\t\t' [ -f \"$pid_file\" ] || continue',\n\t\t' pid=\"$(cat \"$pid_file\" 2>/dev/null || true)\"',\n\t\t' kill_tree \"$pid\"',\n\t\t' rm -f \"$pid_file\"',\n\t\t' done',\n\t\t' for pass in 1 2 3; do',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do kill_port_listeners \"$port\"; done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\\\.sh|stop-local-qa\\\\.sh|bugfix-comparison-qa\\\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' if [ -d /proc ]; then',\n\t\t' for proc_cwd in /proc/[0-9]*/cwd; do',\n\t\t' pid=\"${proc_cwd#/proc/}\"',\n\t\t' pid=\"${pid%/cwd}\"',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' cwd=\"$(readlink -f \"$proc_cwd\" 2>/dev/null || true)\"',\n\t\t' case \"$cwd\" in',\n\t\t' \"$PROJECT_ROOT\"|\"$PROJECT_ROOT\"/*) kill_tree \"$pid\" ;;',\n\t\t' esac',\n\t\t' done',\n\t\t' fi',\n\t\t' sleep 1',\n\t\t' done',\n\t\t' local wait_until=$((SECONDS + 60))',\n\t\t' while [ \"$SECONDS\" -lt \"$wait_until\" ]; do',\n\t\t' local found=0',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do',\n\t\t' if command -v lsof >/dev/null 2>&1 && [ -n \"$(lsof -ti tcp:\"$port\" 2>/dev/null || true)\" ]; then found=1; fi',\n\t\t' done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\\\.sh|stop-local-qa\\\\.sh|bugfix-comparison-qa\\\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' found=1',\n\t\t' done',\n\t\t' [ \"$found\" = \"0\" ] && break',\n\t\t' sleep 2',\n\t\t' done',\n\t\t'}',\n\t\t'cleanup() {',\n\t\t' kill_tree \"$SERVER_PID\"',\n\t\t' kill_tree \"$CLIENT_PID\"',\n\t\t' cleanup_project_processes',\n\t\t' rmdir \"$LOCK_DIR\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'trap cleanup EXIT',\n\t\t'probe_url() { node - \"$1\" <<\\'RESOLVEIO_PROBE\\'',\n\t\t'const http = require(\"http\");',\n\t\t'const https = require(\"https\");',\n\t\t'const url = process.argv[2];',\n\t\t'const mod = /^https:/i.test(url) ? https : http;',\n\t\t'const req = mod.get(url, { timeout: 2500 }, (res) => { res.resume(); process.exit(res.statusCode && res.statusCode < 500 ? 0 : 1); });',\n\t\t'req.on(\"timeout\", () => req.destroy(new Error(\"timeout\")));',\n\t\t'req.on(\"error\", () => process.exit(1));',\n\t\t'RESOLVEIO_PROBE',\n\t\t'}',\n\t\t'truthy() { case \"${1,,}\" in true|1|yes|on) return 0 ;; *) return 1 ;; esac; }',\n\t\t'reuse_running_app_if_ready() {',\n\t\t' truthy \"$REUSE_RUNNING\" || return 1',\n\t\t' [ -d \"$PROJECT_ROOT/server\" ] && SERVER_REQUIRED=1 || SERVER_REQUIRED=0',\n\t\t' probe_url \"$CLIENT_URL\" || return 1',\n\t\t' if [ \"$SERVER_REQUIRED\" = \"1\" ] && ! probe_url \"$SERVER_URL\"; then return 1; fi',\n\t\t' echo \"ResolveIO AI runner QA reusing already-ready local app at $CLIENT_URL\"',\n\t\t' return 0',\n\t\t'}',\n\t\t'log_has_fatal() {',\n\t\t' local file=\"$1\"',\n\t\t' [ -f \"$file\" ] || return 1',\n\t\t' grep -Eiq \"Unhandled Rejection|Cannot read properties of undefined|TypeError|ReferenceError|EADDRINUSE|app crashed|Failed to compile|Error: Cannot find module|NG[0-9]{4}|TS[0-9]{4}\" \"$file\"',\n\t\t'}',\n\t\t'prepare_angular_cache_dirs() {',\n\t\t' [ -d \"$PROJECT_ROOT\" ] || return 0',\n\t\t' mkdir -p \"$PROJECT_ROOT/.angular/cache\" 2>/dev/null || true',\n\t\t' local version=\"\"',\n\t\t' for pkg in \"$PROJECT_ROOT/node_modules/@angular/build/package.json\" \"$PROJECT_ROOT/node_modules/@angular/cli/package.json\" \"$PROJECT_ROOT/node_modules/@angular-devkit/build-angular/package.json\"; do',\n\t\t' if [ -f \"$pkg\" ]; then',\n\t\t' version=\"$(node -e \"try{console.log(require(process.argv[1]).version||\\\\\\\"\\\\\\\")}catch(e){}\" \"$pkg\" 2>/dev/null | head -1)\"',\n\t\t' [ -n \"$version\" ] && break',\n\t\t' fi',\n\t\t' done',\n\t\t' [ -n \"$version\" ] || return 0',\n\t\t' node - \"$PROJECT_ROOT/angular.json\" \"$(basename \"$PROJECT_ROOT\")\" <<\\'RESOLVEIO_ANGULAR_CACHE_PROJECTS\\' | while IFS= read -r project; do',\n\t\t'const fs = require(\"fs\");',\n\t\t'const path = process.argv[2];',\n\t\t'const fallback = process.argv[3];',\n\t\t'const names = new Set([fallback].filter(Boolean));',\n\t\t'try {',\n\t\t' const parsed = JSON.parse(fs.readFileSync(path, \"utf8\"));',\n\t\t' if (parsed.defaultProject) names.add(String(parsed.defaultProject));',\n\t\t' if (parsed.projects && typeof parsed.projects === \"object\") Object.keys(parsed.projects).forEach((name) => names.add(String(name)));',\n\t\t'} catch (error) {}',\n\t\t'for (const name of names) console.log(name.replace(/[^A-Za-z0-9._-]/g, \"_\"));',\n\t\t'RESOLVEIO_ANGULAR_CACHE_PROJECTS',\n\t\t' [ -n \"$project\" ] || continue',\n\t\t' mkdir -p \"$PROJECT_ROOT/.angular/cache/$version/$project/vite\" 2>/dev/null || true',\n\t\t' done',\n\t\t'}',\n\t\t'server_has_started() {',\n\t\t' local file=\"$ARTIFACT_DIR/server.log\"',\n\t\t' [ -f \"$file\" ] || return 1',\n\t\t' grep -Eiq \"nodemon.*starting|node .*tmp/index\\\\.js|Running as Worker|Standalone Node Reaper|listening on|server listening|Server listening|app listening|App listening|Finished .default.\" \"$file\"',\n\t\t'}',\n\t\t'wait_for_server_ready() {',\n\t\t' [ \"$SERVER_REQUIRED\" = \"1\" ] || return 0',\n\t\t' local end=$((SECONDS + STARTUP_TIMEOUT))',\n\t\t' while [ \"$SECONDS\" -lt \"$end\" ]; do',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi',\n\t\t' if server_has_started; then',\n\t\t' local stable_until=$((SECONDS + SERVER_STABLE_SECONDS))',\n\t\t' while [ \"$SECONDS\" -lt \"$stable_until\" ]; do if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi; sleep 2; done',\n\t\t' return 0',\n\t\t' fi',\n\t\t' if probe_url \"$SERVER_URL\"; then',\n\t\t' local stable_until=$((SECONDS + SERVER_STABLE_SECONDS))',\n\t\t' while [ \"$SECONDS\" -lt \"$stable_until\" ]; do if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi; sleep 2; done',\n\t\t' return 0',\n\t\t' fi',\n\t\t' sleep 5',\n\t\t' done',\n\t\t' return 4',\n\t\t'}',\n\t\t'wait_for_client() {',\n\t\t' local end=$((SECONDS + STARTUP_TIMEOUT))',\n\t\t' while [ \"$SECONDS\" -lt \"$end\" ]; do',\n\t\t' if [ -n \"$CLIENT_PID\" ] && ! kill -0 \"$CLIENT_PID\" >/dev/null 2>&1; then return 2; fi',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/client.log\"; then return 3; fi',\n\t\t' if log_has_fatal \"$ARTIFACT_DIR/server.log\"; then return 4; fi',\n\t\t' if probe_url \"$CLIENT_URL\"; then wait_for_server_ready || return $?; return 0; fi',\n\t\t' sleep 5',\n\t\t' done',\n\t\t' return 1',\n\t\t'}',\n\t\t'if reuse_running_app_if_ready; then exit 0; fi',\n\t\t'if ! mkdir \"$LOCK_DIR\" 2>/dev/null; then',\n\t\t' echo \"ResolveIO AI runner QA lock is already held for $PROJECT_ROOT; cleaning stale local QA processes before retrying.\" | tee \"$ARTIFACT_DIR/runner.log\"',\n\t\t' cleanup_project_processes',\n\t\t' rmdir \"$LOCK_DIR\" >/dev/null 2>&1 || true',\n\t\t' if ! mkdir \"$LOCK_DIR\" 2>/dev/null; then',\n\t\t' echo \"ResolveIO AI runner QA lock is still held for $PROJECT_ROOT after cleanup. Stop the existing QA runner before starting another.\" | tee -a \"$ARTIFACT_DIR/runner.log\"',\n\t\t' exit 6',\n\t\t' fi',\n\t\t'fi',\n\t\t'cleanup_project_processes',\n\t\t'if [ -d \"$PROJECT_ROOT/server\" ]; then',\n\t\t' SERVER_REQUIRED=1',\n\t\t' (cd \"$PROJECT_ROOT/server\" && source \"$TOOLS_DIR/env.sh\" && { npm run server || ./start_server.sh; } 2>&1 | tee \"$ARTIFACT_DIR/server.log\") &',\n\t\t' SERVER_PID=$!',\n\t\t' wait_for_server_ready',\n\t\t' SERVER_RESULT=$?',\n\t\t' if [ \"$SERVER_RESULT\" != \"0\" ]; then echo \"ResolveIO AI runner QA server startup fatal error. See $ARTIFACT_DIR/server.log\"; exit \"$SERVER_RESULT\"; fi',\n\t\t'fi',\n\t\t'CLIENT_HOST=\"${RESOLVEIO_RUNNER_QA_CLIENT_HOST:-${RESOLVEIO_SUPPORT_QA_CLIENT_HOST:-0.0.0.0}}\"',\n\t\t'if [ -x \"$PROJECT_ROOT/node_modules/.bin/ng\" ]; then',\n\t\t' prepare_angular_cache_dirs',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && node --max_old_space_size=8048 ./node_modules/.bin/ng serve --watch --configuration local --host \"$CLIENT_HOST\" --port \"$CLIENT_PORT\" \"${ANGULAR_PREBUNDLE_ARGS[@]}\" 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'elif [ -x \"$PROJECT_ROOT/start_client.sh\" ]; then',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && ./start_client.sh 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'elif node -e \"const p=require(process.argv[1]); process.exit(p.scripts&&p.scripts.client?0:1)\" \"$PROJECT_ROOT/package.json\" >/dev/null 2>&1; then',\n\t\t' (cd \"$PROJECT_ROOT\" && source \"$TOOLS_DIR/env.sh\" && npm run client 2>&1 | tee \"$ARTIFACT_DIR/client.log\") &',\n\t\t'else',\n\t\t' echo \"ResolveIO AI runner QA cannot find Angular CLI, start_client.sh, or npm client script for $PROJECT_ROOT\" | tee \"$ARTIFACT_DIR/client.log\"',\n\t\t' exit 5',\n\t\t'fi',\n\t\t'CLIENT_PID=$!',\n\t\t'wait_for_client',\n\t\t'RESULT=$?',\n\t\t'case \"$RESULT\" in',\n\t\t' 0)',\n\t\t' echo \"ResolveIO AI runner QA local app ready at $CLIENT_URL\";',\n\t\t' echo \"$SERVER_PID\" > \"$ARTIFACT_DIR/server.pid\";',\n\t\t' echo \"$CLIENT_PID\" > \"$ARTIFACT_DIR/client.pid\";',\n\t\t' if truthy \"$KEEPALIVE\"; then echo \"ResolveIO AI runner QA keepalive enabled; server/client remain running until this process is stopped.\"; wait; fi;',\n\t\t' exit 0',\n\t\t' ;;',\n\t\t' 2) echo \"ResolveIO AI runner QA client process exited before $CLIENT_URL became ready. See $ARTIFACT_DIR/client.log\"; exit 2 ;;',\n\t\t' 3) echo \"ResolveIO AI runner QA client startup fatal error. See $ARTIFACT_DIR/client.log\"; exit 3 ;;',\n\t\t' 4) echo \"ResolveIO AI runner QA server startup fatal error. See $ARTIFACT_DIR/server.log\"; exit 4 ;;',\n\t\t' *) echo \"ResolveIO AI runner QA local app did not become ready at $CLIENT_URL within ${STARTUP_TIMEOUT}s. See $ARTIFACT_DIR/client.log and $ARTIFACT_DIR/server.log\"; exit 1 ;;',\n\t\t'esac',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerLocalQaStopperScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-$(pwd)}\"',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'CLIENT_PORT=\"${RESOLVEIO_RUNNER_QA_CLIENT_PORT:-${RESOLVEIO_SUPPORT_QA_CLIENT_PORT:-4200}}\"',\n\t\t'SERVER_PORT=\"${RESOLVEIO_RUNNER_QA_SERVER_PORT:-${RESOLVEIO_SUPPORT_QA_SERVER_PORT:-8080}}\"',\n\t\t'MONGO_PORT=\"${RESOLVEIO_RUNNER_QA_MONGO_PORT:-${RESOLVEIO_SUPPORT_QA_MONGO_PORT:-3001}}\"',\n\t\t'INSPECT_PORT=\"${RESOLVEIO_RUNNER_QA_INSPECT_PORT:-${RESOLVEIO_SUPPORT_QA_INSPECT_PORT:-9229}}\"',\n\t\t'kill_tree() {',\n\t\t' local pid=\"$1\"',\n\t\t' [ -n \"$pid\" ] || return 0',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 || return 0',\n\t\t' for child in $(pgrep -P \"$pid\" 2>/dev/null || true); do kill_tree \"$child\"; done',\n\t\t' kill \"$pid\" >/dev/null 2>&1 || true',\n\t\t' sleep 1',\n\t\t' kill -0 \"$pid\" >/dev/null 2>&1 && kill -9 \"$pid\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'kill_port_listeners() {',\n\t\t' local port=\"$1\"',\n\t\t' [ -n \"$port\" ] || return 0',\n\t\t' local pids=\"\"',\n\t\t' if command -v lsof >/dev/null 2>&1; then pids=\"$pids $(lsof -ti tcp:\"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v fuser >/dev/null 2>&1; then pids=\"$pids $(fuser -n tcp \"$port\" 2>/dev/null || true)\"; fi',\n\t\t' if command -v ss >/dev/null 2>&1; then pids=\"$pids $(ss -ltnp \"sport = :$port\" 2>/dev/null | sed -n \\'s/.*pid=\\\\([0-9][0-9]*\\\\).*/\\\\1/p\\' || true)\"; fi',\n\t\t' for pid in $pids; do',\n\t\t' [ \"$pid\" = \"$$\" ] && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' sleep 1',\n\t\t'}',\n\t\t'RUNNER_ANCESTOR_PIDS=\" $$ ${PPID:-} \"',\n\t\t'ancestor_pid=\"${PPID:-}\"',\n\t\t'while [ -n \"$ancestor_pid\" ] && [ \"$ancestor_pid\" != \"0\" ] && [ \"$ancestor_pid\" != \"1\" ]; do',\n\t\t' ancestor_pid=\"$(ps -o ppid= -p \"$ancestor_pid\" 2>/dev/null | tr -d \" \" || true)\"',\n\t\t' [ -n \"$ancestor_pid\" ] && RUNNER_ANCESTOR_PIDS=\"$RUNNER_ANCESTOR_PIDS $ancestor_pid \"',\n\t\t'done',\n\t\t'skip_cleanup_pid() {',\n\t\t' case \"$RUNNER_ANCESTOR_PIDS\" in *\" $1 \"*) return 0 ;; esac',\n\t\t' return 1',\n\t\t'}',\n\t\t'for pid_file in \"$ARTIFACT_DIR/server.pid\" \"$ARTIFACT_DIR/client.pid\"; do',\n\t\t' [ -f \"$pid_file\" ] || continue',\n\t\t' pid=\"$(cat \"$pid_file\" 2>/dev/null || true)\"',\n\t\t' kill_tree \"$pid\"',\n\t\t' rm -f \"$pid_file\"',\n\t\t'done',\n\t\t'for pass in 1 2 3; do',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do kill_port_listeners \"$port\"; done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\\\.sh|stop-local-qa\\\\.sh|bugfix-comparison-qa\\\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' kill_tree \"$pid\"',\n\t\t' done',\n\t\t' if [ -d /proc ]; then',\n\t\t' for proc_cwd in /proc/[0-9]*/cwd; do',\n\t\t' pid=\"${proc_cwd#/proc/}\"',\n\t\t' pid=\"${pid%/cwd}\"',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' cwd=\"$(readlink -f \"$proc_cwd\" 2>/dev/null || true)\"',\n\t\t' case \"$cwd\" in',\n\t\t' \"$PROJECT_ROOT\"|\"$PROJECT_ROOT\"/*) kill_tree \"$pid\" ;;',\n\t\t' esac',\n\t\t' done',\n\t\t' fi',\n\t\t' sleep 1',\n\t\t'done',\n\t\t'wait_until=$((SECONDS + 60))',\n\t\t'while [ \"$SECONDS\" -lt \"$wait_until\" ]; do',\n\t\t' found=0',\n\t\t' for port in \"$CLIENT_PORT\" \"$SERVER_PORT\" \"$MONGO_PORT\" \"$INSPECT_PORT\"; do',\n\t\t' if command -v lsof >/dev/null 2>&1 && [ -n \"$(lsof -ti tcp:\"$port\" 2>/dev/null || true)\" ]; then found=1; fi',\n\t\t' done',\n\t\t' for pid in $(ps -eo pid=,args= | awk -v root=\"$PROJECT_ROOT\" \\'index($0, root) && $0 !~ /awk -v root=/ && $0 !~ /ps -eo pid=,args=/ && $0 !~ /run-local-qa\\\\.sh|stop-local-qa\\\\.sh|bugfix-comparison-qa\\\\.sh/ && $0 ~ /(ng serve|node .*node_modules\\\\/\\\\.bin\\\\/ng|esbuild|npm run client|start_client\\\\.sh|npm run server|start_server\\\\.sh|nodemon|node .*tmp\\\\/index\\\\.js|mongod|mongodb-binaries\\\\/mongod)/ {print $1}\\' 2>/dev/null || true); do',\n\t\t' skip_cleanup_pid \"$pid\" && continue',\n\t\t' found=1',\n\t\t' done',\n\t\t' [ \"$found\" = \"0\" ] && break',\n\t\t' sleep 2',\n\t\t'done',\n\t\t'rmdir \"$ARTIFACT_DIR/.qa.lock\" >/dev/null 2>&1 || true',\n\t\t'echo \"ResolveIO AI runner QA local app stopped for $PROJECT_ROOT\"',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerBugfixComparisonQaScript(): string {\n\treturn [\n\t\t'#!/usr/bin/env bash',\n\t\t'set -u',\n\t\t'TOOLS_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"',\n\t\t'source \"$TOOLS_DIR/env.sh\"',\n\t\t'PROJECT_ROOT=\"${1:-}\"',\n\t\t'if [ -z \"$PROJECT_ROOT\" ]; then',\n\t\t' echo \"Usage: $0 <project-root> [baseline-ref] -- <qa-command...>\" >&2',\n\t\t' exit 2',\n\t\t'fi',\n\t\t'shift || true',\n\t\t'DEFAULT_BASELINE_REF=\"${RESOLVEIO_RUNNER_QA_BASELINE_REF:-${RESOLVEIO_SUPPORT_QA_BASELINE_REF:-origin/master}}\"',\n\t\t'if [ \"${1:-}\" = \"--\" ]; then',\n\t\t' BASELINE_REF=\"$DEFAULT_BASELINE_REF\"',\n\t\t'else',\n\t\t' BASELINE_REF=\"${1:-$DEFAULT_BASELINE_REF}\"',\n\t\t' if [ \"$#\" -gt 0 ]; then shift || true; fi',\n\t\t'fi',\n\t\t'if [ \"${1:-}\" = \"--\" ]; then shift; fi',\n\t\t'if [ \"$#\" -eq 0 ]; then',\n\t\t' echo \"Usage: $0 <project-root> [baseline-ref] -- <qa-command...>\" >&2',\n\t\t' exit 2',\n\t\t'fi',\n\t\t'PROJECT_ROOT=\"$(cd \"$PROJECT_ROOT\" && pwd)\"',\n\t\t'REPO_ROOT=\"$(git -C \"$PROJECT_ROOT\" rev-parse --show-toplevel)\"',\n\t\t'PROJECT_REL=\"$(git -C \"$REPO_ROOT\" ls-files --full-name \"$PROJECT_ROOT\" 2>/dev/null | head -1 | xargs dirname 2>/dev/null || true)\"',\n\t\t'if [ -z \"$PROJECT_REL\" ] || [ \"$PROJECT_REL\" = \".\" ]; then',\n\t\t' PROJECT_REL=\"$(node - \"$REPO_ROOT\" \"$PROJECT_ROOT\" <<\\'RESOLVEIO_REL\\'',\n\t\t'const path = require(\"path\");',\n\t\t'console.log(path.relative(process.argv[2], process.argv[3]) || \".\");',\n\t\t'RESOLVEIO_REL',\n\t\t' )\"',\n\t\t'fi',\n\t\t'ARTIFACT_DIR=\"$PROJECT_ROOT/qa-artifacts\"',\n\t\t'mkdir -p \"$ARTIFACT_DIR/baseline\" \"$ARTIFACT_DIR/candidate\"',\n\t\t'RESULT_JSON=\"$ARTIFACT_DIR/bugfix-comparison-result.json\"',\n\t\t'CANDIDATE_PATCH=\"$ARTIFACT_DIR/bugfix-candidate.patch\"',\n\t\t'ORIGINAL_HEAD=\"$(git -C \"$REPO_ROOT\" rev-parse HEAD)\"',\n\t\t'ORIGINAL_BRANCH=\"$(git -C \"$REPO_ROOT\" symbolic-ref --short HEAD 2>/dev/null || true)\"',\n\t\t'QA_COMMAND=(\"$@\")',\n\t\t'STOPPER=\"$TOOLS_DIR/stop-local-qa.sh\"',\n\t\t'CURRENT_PHASE=\"\"',\n\t\t'stop_local_qa() {',\n\t\t' \"$STOPPER\" \"$PROJECT_ROOT\" >/dev/null 2>&1 || true',\n\t\t'}',\n\t\t'write_json() {',\n\t\t' node - \"$RESULT_JSON\" \"$@\" <<\\'RESOLVEIO_WRITE_JSON\\'',\n\t\t'const fs = require(\"fs\");',\n\t\t'const [path, status, baselineExit, candidateExit, baselineRef, originalHead, projectRel, note] = process.argv.slice(2);',\n\t\t'const payload = {',\n\t\t' status,',\n\t\t' baseline_ref: baselineRef,',\n\t\t' original_head: originalHead,',\n\t\t' project: projectRel,',\n\t\t' baseline_exit_code: Number(baselineExit),',\n\t\t' candidate_exit_code: Number(candidateExit),',\n\t\t' code_switch_proven: Number(baselineExit) !== 0 && Number(candidateExit) === 0,',\n\t\t' candidate_passed: Number(candidateExit) === 0,',\n\t\t' baseline_failed: Number(baselineExit) !== 0,',\n\t\t' note,',\n\t\t' artifact_dirs: { baseline: \"qa-artifacts/baseline\", candidate: \"qa-artifacts/candidate\" },',\n\t\t' created_at: new Date().toISOString()',\n\t\t'};',\n\t\t'fs.writeFileSync(path, JSON.stringify(payload, null, 2));',\n\t\t'console.log(JSON.stringify(payload, null, 2));',\n\t\t'RESOLVEIO_WRITE_JSON',\n\t\t'}',\n\t\t'snapshot_phase_artifacts() {',\n\t\t' local phase=\"$1\"',\n\t\t' mkdir -p \"$ARTIFACT_DIR/$phase\"',\n\t\t' find \"$ARTIFACT_DIR\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*.json\" -o -name \"*.txt\" -o -name \"*.log\" -o -name \"*.zip\" \\\\) -print0 2>/dev/null | while IFS= read -r -d \"\" file; do',\n\t\t' cp \"$file\" \"$ARTIFACT_DIR/$phase/$(basename \"$file\")\" 2>/dev/null || true',\n\t\t' done',\n\t\t'}',\n\t\t'capture_candidate_patch() {',\n\t\t' : > \"$CANDIDATE_PATCH\"',\n\t\t' git -C \"$REPO_ROOT\" diff --binary -- \"$PROJECT_REL\" >> \"$CANDIDATE_PATCH\" || true',\n\t\t' git -C \"$REPO_ROOT\" diff --binary --cached -- \"$PROJECT_REL\" >> \"$CANDIDATE_PATCH\" || true',\n\t\t'}',\n\t\t'checkout_project_from_ref() {',\n\t\t' local ref=\"$1\"',\n\t\t' git -C \"$REPO_ROOT\" checkout \"$ref\" -- \"$PROJECT_REL\"',\n\t\t'}',\n\t\t'restore_candidate() {',\n\t\t' stop_local_qa',\n\t\t' checkout_project_from_ref \"$ORIGINAL_HEAD\" || true',\n\t\t' if [ -s \"$CANDIDATE_PATCH\" ]; then',\n\t\t' git -C \"$REPO_ROOT\" apply --whitespace=nowarn \"$CANDIDATE_PATCH\" || true',\n\t\t' fi',\n\t\t'}',\n\t\t'trap restore_candidate EXIT',\n\t\t'run_phase() {',\n\t\t' local phase=\"$1\"',\n\t\t' CURRENT_PHASE=\"$phase\"',\n\t\t' stop_local_qa',\n\t\t' export RESOLVEIO_RUNNER_QA_PHASE=\"$phase\"',\n\t\t' export RESOLVEIO_SUPPORT_QA_PHASE=\"$phase\"',\n\t\t' export RESOLVEIO_RUNNER_QA_ARTIFACT_DIR=\"$ARTIFACT_DIR/$phase\"',\n\t\t' export RESOLVEIO_SUPPORT_QA_ARTIFACT_DIR=\"$ARTIFACT_DIR/$phase\"',\n\t\t' mkdir -p \"$ARTIFACT_DIR/$phase\"',\n\t\t' find \"$ARTIFACT_DIR/$phase\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*.json\" -o -name \"*.txt\" -o -name \"*.log\" -o -name \"*.zip\" \\\\) -delete 2>/dev/null || true',\n\t\t' find \"$ARTIFACT_DIR\" -maxdepth 1 -type f \\\\( -name \"*.png\" -o -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.webp\" -o -name \"*proof.json\" -o -name \"auth-bootstrap-result.json\" \\\\) -delete 2>/dev/null || true',\n\t\t' set +e',\n\t\t' (cd \"$REPO_ROOT\" && \"${QA_COMMAND[@]}\") 2>&1 | tee \"$ARTIFACT_DIR/$phase/qa-command.log\"',\n\t\t' local rc=\"${PIPESTATUS[0]}\"',\n\t\t' set +e',\n\t\t' snapshot_phase_artifacts \"$phase\"',\n\t\t' stop_local_qa',\n\t\t' return \"$rc\"',\n\t\t'}',\n\t\t'echo \"ResolveIO bugfix comparison QA preserving candidate diff for $PROJECT_REL\"',\n\t\t'capture_candidate_patch',\n\t\t'stop_local_qa',\n\t\t'echo \"ResolveIO bugfix comparison QA baseline phase: $BASELINE_REF\"',\n\t\t'checkout_project_from_ref \"$BASELINE_REF\"',\n\t\t'run_phase baseline',\n\t\t'BASELINE_EXIT=\"$?\"',\n\t\t'echo \"ResolveIO bugfix comparison QA candidate phase: restored workspace candidate\"',\n\t\t'restore_candidate',\n\t\t'run_phase candidate',\n\t\t'CANDIDATE_EXIT=\"$?\"',\n\t\t'if [ \"$CANDIDATE_EXIT\" = \"0\" ] && [ \"$BASELINE_EXIT\" != \"0\" ]; then',\n\t\t' STATUS=\"pass\"',\n\t\t' NOTE=\"Baseline failed and candidate passed for the same QA command.\"',\n\t\t'elif [ \"$CANDIDATE_EXIT\" = \"0\" ]; then',\n\t\t' STATUS=\"inconclusive_baseline_also_passed\"',\n\t\t' NOTE=\"Candidate passed, but baseline also passed; the code switch did not prove the bug fix.\"',\n\t\t'else',\n\t\t' STATUS=\"fail_candidate_failed\"',\n\t\t' NOTE=\"Candidate failed the QA command.\"',\n\t\t'fi',\n\t\t'write_json \"$STATUS\" \"$BASELINE_EXIT\" \"$CANDIDATE_EXIT\" \"$BASELINE_REF\" \"$ORIGINAL_HEAD\" \"$PROJECT_REL\" \"$NOTE\"',\n\t\t'[ \"$CANDIDATE_EXIT\" = \"0\" ] || exit \"$CANDIDATE_EXIT\"',\n\t\t'[ \"$STATUS\" = \"pass\" ] || exit 8',\n\t\t''\n\t].join('\\n');\n}\n\nexport function buildResolveIORunnerQaToolsReadme(options: ResolveIORunnerQaToolBundleOptions = {}): string {\n\tconst mode = options.mode || 'runner';\n\tconst toolsDir = mode === 'support' ? '.resolveio-support-tools' : '.resolveio-ai-runner-tools';\n\tconst port = normalizePort(options.qaClientPort, '4200');\n\tconst clientUrlVar = envVar(mode, 'CLIENT_URL');\n\tconst keepaliveVar = envVar(mode, 'KEEPALIVE');\n\tconst usernameVar = envVar(mode, 'USERNAME');\n\tconst passwordVar = envVar(mode, 'PASSWORD');\n\treturn [\n\t\t`# ResolveIO ${mode === 'support' ? 'Support' : 'AI Runner'} Local QA Tools`,\n\t\t'',\n\t\t'These scripts are generated by `@resolveio/server-lib` and are shared by support tickets, AICoder app-builder runs, and AI-terminal runs.',\n\t\t'',\n\t\t'```bash',\n\t\t`source ${toolsDir}/env.sh`,\n\t\t`${toolsDir}/run-local-qa.sh <project-root>`,\n\t\t`node ${toolsDir}/qa-auth-bootstrap.js <project-root> /target-route`,\n\t\t`${toolsDir}/bugfix-comparison-qa.sh <project-root> origin/master -- bash -lc '<same QA command>'`,\n\t\t'```',\n\t\t'',\n\t\t`This workspace reserves Angular QA client port ${port}; use \\`$${clientUrlVar}\\` instead of assuming 4200 is free.`,\n\t\t'The local QA runner starts server/client, polls the reserved client URL, writes `qa-artifacts/server.log` and `qa-artifacts/client.log`, and fails fast on fatal startup/runtime errors.',\n\t\t'The shared auth bootstrap calls `/login`, then `/accessToken`, clears service workers/cache/IndexedDB/local storage for the exact localhost client origin, seeds `refreshToken`, `accessToken`, `user`, and `lastURL`, and writes `qa-artifacts/auth-bootstrap-result.json` plus a ready/failure screenshot.',\n\t\t`For browser clickthrough work, start the runner once with \\`${keepaliveVar}=true ${toolsDir}/run-local-qa.sh <project-root> &\\` and reuse \\`$${clientUrlVar}\\` for all login/upload/screenshot retries. Do not restart Angular for auth failures.`,\n\t\t'Use desktop screenshots at 1920x1080 by default unless the task is explicitly mobile/responsive. Every screenshot must have a customer-facing caption.',\n\t\t'For import/export/form-submit/data workflows, prove before/action/after with representative data and a concrete row/count/value assertion.',\n\t\t'For bug fixes, use `bugfix-comparison-qa.sh` so baseline/master runs the exact same repro before the candidate/PR run. A passing candidate is not enough unless the comparison result shows baseline failed or the report explicitly explains why the baseline failure could not be reproduced.',\n\t\t`Use \\`$${usernameVar}\\` and \\`$${passwordVar}\\` for the local fixture admin account unless ticket/app-specific credentials are provided.`,\n\t\t'The env file reuses `/var/lib/resolveio/puppeteer`, npm cache, worker-safe Browserslist settings, and Angular cache prep so QA should not download a browser or rebuild cold caches unnecessarily.',\n\t\tmode === 'support'\n\t\t\t? 'Support workspaces also stage local `mongod` and `mongosh` wrappers so app server scripts can start MongoDB when the worker image does not have MongoDB installed.'\n\t\t\t: '',\n\t\t''\n\t].filter((line) => line !== '').join('\\n');\n}\n"]}
|